barnowl-1.10/0000755000175000017500000000000013055170372010103 500000000000000barnowl-1.10/owl.c0000644000175000017500000004554213020626370010776 00000000000000/* Copyright (c) 2006-2011 The BarnOwl Developers. All rights reserved. * Copyright (c) 2004 James Kretchmar. All rights reserved. * * This program is free software. You can redistribute it and/or * modify under the terms of the Sleepycat License. See the COPYING * file included with the distribution for more information. */ #include "owl.h" #include #include #include #include #include #if OWL_STDERR_REDIR #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #endif int stderr_replace(void); #endif owl_global g; typedef struct _owl_options { bool load_initial_subs; char *configfile; char *tty; char *confdir; bool debug; } owl_options; void usage(FILE *file) { fprintf(file, "BarnOwl version %s\n", version); fprintf(file, "Usage: barnowl [-n] [-d] [-D] [-v] [-h] [-c ] [-s ] [-t ]\n"); fprintf(file, " -n,--no-subs don't load zephyr subscriptions\n"); fprintf(file, " -d,--debug enable debugging\n"); fprintf(file, " -v,--version print the BarnOwl version number and exit\n"); fprintf(file, " -h,--help print this help message\n"); fprintf(file, " -s,--config-dir specify an alternate config dir (default ~/.owl)\n"); fprintf(file, " -c,--config-file specify an alternate config file (default ~/.owl/init.pl)\n"); fprintf(file, " -t,--tty set the tty name\n"); } /* TODO: free owl_options after init is done? */ void owl_parse_options(int argc, char *argv[], owl_options *opts) { static const struct option long_options[] = { { "no-subs", 0, 0, 'n' }, { "config-file", 1, 0, 'c' }, { "config-dir", 1, 0, 's' }, { "tty", 1, 0, 't' }, { "debug", 0, 0, 'd' }, { "version", 0, 0, 'v' }, { "help", 0, 0, 'h' }, { NULL, 0, NULL, 0} }; char c; while((c = getopt_long(argc, argv, "nc:t:s:dDvh", long_options, NULL)) != -1) { switch(c) { case 'n': opts->load_initial_subs = 0; break; case 'c': opts->configfile = g_strdup(optarg); break; case 's': opts->confdir = g_strdup(optarg); break; case 't': opts->tty = g_strdup(optarg); break; case 'd': opts->debug = 1; break; case 'v': printf("This is BarnOwl version %s\n", version); exit(0); case 'h': usage(stdout); exit(0); default: usage(stderr); exit(1); } } } void owl_start_color(void) { start_color(); #ifdef HAVE_USE_DEFAULT_COLORS use_default_colors(); #endif /* define simple color pairs */ if (has_colors() && COLOR_PAIRS>=8) { int bg = COLOR_BLACK; #ifdef HAVE_USE_DEFAULT_COLORS bg = -1; #endif init_pair(OWL_COLOR_BLACK, COLOR_BLACK, bg); init_pair(OWL_COLOR_RED, COLOR_RED, bg); init_pair(OWL_COLOR_GREEN, COLOR_GREEN, bg); init_pair(OWL_COLOR_YELLOW, COLOR_YELLOW, bg); init_pair(OWL_COLOR_BLUE, COLOR_BLUE, bg); init_pair(OWL_COLOR_MAGENTA, COLOR_MAGENTA, bg); init_pair(OWL_COLOR_CYAN, COLOR_CYAN, bg); init_pair(OWL_COLOR_WHITE, COLOR_WHITE, bg); } } void owl_start_curses(void) { struct termios tio; /* save initial terminal settings */ tcgetattr(STDIN_FILENO, owl_global_get_startup_tio(&g)); tcgetattr(STDIN_FILENO, &tio); tio.c_iflag &= ~(ISTRIP|IEXTEN); tio.c_cc[VQUIT] = fpathconf(STDIN_FILENO, _PC_VDISABLE); tio.c_cc[VSUSP] = fpathconf(STDIN_FILENO, _PC_VDISABLE); tio.c_cc[VSTART] = fpathconf(STDIN_FILENO, _PC_VDISABLE); tio.c_cc[VSTOP] = fpathconf(STDIN_FILENO, _PC_VDISABLE); tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); /* screen init */ initscr(); cbreak(); noecho(); owl_start_color(); } void owl_shutdown_curses(void) { endwin(); /* restore terminal settings */ tcsetattr(STDIN_FILENO, TCSAFLUSH, owl_global_get_startup_tio(&g)); } /* * Process a new message passed to us on the message queue from some * protocol. This includes adding it to the message list, updating the * view and scrolling if appropriate, logging it, and so on. * * Either a pointer is kept to the message internally, or it is freed * if unneeded. The caller no longer ``owns'' the message's memory. * * Returns 1 if the message was added to the message list, and 0 if it * was ignored due to user settings or otherwise. */ static int owl_process_message(owl_message *m) { const owl_filter *f; /* if this message it on the puntlist, nuke it and continue */ if (owl_global_message_is_puntable(&g, m)) { owl_message_delete(m); return 0; } /* login or logout that should be ignored? */ if (owl_global_is_ignorelogins(&g) && owl_message_is_loginout(m)) { owl_message_delete(m); return 0; } if (!owl_global_is_displayoutgoing(&g) && owl_message_is_direction_out(m)) { owl_message_delete(m); return 0; } /* add it to the global list */ owl_messagelist_append_element(owl_global_get_msglist(&g), m); /* add it to any necessary views; right now there's only the current view */ owl_view_consider_message(owl_global_get_current_view(&g), m); if(owl_message_is_direction_in(m)) { /* let perl know about it*/ owl_perlconfig_getmsg(m, NULL); /* do we need to autoreply? */ if (owl_global_is_zaway(&g) && !owl_message_get_attribute_value(m, "isauto")) { if (owl_message_is_type_zephyr(m)) { owl_zephyr_zaway(m); } else if (owl_message_is_type_aim(m)) { if (owl_message_is_private(m)) { owl_function_send_aimawymsg(owl_message_get_sender(m), owl_global_get_zaway_msg(&g)); } } } /* ring the bell if it's a personal */ if (!strcmp(owl_global_get_personalbell(&g), "on")) { if (!owl_message_is_loginout(m) && !owl_message_is_mail(m) && owl_message_is_personal(m)) { owl_function_beep(); } } else if (!strcmp(owl_global_get_personalbell(&g), "off")) { /* do nothing */ } else { f=owl_global_get_filter(&g, owl_global_get_personalbell(&g)); if (f && owl_filter_message_match(f, m)) { owl_function_beep(); } } /* if it matches the alert filter, do the alert action */ f=owl_global_get_filter(&g, owl_global_get_alert_filter(&g)); if (f && owl_filter_message_match(f, m)) { owl_function_command_norv(owl_global_get_alert_action(&g)); } /* if it's a zephyr login or logout, update the zbuddylist */ if (owl_message_is_type_zephyr(m) && owl_message_is_loginout(m)) { if (owl_message_is_login(m)) { owl_zbuddylist_adduser(owl_global_get_zephyr_buddylist(&g), owl_message_get_sender(m)); } else if (owl_message_is_logout(m)) { owl_zbuddylist_deluser(owl_global_get_zephyr_buddylist(&g), owl_message_get_sender(m)); } else { owl_function_error("Internal error: received login notice that is neither login nor logout"); } } } /* let perl know about it */ owl_perlconfig_newmsg(m, NULL); /* log the message if we need to */ owl_log_message(m); /* redraw the sepbar; TODO: don't violate layering */ owl_global_sepbar_dirty(&g); return 1; } static gboolean owl_process_messages_prepare(GSource *source, int *timeout) { *timeout = -1; return owl_global_messagequeue_pending(&g); } static gboolean owl_process_messages_check(GSource *source) { return owl_global_messagequeue_pending(&g); } /* * Process any new messages we have waiting in the message queue. */ static gboolean owl_process_messages_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { int newmsgs=0; int followlast = owl_global_should_followlast(&g); owl_message *m; /* Grab incoming messages. */ while (owl_global_messagequeue_pending(&g)) { m = owl_global_messagequeue_popmsg(&g); if (owl_process_message(m)) newmsgs = 1; } if (newmsgs) { /* follow the last message if we're supposed to */ if (followlast) owl_function_lastmsg(); /* do the newmsgproc thing */ owl_function_do_newmsgproc(); /* redisplay if necessary */ /* this should be optimized to not run if the new messages won't be displayed */ owl_mainwin_redisplay(owl_global_get_mainwin(&g)); } return TRUE; } static GSourceFuncs owl_process_messages_funcs = { owl_process_messages_prepare, owl_process_messages_check, owl_process_messages_dispatch, NULL }; void owl_process_input_char(owl_input j) { int ret; owl_global_set_lastinputtime(&g, time(NULL)); owl_global_wakeup(&g); ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j); if (ret!=0 && ret!=1) { owl_function_makemsg("Unable to handle keypress"); } } gboolean owl_process_input(GIOChannel *source, GIOCondition condition, void *data) { owl_global *g = data; owl_input j; while (1) { j.ch = wgetch(g->input_pad); if (j.ch == ERR) return TRUE; j.uch = '\0'; if (j.ch >= KEY_MIN && j.ch <= KEY_MAX) { /* This is a curses control character. */ } else if (j.ch > 0x7f && j.ch < 0xfe) { /* Pull in a full utf-8 character. */ int bytes, i; char utf8buf[7]; memset(utf8buf, '\0', 7); utf8buf[0] = j.ch; if ((j.ch & 0xc0) && (~j.ch & 0x20)) bytes = 2; else if ((j.ch & 0xe0) && (~j.ch & 0x10)) bytes = 3; else if ((j.ch & 0xf0) && (~j.ch & 0x08)) bytes = 4; else if ((j.ch & 0xf8) && (~j.ch & 0x04)) bytes = 5; else if ((j.ch & 0xfc) && (~j.ch & 0x02)) bytes = 6; else bytes = 1; for (i = 1; i < bytes; i++) { int tmp = wgetch(g->input_pad); /* If what we got was not a byte, or not a continuation byte */ if (tmp > 0xff || !(tmp & 0x80 && ~tmp & 0x40)) { /* ill-formed UTF-8 code unit subsequence, put back the char we just got. */ ungetch(tmp); j.ch = ERR; break; } utf8buf[i] = tmp; } if (j.ch != ERR) { if (g_utf8_validate(utf8buf, -1, NULL)) { j.uch = g_utf8_get_char(utf8buf); } else { j.ch = ERR; } } } else if (j.ch <= 0x7f) { j.uch = j.ch; } owl_process_input_char(j); } return TRUE; } static void sig_handler_main_thread(void *data) { int sig = GPOINTER_TO_INT(data); owl_function_debugmsg("Got signal %d", sig); if (sig == SIGWINCH) { owl_function_resize(); } else if (sig == SIGTERM || sig == SIGHUP) { owl_function_quit(); } else if (sig == SIGINT && owl_global_take_interrupt(&g)) { owl_input in; in.ch = in.uch = owl_global_get_startup_tio(&g)->c_cc[VINTR]; owl_process_input_char(in); } } static void sig_handler(const siginfo_t *siginfo, void *data) { /* If it was an interrupt, set a flag so we can handle it earlier if * needbe. sig_handler_main_thread will check the flag to make sure * no one else took it. */ if (siginfo->si_signo == SIGINT) { owl_global_add_interrupt(&g); } /* Send a message to the main thread. */ owl_select_post_task(sig_handler_main_thread, GINT_TO_POINTER(siginfo->si_signo), NULL, g_main_context_default()); } #define OR_DIE(s, syscall) \ G_STMT_START { \ if ((syscall) == -1) { \ perror((s)); \ exit(1); \ } \ } G_STMT_END void owl_register_signal_handlers(void) { struct sigaction sig_ignore = { .sa_handler = SIG_IGN }; struct sigaction sig_default = { .sa_handler = SIG_DFL }; sigset_t sigset; int ret, i; const int reset_signals[] = { SIGABRT, SIGBUS, SIGCHLD, SIGFPE, SIGILL, SIGQUIT, SIGSEGV, }; /* Don't bother resetting watched ones because owl_signal_init will. */ const int watch_signals[] = { SIGWINCH, SIGTERM, SIGHUP, SIGINT, }; /* Sanitize our signals; the mask and dispositions from our parent * aren't really useful. Signal list taken from equivalent code in * Chromium. */ OR_DIE("sigemptyset", sigemptyset(&sigset)); if ((ret = pthread_sigmask(SIG_SETMASK, &sigset, NULL)) != 0) { errno = ret; perror("pthread_sigmask"); exit(1); } for (i = 0; i < G_N_ELEMENTS(reset_signals); i++) { OR_DIE("sigaction", sigaction(reset_signals[i], &sig_default, NULL)); } /* Turn off SIGPIPE; we check the return value of write. */ OR_DIE("sigaction", sigaction(SIGPIPE, &sig_ignore, NULL)); /* Register some signals with the signal thread. */ owl_signal_init(watch_signals, G_N_ELEMENTS(watch_signals), sig_handler, NULL); } #if OWL_STDERR_REDIR /* Replaces stderr with a pipe so that we can read from it. * Returns the fd of the pipe from which stderr can be read. */ int stderr_replace(void) { int pipefds[2]; if (0 != pipe(pipefds)) { perror("pipe"); owl_function_debugmsg("stderr_replace: pipe FAILED"); return -1; } owl_function_debugmsg("stderr_replace: pipe: %d,%d", pipefds[0], pipefds[1]); if (-1 == dup2(pipefds[1], STDERR_FILENO)) { owl_function_debugmsg("stderr_replace: dup2 FAILED (%s)", strerror(errno)); perror("dup2"); return -1; } return pipefds[0]; } /* Sends stderr (read from rfd) messages to the error console */ gboolean stderr_redirect_handler(GIOChannel *source, GIOCondition condition, void *data) { int navail, bread; char buf[4096]; int rfd = g_io_channel_unix_get_fd(source); char *err; /* TODO: Use g_io_channel_read_line? We'd have to be careful about * blocking on the read. */ if (rfd<0) return TRUE; if (-1 == ioctl(rfd, FIONREAD, &navail)) { return TRUE; } /*owl_function_debugmsg("stderr_redirect: navail = %d\n", navail);*/ if (navail <= 0) return TRUE; if (navail > sizeof(buf)-1) { navail = sizeof(buf)-1; } bread = read(rfd, buf, navail); if (bread == -1) return TRUE; err = g_strdup_printf("[stderr]\n%.*s", bread, buf); owl_function_log_err(err); g_free(err); return TRUE; } #endif /* OWL_STDERR_REDIR */ int main(int argc, char **argv, char **env) { int argc_copy; char **argv_copy; char *perlout, *perlerr; const owl_style *s; const char *dir; owl_options opts; GSource *source; GIOChannel *channel; argc_copy = argc; argv_copy = g_strdupv(argv); setlocale(LC_ALL, ""); memset(&opts, 0, sizeof opts); opts.load_initial_subs = 1; owl_parse_options(argc, argv, &opts); g.load_initial_subs = opts.load_initial_subs; owl_start_curses(); /* owl global init */ owl_global_init(&g); if (opts.debug) owl_global_set_debug_on(&g); if (opts.confdir) owl_global_set_confdir(&g, opts.confdir); owl_function_debugmsg("startup: first available debugging message"); owl_global_set_startupargs(&g, argc_copy, argv_copy); g_strfreev(argv_copy); owl_global_set_haveaim(&g); owl_register_signal_handlers(); /* register STDIN dispatch; throw away return, we won't need it */ channel = g_io_channel_unix_new(STDIN_FILENO); g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR, &owl_process_input, &g); g_io_channel_unref(channel); owl_zephyr_initialize(); #if OWL_STDERR_REDIR /* Do this only after we've started curses up... */ if (isatty(STDERR_FILENO)) { owl_function_debugmsg("startup: doing stderr redirection"); channel = g_io_channel_unix_new(stderr_replace()); g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR, &stderr_redirect_handler, NULL); g_io_channel_unref(channel); } #endif /* create the owl directory, in case it does not exist */ owl_function_debugmsg("startup: creating owl directory, if not present"); dir=owl_global_get_confdir(&g); mkdir(dir, S_IRWXU); /* set the tty, either from the command line, or by figuring it out */ owl_function_debugmsg("startup: setting tty name"); if (opts.tty) { owl_global_set_tty(&g, opts.tty); } else { char *tty = owl_util_get_default_tty(); owl_global_set_tty(&g, tty); g_free(tty); } /* Initialize perl */ owl_function_debugmsg("startup: processing config file"); owl_global_pop_context(&g); owl_global_push_context(&g, OWL_CTX_READCONFIG, NULL, NULL, NULL); perlerr=owl_perlconfig_initperl(opts.configfile, &argc, &argv, &env); if (perlerr) { endwin(); fprintf(stderr, "Internal perl error: %s\n", perlerr); fflush(stderr); printf("Internal perl error: %s\n", perlerr); fflush(stdout); exit(1); } owl_global_complete_setup(&g); owl_global_setup_default_filters(&g); /* set the current view */ owl_function_debugmsg("startup: setting the current view"); owl_view_create(owl_global_get_current_view(&g), "main", owl_global_get_filter(&g, "all"), owl_global_get_style_by_name(&g, "default")); /* AIM init */ owl_function_debugmsg("startup: doing AIM initialization"); owl_aim_init(); /* execute the startup function in the configfile */ owl_function_debugmsg("startup: executing perl startup, if applicable"); perlout = owl_perlconfig_execute("BarnOwl::Hooks::_startup();"); g_free(perlout); /* welcome message */ owl_function_debugmsg("startup: creating splash message"); char *welcome = g_strdup_printf( "-----------------------------------------------------------------------\n" "Welcome to BarnOwl version %s.\n" "To see a quick introduction, type ':show quickstart'. \n" "Press 'h' for on-line help. \n" " \n" "BarnOwl is free software. Type ':show license' for more \n" "information. ^ ^ \n" " OvO \n" "Please report any bugs or suggestions to bug-barnowl@mit.edu ( ) \n" "-----------------------------------------------------------------m-m---\n", version); owl_function_adminmsg("", welcome); g_free(welcome); owl_function_debugmsg("startup: setting context interactive"); owl_global_pop_context(&g); owl_global_push_context(&g, OWL_CTX_INTERACTIVE|OWL_CTX_RECV, NULL, "recv", NULL); /* process the startup file */ owl_function_debugmsg("startup: processing startup file"); owl_function_source(NULL); owl_function_debugmsg("startup: set style for the view: %s", owl_global_get_default_style(&g)); s = owl_global_get_style_by_name(&g, owl_global_get_default_style(&g)); if(s) owl_view_set_style(owl_global_get_current_view(&g), s); else owl_function_error("No such style: %s", owl_global_get_default_style(&g)); source = owl_window_redraw_source_new(); g_source_attach(source, NULL); g_source_unref(source); source = g_source_new(&owl_process_messages_funcs, sizeof(GSource)); g_source_attach(source, NULL); g_source_unref(source); owl_log_init(); owl_function_debugmsg("startup: entering main loop"); owl_select_run_loop(); /* Shut down everything. */ owl_zephyr_shutdown(); owl_signal_shutdown(); owl_shutdown_curses(); owl_log_shutdown(); return 0; } barnowl-1.10/compile0000755000175000017500000001624513020637074011410 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: barnowl-1.10/runtests.sh0000755000175000017500000000016613020626370012250 00000000000000#!/bin/sh export G_SLICE=debug-blocks exec env HARNESS_PERL=./tester prove --failures "${srcdir:=$(dirname "$0")}/t/" barnowl-1.10/depcomp0000755000175000017500000005601613020637074011407 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: barnowl-1.10/messagelist.c0000644000175000017500000000601013020626370012500 00000000000000#include "owl.h" CALLER_OWN owl_messagelist *owl_messagelist_new(void) { owl_messagelist *ml = g_slice_new(owl_messagelist); ml->list = g_ptr_array_new(); return ml; } void owl_messagelist_delete(owl_messagelist *ml, bool free_messages) { if (free_messages) g_ptr_array_foreach(ml->list, (GFunc)owl_message_delete, NULL); g_ptr_array_free(ml->list, true); g_slice_free(owl_messagelist, ml); } int owl_messagelist_get_size(const owl_messagelist *ml) { return ml->list->len; } void *owl_messagelist_get_element(const owl_messagelist *ml, int n) { /* we assume things like owl_view_get_element(v, owl_global_get_curmsg(&g)) * work even when there are no messages in the message list. So don't * segfault if someone asks for the zeroth element of an empty list. */ if (n >= ml->list->len) return NULL; return ml->list->pdata[n]; } int owl_messagelist_get_index_by_id(const owl_messagelist *ml, int target_id) { /* return the message index with id == 'id'. If it doesn't exist return -1. */ int first, last, mid, msg_id; owl_message *m; first = 0; last = ml->list->len - 1; while (first <= last) { mid = (first + last) / 2; m = ml->list->pdata[mid]; msg_id = owl_message_get_id(m); if (msg_id == target_id) { return mid; } else if (msg_id < target_id) { first = mid + 1; } else { last = mid - 1; } } return -1; } owl_message *owl_messagelist_get_by_id(const owl_messagelist *ml, int target_id) { /* return the message with id == 'id'. If it doesn't exist return NULL. */ int n = owl_messagelist_get_index_by_id(ml, target_id); if (n < 0) return NULL; return ml->list->pdata[n]; } void owl_messagelist_append_element(owl_messagelist *ml, void *element) { g_ptr_array_add(ml->list, element); } /* do we really still want this? */ int owl_messagelist_delete_element(owl_messagelist *ml, int n) { /* mark a message as deleted */ owl_message_mark_delete(ml->list->pdata[n]); return(0); } int owl_messagelist_undelete_element(owl_messagelist *ml, int n) { /* mark a message as deleted */ owl_message_unmark_delete(ml->list->pdata[n]); return(0); } void owl_messagelist_delete_and_expunge_element(owl_messagelist *ml, int n) { owl_message_delete(g_ptr_array_remove_index(ml->list, n)); } int owl_messagelist_expunge(owl_messagelist *ml) { /* expunge deleted messages */ int i; GPtrArray *newlist; owl_message *m; newlist = g_ptr_array_new(); /*create a new list without messages marked as deleted */ for (i = 0; i < ml->list->len; i++) { m = ml->list->pdata[i]; if (owl_message_is_delete(m)) { owl_message_delete(m); } else { g_ptr_array_add(newlist, m); } } /* free the old list */ g_ptr_array_free(ml->list, true); /* copy the new list to the old list */ ml->list = newlist; return(0); } void owl_messagelist_invalidate_formats(const owl_messagelist *ml) { int i; owl_message *m; for (i = 0; i < ml->list->len; i++) { m = ml->list->pdata[i]; owl_message_invalidate_format(m); } } barnowl-1.10/autogen.sh0000755000175000017500000000003313020626370012014 00000000000000#!/bin/sh autoreconf -fvi barnowl-1.10/cpanfile0000644000175000017500000000107113020626370011522 00000000000000requires 'AnyEvent'; requires 'Class::Accessor'; requires 'ExtUtils::Depends'; requires 'Glib'; requires 'Module::Install'; requires 'Net::Twitter::Lite'; requires 'PAR'; # feature 'facebook', 'Facebook support' => sub { requires 'Any::Moose', '>= 0.13'; requires 'AnyEvent::HTTP'; requires 'DateTime', '>= 0.61'; requires 'DateTime::Format::Strptime', '>= 1.4000'; requires 'JSON', '>= 2.16'; requires 'Lingua::EN::Keywords'; requires 'MIME::Base64::URLSafe', '>= 0.01'; requires 'Ouch', '>= 0.0400'; requires 'URI', '>= 1.54'; requires 'URI::Encode', '>= 0.02'; # } barnowl-1.10/doc/0000755000175000017500000000000013055170372010650 500000000000000barnowl-1.10/doc/owl-window.txt0000644000175000017500000002022513020626370013434 00000000000000 ========== owl_window ========== owl_window is intended to be a wrapper over ncurses WINDOW and PANEL objects to abstract away much of the nastiness that is ncurses. It provides redraw scheduling, and sane window moving and resizing. ------------------- Hierarchy and types ------------------- owl_window creates a hierarchy of window objects. The hierarchy currently uses ncurses' built-in window hierarchy system with subwins. This was easier to implement but has some caveats, detailed later. At the top level, we have the screen window which represents the actual screen. The screen window is not usually interacted with directly, but rather it is a handle to interface with the terminal as if it were a normal window. Underneath the screen, we have top-level windows, or panels. Panels are normal WINDOWs (newwin) connected to a PANEL (from libpanel). Panels may overlap freely and maintain a stacking order. (For now, this stacking order is not exposed except for a mechanism to move a panel to the top. This is not difficult to otherwise correct otherwise.) Under each panel is a tree of subwins. These are backed by ncurses subwins. Because ncurses subwins simply share their parent windows' buffer, we cannot provide as many nice guarantees about ordering. Sibling subwins may not overlap, and parents must (sometimes) take children position into account. More on this later. This model is sufficient for BarnOwl's current purposes. Should we need to, this may later be reworked. (Specifically, we'd want to back everything by pads and build a compositing window manager.) Each of these three types is temporarily stuffed into one type. We can later do subtyping of sorts, but that will require more heavy use of GObject. As an example, here is the graph used by BarnOwl's current interface: +==========+ || screen || +==========+ / \ +-----------+ +--------+ | mainpanel | | popwin | +-----------+ +--------+ / / | \ \ recwin sepwin msgwin typwin viewwin A window may be unlinked from its parent with a call to owl_window_unlink. From then on, the object is still accessible, but it will not do anything. If desired, we may add the ability to relink a window in future. This behavior allows us to safely hold references to windows, even after they have been "destroyed". ---------- Visibility ---------- Each window maintains state for whether or not the user has requested it be visible. A user calls owl_window_show to flip the 'shown' bit on a window and owl_window_show_all to do so recursively. Likewise, owl_window_hide disables this bit. If a window and all its parents are shown, then the user has requested this window be visible. We say a window is realized if it has a corresponding on-screen window. A window will only be realized if it is requested to be shown. Furthermore, the window's parent must also be realized (unless it is the screen). If a window is failed to be created for any reason (most notably if its dimensions are zero), owl_window will cope and consider it unrealized. This realized/unrealized state fixes two nuisances with the old code: First, owl_window can safely manage all NULL windows. Interacting code needn't check to avoid segfaults; the owl_window is never NULL, and code requesting the WINDOW will never be called when NULL. Second, we have a consistent handle to a logical window, despite changes in the physical window. This is important for resizing windows. It is difficult to safely resize windows in ncurses. It is usually far easier to destroy everything and recreate it. Note that this means owl_window will intentionally never expose the underlying WINDOW except during appropriate events. -------- Resizing -------- Windows may be moved and resized with owl_window_move, owl_window_resize, and owl_window_set_position. Internally, resizing is very simple. We unrealize the window, set new position, and then realize it at the new location. When a window changes size, it emits a "resized" signal which windows may react to. It may actually possible to optimize moves, but this has a slight nuisance with incorrect begy/begx values which cursors currently rely on. It is intended that top-level windows connect to this signal to change themselves, while windows containing subwins connect to their own signals to relayout their subwins. This is because top-level windows may be sized independently, while sibling subwins should not overlap. The signals are implemented currently with GObject signals. --------- Redrawing --------- Currently, users of widgets in BarnOwl must remember to call owl_foo_redisplay when a widget needs to be redrawn. This is quite annoying and an implementation detail that functions like owl_editwin_insert_string should take care of. To allow widget implementations to redraw themselves without calling an expensive redisplay many times, owl_window_dirty flags a window as "dirty". The framework will promise to redraw that window before the next doupdate, while repeated owl_window_dirty calls remain cheap. Windows currently redraw with a "redraw" GObject signal. This and the resize signal, is somewhat awkward for the editwin which attaches to and releases windows, as we must remember signal ids. However, if we make widget objects (owl_editwin, owl_mainwin, etc.) also GObjects, these signals will automatically detach. We may also consider a different mechanism than continuously attaching/detaching things. That's kinda weird anyway. (We may want to replace it with a normal callback at some point. Mostly using the GObject signals to play with them, and because we'd likely get some form of automatic binding generation.) ---------------------- Known issues and notes ---------------------- - owl_window does not export the underlying WINDOW*. This is intentional. To safely resize windows, owl_window reserves the right to destroy/recreate the window whenever it feels like. We can add "window-realized"/"window-unrealized" signals if people really want though. - This is currently using GObject. This buys us a lot of niceness, but it is adding a new library with full-blown (and somewhat overengineered) object system. It's very useful for prototyping, but if people want, it can be replaced. I think it's actually worthwhile, as most of the overengineering is explicitly designed for language bindings, something we could be better at. - There is this really sketchy "three types in one" thing going on with the screen, panels, and subwins. I'd like to refactor that into some sort of subtyping, but that would ideally involve even more use of GObject. - owl_mainwin is not very well ported and the windows do not have a very consistent implementation. This is a known problem that will be addressed in the next iteration. The current ports were done partly as experiments for conventions and mostly to get something working as soon as possible. Among things that should change is for the widgets to all use new/delete/pointers instead of init/cleanup/embed-in-struct. - The editwin and a few others are strange and keep track of signal ids. This is somewhat a side effect of us not using GObject everywhere; the signals can automatically disconnect in the right contexts if we do. - The sepbar depends on a value computed while the mainwin is drawn, so we currently ensure the windows are created in the right order for the repaints to occur correctly. This is rather poor and should be refactored later. - The code fairly routinely does casts to add extra throw-away parameters to functions. Most notably, casting functions of type void do_something(void *obj) to something of type void do_something(void *obj, void *user_data) (the latter is a GFunc) with the expectation that the user_data argument is discarded. While calling with this cast is undefined by the standard and depends on calling convention, glib uses it internally /everywhere/ and much of glib and gobject API heavily depends on it. As BarnOwl already depends on glib, we implicitly assume this cast works. barnowl-1.10/doc/barnowl.10000644000175000017500000000447313020626370012322 00000000000000.TH BARNOWL 1 "24 Jun 2011" .SH NAME BarnOwl \- tty\(hybased zephyr client .SH SYNOPSIS .B barnowl [\-n] [\-d] [\-D] [\-v] [\-h] [\-c \fICONFIGFILE\fP] [\-t \fITTY\fP] [\-s \fICONFIGDIR\fP] .br .SH DESCRIPTION .B BarnOwl is a fully integrated tty\(hybased instant messaging client. Currently it supports AOL Instant Messenger, MIT Zephyr, Jabber, IRC, and Twitter. It is curses\(hybased, allows for emacs\(hystyle editing of outgoing messages, and uses Perl as an extension and configuration language. \fBBarnOwl\fP will also run happily without a configuration file. Once \fBBarnOwl\fP is started, typing \(oqh\(cq will display a help screen. Typing \(oq:\(cq enters command mode, allowing the user to type a \fBBarnOwl\fP command line. .SH OPTIONS The following command\-line options are avilable when running \fBBarnOwl\fP: .TP \fB\-n\fP, \fB\-\-no\-subs\fP Do not subscribe to zephyr messages on startup. By default, \fBBarnOwl\fP subscribes to the default subscriptions and to anything found in \fI~/.zephyr.subs\fP. When this option is used, no subscriptions are loaded. .TP \fB\-c\fP, \fB\-\-config\-file\fP=\fIFILE\fP Specify an alternate config file for \fBBarnOwl\fP to use. The config file is an arbitrary Perl script evaluated in the \fImain\fP package, and if it overrides the \fIBarnOwl::startup\fP method that is run when \fBBarnOwl\fP starts. (Compare \fI~/.owl/startup\fP, which contains \fBBarnOwl\fP commands that are run at startup after the config file is loaded.) By default, \fBBarnOwl\fP uses the first of \fI~/.owl/init.pl\fP, \fI~/.barnowlconf\fP, or \fI~/.owlconf\fP that exists. .TP \fB\-s\fP, \fB\-\-config\-dir\fP=\fIDIR\fP Specify an alternate configuration directory. By default, \fBBarnOwl\fP uses \fI~/.owl/\fP. .TP \fB\-t\fP, \fB\-\-tty\fP=\fITTY\fP Specify the tty name to use for the zephyr location. .TP \fB\-v\fP, \fB\-\-version\fP Print the version number of \fBBarnOwl\fP and exit. .TP \fB\-d\fP, \fB\-\-debug\fP Enable debugging. By default, debugging information is placed in \fI/var/tmp/barnowl\-debug.PID\fP. .TP \fB\-h\fP, \fB\-\-help\fP Print command\(hyline option help. .SH AUTHORS Written by Nelson Elhage and Alejandro Sedeno at the Massachusetts Institute of Technology. Based on Owl by James Kretchmar. Comments, questions, and bug reports may be mailed to \fBbug\-barnowl@mit.edu\fP. barnowl-1.10/doc/code.txt0000644000175000017500000001662713020626370012253 00000000000000TYPES / CLASSES / SOURCE FILES ------------------------------ cmd: Underlying implementation of command table management and command dispatching. Also handles the implementation of command aliases. commands: Dispatching for commands and handling of their arguments. (Commands are the interface exported to the user.) Many commands tend to be backed by functions. In general, a command takes a string as an argument and optionally returns a string. At the top of the file is a table mapping command names and help to functions implementing them. The standard entrypoint for executing a command is owl_function_command("foo"); Commands are only active within specific contexts, and attempts to call them from invalid contexts will fail. context: A context specifies the current state of owl, in terms of which modal window is active and which point in its life owl is in (eg, in startup, or running). This is implemented as a bitmask and there is some hierarchy. Commands may restrict themselves to only running in a limited number of contexts to prevent commands from being executed at points when they not make sense. Also, the data from the active context (eg, a pointer to an active window) may be passed to a command. dict: Simple dictionary abstraction mapping from strings to pointers. editwin: Text editing window (both multiline and single line). Sometimes also referred to as typewin. filter: Patterns which match messages. These may contain multiple filterelements which may be combined together (eg, by "and" and "or"). filterelement: An element of a filter which matches on some attribute of a message. fmtext: Formatted text routines (handles things like @i{foo}). These are particularly useful for building up text regions that are to be rendered on-screen, as they resize memory as needed, and they have routines for cropping as needed. functions: Where most features are implemented. Users should always interact with functions through commands. In general, functions are abstract entrypoints into the system and attempt to hide access to global state. global: Global state and variables and toplevel objects. owl.h defines "g" as a singleton instance of owl_global. Where possible/appropriate, most accesses to global data should be from a limited number of files (eg, from owl.c and functions.c). Consider whether you really need to before adding in uses of global. help: Help strings for commands and key bindings. Most of this is now in keys.c, commands.c, and variables.c, along with the definition of commands and keybindings. keys: Default key binding definitions for all keymaps. This also includes default actions for keymaps. keybinding: Binding between a sequence of keypresses and a command. When executed, this executes the commands. The sequence of keypresses is kept as a stack. Keybindings are a part of keymaps. keypress: Utility routines for translating between keypress values and and human-readable key names. keymap: Contains both keymap and keyhandler. A keymap is contains a list of keybindings, a sub-keymap, and optionally a default handler function. The sub-keymap is a more general keymap which is consulted if the specific keymap doesn't contain a match. (For example, the "global" keymap is the ancestor of all other keymaps.) The keyhandler is a collection of keymaps which handles checking for key matches within keymaps. It maintains a stack of keypresses and compares them against the bindings in keymaps. It also handles ESC as a prefix for Meta. At any one time, there is exactly one active keymap which determines where keybindings are looked for (along with its parents). list: Simple list abstraction. (Uses realloc to resize the list.) logging: Interface to incoming / outgoing zephyr logging. mainwin: Window that displays the list of messages. (Sometimes also referred to as recwin.) message: Abstraction to messages. Currently, messages are either of type zephyr or of type admin. messagelist: List of messages. owl.c: main() and signal handlers and other initial setup. Also contains the main loop, which is roughly: - handle scheduled resizes, and anything that might result - while zephyrs are pending, grab incoming zephyrs and handle them (which includes formatting them with either perl extension or default formatter as part of owl_message_create_from_zephyr). - updates mainwin display if there are new zephyrs - displays and updates popwins and the terminal as necessary - sends characters to the popwin, recwin/mainwin, or typewin/editwin owl.h: Prototypes for all types, as well as global constants. owl_prototypes.h: Autogenerated prototypes for all functions. Created by codelist.pl. popwin: Modal pop-up window container. Usually contains a viewwin for read-only scrolling text. readconfig: Perl extension interface. text: Text formatting utilities (ie, indenting, truncating, etc) util: Misc utility functions that don't fit anywhere yet: - sepbar rendering - tokenizing and parsing utilities - downstr - stristr - owl_malloc/free/realloc variable: Interface to setting and getting variables. Current variable types include bool, int, string, and other. There's also an enum type which is variant of int. Variables can be created and customized here as well. varstubs.c: Autogenerated headers for accessing global variables view: A collection of messages determined by a filter. Many operations may be performed on the members of a view, and a view can be narrowed-to for display. viewwin: Read-only scrolling text displayed in a modal popwin. This is also sometimes called "popless". zephyr: Routines for interfacing to zephyr. zwrite: Outgoing zephyrs. Sends pings on creation, handles command arguments, etc. =========================================================================== CURSES WINDOWS -------------- The four curses windows on the screen are recwin - receiving window sepwin - seperator window msgwin - message window typwin - typing window =========================================================================== Conventions and Design Criteria ------------------------------- Functions for creating and destroying objects should be named according to the following conventions: owl_*_init: Takes a pointer to a caller-allocated struct, and creates an object there. owl_*_cleanup: Takes a pointer, and destroys the object there, expecting the caller to free the struct. owl_*_new: Allocates a struct, creates an object there, and returns a pointer. owl_*_delete: Takes a pointer, destroys the object, and frees the struct. Functions should document if the caller needs to free something, and this should be the exception to the rule. Owl should be generally useful out-of-the-box without extensive configuration, for most people's needs. People shouldn't have to spend days tweaking with config files before being happy switching to it. barnowl-1.10/doc/advanced.txt0000644000175000017500000001646013020626370013101 00000000000000 ======================== Owl Advanced Users Guide ======================== ========================= Section X: COMMAND ALISES ========================= [see Section 4 in intro.txt, which may want to be moved here] ======================= Section X: KEY BINDINGS ======================= [see Section 4 in intro.txt, which may want to be moved here] ========================= Section X: CUSTOM FILTERS ========================= For example, the following command will create a filter called 'mail' that maches any messages sent to the zephyr class 'mail': filter mail class ^mail$ The first argument after the filter command specifies the name of the filter to be created. The text after that indicates that matching messages must have the zephyr class "mail". For help understanding the '^' and '$' characters, consult a reference on regular expressions. Note that all pattern matching in Owl is case-insensitive. The message fields that can be used in a filter command include: sender message sender recipient message recipient class zephyr class name instance zephyr instance name opcode zephyr opcode realm zephyr realm body message body type message type ('zephyr', 'aim', 'admin') direction either 'in' 'out' or 'none'\n" login either 'login' 'logout' or 'none'\n" You can also use the operators 'and' 'or' and 'not' as well as the values 'true' and 'false'. Parentheses can be used to group expressions, though there must be spaces present before and after all parenthesis. For example: filter myfilt ( class ^foo$ ) or ( class ^quux$ and instance ^bar$ ) If you define a filter using a filter name that already exists, it will overwrite the existing filter. This can be a useful way to override the built-in filters. ========================================= Section 6: THE PERL EXTENSION CONFIG FILE ========================================= *** WARNING: This interface is still evolving and may change over time *** The ~/.owlconf file is interpreted by the perl interpreter. You may specify an alternate file by running owl with "owl -c ". Subroutines created with the names below will be executed at the specified times: subroutine name properties --------------- ---------- owl::startup() run when owl first starts owl::shutdown() run when owl exits owl::format_msg() run to format messages when using the perl style. The return value is used to display the message on the screen. owl::receive_msg() run when a message is received, and after it has been added to the message list It is possible to call back into owl and execute owl commands from within these functions. This is particularly useful in owl::startup for setting up your initial owl environment. If you wish to execute an owl command use the function owl::command(). i.e. owl::command('set zsigproc "/mit/kretch/bin/getzsig foo"'); will set the owl variable zsigproc to the value "/mit/kretch/bin/getzsig foo". Note that you will need to watch out for perl quoting issues. [It may be worth talking about them a little here...] Both owl::format_msg and owl::receive_msg are passed perl owl::Message objects which have methods for accessing the attributes of the message. (Caveat: Note that these owl::Message objects are currently only snapshots of the message contents that are created as needed. As such, there could be multiple owl::Message objects for the same owl message. Use the msgid if you want to uniquely identify individual messages.) All owl::Message objects contain the following methods: type - returns the type of the message ("zephyr", "aim", "admin") direction - returns "in" or "out" for incoming or outgoing messages time - returns a string of the time when the message showed up id - returns a unique id for the message body - returns the body text of the message sender - returns the sender of the message recipient - returns the recipient of the message login - returns either "login", "logout", or "none" is_login - returns true if this is a login message is_logout - returns true if this is a logout message is_loginout - returns true if this is a login or logout message is_incoming - returns true if this is an incoming message is_outgoing - returns true if this is an outgoing message is_deleted - returns true if this message is marked for deletion is_ - returns true if the message is of type (eg, is_zephyr) delete - marks the message for deletion undelete - unmarks the message from deletion pretty_sender - returns a cleaned up version of the sender The following owl::Message methods are only applicable to various message types: header - returns the admin message header line (admin) is_personal - returns true if this is a personal message (aim,zephyr) is_private - returns true if this was a private message (zephyr) login_tty - returns the login tty for login messages (zephyr) login_host - returns the login host for login messages (zephyr) zwriteline - returns the zwrite command line for outgoing zephyrs (zephyr) zsig - returns the zsig (zephyr) is_ping - returns true if this was a zephyr ping (zephyr) is_mail - returns true if this was a new mail notification (zephyr) class - returns the zephyr class (zephyr) instance - returns the zephyr instance (zephyr) realm - returns the zephyr realm (zephyr) opcode - returns the zephyr opcode (zephyr) hostname - returns the zephyr sender's hostname (zephyr) fields - returns the zephyr fields as a perl list (zephyr) auth - returns whether this zephyr was authentic (zephyr) An example formatting function that formats messages so that they only list the direction, sender, and time would be: sub owl::format_msg { my ($m) = @_; # assigns the message object passed # to this function to $m return sprintf "[direction=%s] from sender %s at %s\n", $m->direction, $m->sender, $m->time; } In the above, $m is the owl::Message object and its methods are called with $m->METHODNAME. An example receiver function that tags all zephyr pings for deletion would be: sub owl::receive_msg { my ($m) = @_; # assigns the message object passed # to this function to $m if ($m->is_zephyr and $m->is_ping) { $m->delete(); } } ================= Section X: STYLES ================= ======================================== Section 7: PERL COMMANDS FROM WITHIN OWL ======================================== Perl code may be executed from within owl with: perl If you use pperl instead of perl, the return value of the perl command will be displayed in a pop-up window. This is particularly useful within key bindings and aliases. For example: alias finger pperl $x=owl::getcurmsg()->hostname; `finger \@$x`; Will cause the "finger" command to be used to finger at the host where the current message came from. You can then bind this to the "f" key with: bindkey recv f command finger See the section above for detailss of commands and functions that are available from within the perl interpreter. barnowl-1.10/doc/intro.txt0000644000175000017500000003600113020626370012460 00000000000000 ======================== Quick Guide To Using Owl ======================== ======================= Section 1: INTRODUCTION ======================= Owl is a tty, curses-based instant messaging client. This is a quick guide to learning how to use it. Currently Owl supports AIM & zephyr, but other messaging protocols, including Jabber, are on the way. Some major features of owl include: o) As a tty client it can be run over telnet, rlogin or text ssh sessions o) It uses a perl configuration file for setting preferences and formatting messages o) Emacs style editing of messages o) It is easy to use and runs without a configfile. o) Advanced sorting and coloring of messages ========================== Section 2: GETTING STARTED ========================== Owl will run happily without a configuration file, so to get started just run the program. Owl will take over the terminal window it is started in, so you may wish to have another terminal window available at the same time. On Athena you can find owl in the ktools locker. To run it, type: add ktools owl at the Athena% prompt. If you wish to run the latest beta release of owl use: add ktools owl-beta instead. The beta release will often have newer features, but is not as tried and true as the production release. As a result it may be less stable. The Screen Layout ----------------- There are three main parts to the owl screen. The large top portion of the screen is where messages are displayed. The status bar separates this area from the one below and displays owl status information. The space below that is used to type messages and is also used by owl to give warnings and information to the user. On Line Help ------------ Owl has a full on line help system. Pressing the 'h' key will bring up the basic help screen. Further help can be obtained using the help command, described later. Sending a Zephyr ---------------- To send a zephyr press the 'z' key. This will start a zwrite command, which you can finish by typing the name of the user you wish to send to, followed by enter. Begin typing your message. You will notice that most emacs-style editing is available. When you are ready to send the message type Control-D or a dot ('.') on a line by itself. If instead you wish to cancel the message type Control-C. If you wish to send to a class/instance pair simply supply -c and -i arguments to the zwrite command as you normally would. Sending an AIM message ---------------------- Before sending an AIM message you must login to AOL Instant Messenger. Use the 'aimlogin' command, with your screenname as an argument: aimlogin You will be prompted for your password, which you must enter. Once you are successfully logged in you can send an AIM message by pressing the 'a' key, which will bring up an 'aimwrite' command: aimwrite Supply the screen name you wish to write to as an argument and then send the message just as you would send a zephyr, as described above. Manipulating Messages --------------------- When there are zephyrs in the message window, one of them will be the 'current' message. Owl will indicate which one it is with an arrow that looks like this: -> The following keys will move you to different messages: n move to the next non-deleted message p move to the previous non-deleted message C-n or down move to the next message C-p or up move to the previous message < move to the first message > move to the last message C-v page down M-v page up right scroll the screen to the right left scroll the screen to the left P move to the next personal message M-P move to the previous personal message When you are ready to delete a message you can mark it for deletion with the 'd' key, and a 'D' will appear to the left of the message. Messages will not actually be removed until you perform an expunge. The following keys are used to delete, undelete and expunge messages: d mark a message for deletion u unmark a message for deletion x expunge deleted messages T mark all 'trash' messages for deletion M-D mark all messages in the view for deletion M-u unmark all messages in the view for deletion If you would like to respond to a message sent to you there is a reply shortcut: r Reply. Personal messages get a personal reply, group messages get a group reply. R Reply to sender. Always replies personally to the sender. M-r Reply but allow editing of the command line. M-R Reply to sender but allow editing of the command line. In the event that the current message is too large to fit on the screen, you can scroll within the message using the following keys: SPACE page down b page up RETURN line down BACKSPACE line up The message pointer will change to indicate that the message is not starting at the first line. Two other keys that relate to the current message: i print detailed information about the message w instruct netscape to visit a URL in the message Other Functions ---------------- Some other functions that can be performed with a single keystroke: A toggle zephyr zaway on or off C-l refresh and resize the screen C-z suspend Command Mode ------------ Owl has a command mode from which you can enter more detailed commands for Owl to process. To enter command mode press the colon (':') key: : begin command mode Owl will give you a command prompt and you can begin typing your command. Type Enter to execute the command, Control-C to cancel. There are many commands. The basic commands are listed on the basic help screen (by pressing 'h'). If you'd like a list of all commands you can use the command: show commands And for detailed information on the syntax and use of a command you can use: help For example "help zwrite" will display all the options available when using the zwrite command. Variables --------- Owl has a number of internal variables that can be used to change the behavior the program. The 'print' command will let you view the value of a variable and the 'set' commmand will let you set the value of a variable. For example: set personalbell on will set the value of the variable 'personalbell' to 'on'. The command: print personalbell will show you the current value. The 'print' command with no arguments: print Owl will show you the value of all variables. You can also use show variables show variable To display further information on owl variables. ================ Section 3: VIEWS ================ Owl always displays a current "view" of messages. The view describes which set of messages should be included on the display. The default view is called "all" and includes every message. However, you can narrow the view to a particular set of messages: M-n Narrow view to the selected conversation M-N Narrow view to selected conversation by instance V Return to the home view (the 'all' view) X Expunge messages and return to home view If you press M-n while the pointer is on a personal message, the view will be narrowed to the conversation with that user only. If used on a group message the conversation will be narrowed to that group. There are also some Owl commands related to views: viewclass Narrow the view to the named zephyr class viewuser Narrow the view to the named user More information on views and how they work is included in the section on "FILTERS AND COLORS". ============================= Section 4: FILTERS AND COLORS ============================= Filters ------- Owl will allow you to create custom message filters. A message filter is an expression that matches a set of messages based on certain criteria. Owl comes with a number of build-in filters already. You can view a list of them with the command: show filters The default filters include: all Matches all messages none Matches no messages personal Only personal messages (no group messages) login Login/Logout notifications auto Messages generated by automated programs out Messages sent from you to another user aim AIM messages zephyr Zephyr messages trash "Trash" messages ping Zephyr pings reply-lockout Messages for which the reply commands should not work If you wish to view the messages that match a particular filter, use the 'view' command. For example: view personal This will display only personal messages on the screen. You can change back to the 'all' view by pressing the 'V' key (capitalized). Note that the 'v' key (not capitalized) is a shortcut to bring up the 'view' command. You can also create your own filters. For more information on this, consult the Owl Advanced Users Guide. Colors ------ Every filter can have a color associated with it. Messages matching the filter will then be displayed in that color if your terminal supports it. The color for a filter can be set by using the '-c' option to the filter command. For example: filter personal -c white This cause all messages in the 'personal' filter to be displayed in white. You can produce a list of the colors available to Owl with the command: show colors If a message matches more than one filter it will be displayed in the color specified in the last filter listed in the 'show filters' command. If you would like your color settings to persist, such that they are preset every time you start Owl, please read the "Saving Your Settings" section below. =============================== Section 5: SAVING YOUR SETTINGS =============================== Any changes you make to Owl are lost when the program is terminated, unless you specify otherwise. If you would like a setting to persist such that it is available every time you start Owl you can use the word 'startup' before any command. For example: startup filter personal -c white Will instruct Owl to color personal messages white both in the current session and in any future Owl session. You may revert this behavior with the 'unstartup' command: unstartup filter personal -c white which will not affect the current session, but will cause future sessions not to take this action. Here is another example, this instructs Owl to display zephyr ping messages: startup set rxping on ========================== Section 6: THE CONFIG FILE ========================== *** WARNING: This interface may change substantially in the near future *** The ~/.owlconf file is interpreted by the perl interpreter. You may specify an alternate file by running owl with "owl -c ". If you wish to execute an owl command from .owlconf use the function owl::command(). i.e.: owl::command('set zsigproc "/mit/kretch/bin/getzsig foo"'); Subroutines created with the names below will be executed at the specified times: subroutine name properties --------------- ---------- owl::startup() run when owl first starts owl::shutdown() run when owl exits owl::format_msg() run to format messages when using the perl style. The return value is used to display the message on the screen. owl::receive_msg() run when a message is received, and after it has been added to the message list Both owl::format_msg and owl::receive_msg are passed perl owl::Message objects which contain attributes of the message. Please see the advanced.txt file for further documentation of the Perl extension API. The "appendtosepbar" variable may be set in owl::format_msg() to set text to be appended to sepbar that separates the received message list from the edit window. ========================================== Section 4: KEYBINDINGS AND COMMAND ALIASES ========================================== Aliases ------- Command aliases allow users to create shortcuts for commonly used commands. Aliases can be created wit the alias command: alias NAME VALUE For example: alias zw zwrite Will make "zw" an alias for the zwrite command. As such, "zw aphacker" will be expanded to "zwrite aphacker". If the value of an alias is multiple words, use of the alias will result in the alias command name being replaced by the sequence of words. Any arguments following the alias name will be appended after the expanded alias value. For example: alias vs view -s will result in "vs standard" being expanded to "view -s standard". There is not yet any way to allow an alias to take arguments that will be inserted in the middle of the expansion. Separating Commands ------------------- Multiple commands can be grouped together with parentheses and then separated by semicolons. For example: ( smartnarrow ; delete view ; expunge ; view all ) Will result in the four commands being executed in sequence. This is particularly useful with key bindings and coommands. For example: alias sn-delete ( smartnarrow ; delete view ) will create an "sn-delete" alias that will smartnarrow to a view and them mark the view for deletion. Using "show commands" will list all existing aliases. Key Bindings ------------ New key bindings may be created with the "bindkey" command. Each key binding is associated with a particular keymap which is applicable in a particular context/situation. When the key associated with a binding is pressed in the right context, it will result in an owl command being run. The syntax is: bindkey command For example: bindkey recv C-k command delete will bind Control-k to the delete command, but only in the recv window context. Some keymaps inherit their bindings from more general keymaps. The valid keymaps are: - global - owl-wide defaults (apply everywhere) |-edit - all text editing and command windows | |-editmulti - multi-line text editing windows | |-editline - single-line editing and command windows | |-editresponse - single-line responses to questions |-popless - scrolling pop-up windows |-recv - the main message list window where received messages are displayed The existing key bindings can be shown with "show keymaps". The use of "show commands" will list all available commands. Note that not all commands may be used in all contexts. Key sequences may be surrounded by quotes and include a sequence of keys that must be pressed in order to execute the command. For example: bindkey recv "C-s v" command view -s vt will result in "Control-s" followed by "v" in the recv window causing the command "view -s vt" to be run. barnowl-1.10/doc/releasing-barnowl.txt0000644000175000017500000000674513020626370014754 00000000000000-*- mode: org *- * DOING A BARNOWL RELEASE - [ ] Send mail to barnowl-dev indicating that a release is happening soon, and soliciting any improvements that developers want included in the release. - [ ] Wait a while (a week or so, or more if necessary) for any pending patches to get in. - [ ] Prepare the -rc commit - [ ] Run ./scripts/add-changelog NEW-VERSION PREV-TAG..HEAD - [ ] Edit ChangeLog to combine and filter entries - [ ] Edit configure.ac to bump the version to 1.Nrc1 - [ ] Commit with message 'BarnOwl 1.Nrc1'; don't push until after builds all succeed - [ ] Run scripts/do-release with -f (so it won't complain about missing changelog), makes a tarball - [ ] Do a locker build (See DOING A LOCKER BUILD) - [ ] Update configure.ac on master to bump the version to 1.(N+1)dev - [ ] Add the barnowl-1.(N+1)dev git tag - [ ] Push git git: - [ ] The RC commit - [ ] The configure.ac change on master - [ ] A release-1.N branch pointing at the RC commit - [ ] the new git tags - [ ] Update debian/changelog on the launchpad build using `dch -v 1.(N+1)` - [ ] bzr branch lp:~barnowl/barnowl/packaging && cd packaging && dch -v 1.(N+1) - [ ] Add relevant changelog entries such as "New upstream release" or "Placeholder version number for daily builds."; fix your name and email if necessary - [ ] bzr commit && bzr push - [ ] Copy tarball into /mit/barnowl/web_scripts/dist - [ ] Send mail announcing the RC to barnowl-dev@mit.edu - [ ] Wait 1-2 weeks, collect any bug reports - [ ] Fix any reported bugs on master - [ ] Cherry-pick/backport appropriate fixes from master onto release-1.N - [ ] If there have been many or large bugfixes, repeat the process for barnowl 1.Nrc2 * DOING THE ACTUAL RELEASE - [ ] Update the changelog and configure.ac for barnowl 1.N - [ ] Copy the changelog changes to the master branch - [ ] run ./scripts/do-release - [ ] Do the locker build - [ ] Push the release tag - [ ] Write up release notes (I usually use the previous release's email as a template) - [ ] Update the website - [ ] Add the line that `do-release` printed to the changelog on the home page - [ ] Add your release notes as /release-notes/1.N - [ ] Send the release notes to barnowl-users@mit.edu * DOING A LOCKER BUILD - [ ] Copy the tarball to build@nelhage.com - [ ] ssh to build@nelhage.com and kinit - [ ] On build@nelhage.com, run barnowl-build-all TARBALL. This script does builds for all Debathena platforms using chroots on nelhage.com, and ssh's to Athena 9 machines to do the two Athena 9 builds. - [ ] Sanity-check the builds - [ ] Do cursory testing on debathena platforms and both athena9s. - [ ] chroots on nelhage.com also useful - [ ] Update symlinks with locker-update script; - locker-update [-b] [-n] VERSION - e.g. locker-update -b -n barnowl-1.6rc1 - [ ] Use -b to update the barnowl-beta name - [ ] Use -n first for dry-run * LOCKER LAYOUT - builds/barnowl-VERSION contains the arch-independent files by version - arch/SYSNAME/bin/barnowl-VERSION is the actual binary - arch/SYSNAME/bin/barnowl is a symlink to ../../common/bin/barnowl (wrapper script runs barnowl.real). .../barnowl.real is a symlink to the latest version. - zcrypt is also installed with a versioned name, but currently barnowl-N will not run zcrypt-N, so we can't change that interface at all. barnowl-1.10/window.c0000644000175000017500000003550213020626370011477 00000000000000#include "owl.h" struct _owl_window { /*noproto*/ GObject object; /* hierarchy information */ owl_window *parent; owl_window *child; owl_window *next, *prev; /* flags */ int dirty : 1; int dirty_subtree : 1; int shown : 1; int is_screen : 1; /* window information */ WINDOW *win; PANEL *pan; int nlines, ncols; int begin_y, begin_x; }; enum { REDRAW, RESIZED, LAST_SIGNAL }; static guint window_signals[LAST_SIGNAL] = { 0 }; static void owl_window_dispose(GObject *gobject); static void owl_window_finalize(GObject *gobject); static owl_window *_owl_window_new(owl_window *parent, int nlines, int ncols, int begin_y, int begin_x); static void _owl_window_link(owl_window *w, owl_window *parent); static void _owl_window_create_curses(owl_window *w); static void _owl_window_destroy_curses(owl_window *w); static void _owl_window_realize(owl_window *w); static void _owl_window_unrealize(owl_window *w); static owl_window *cursor_owner; static owl_window *default_cursor; /* clang gets upset about the glib argument chopping hack because it manages to * inline owl_window_children_foreach. user_data should be a pointer to a * FuncOneArg. */ typedef void (*FuncOneArg)(void *); static void first_arg_only(gpointer data, gpointer user_data) { FuncOneArg *func = user_data; (*func)(data); } G_DEFINE_TYPE (OwlWindow, owl_window, G_TYPE_OBJECT) static void owl_window_class_init (OwlWindowClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); /* Set up the vtabl */ gobject_class->dispose = owl_window_dispose; gobject_class->finalize = owl_window_finalize; klass->redraw = NULL; klass->resized = NULL; /* Create the signals, remember IDs */ window_signals[REDRAW] = g_signal_new("redraw", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_CLEANUP, G_STRUCT_OFFSET(OwlWindowClass, redraw), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER, NULL); /* TODO: maybe type should be VOID__INT_INT_INT_INT; will need to generate a * marshaller */ window_signals[RESIZED] = g_signal_new("resized", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(OwlWindowClass, resized), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); } static void owl_window_dispose (GObject *object) { owl_window *w = OWL_WINDOW (object); /* Unmap the window */ owl_window_hide (w); /* Unlink and unref all children */ while (w->child) { owl_window *child = w->child; owl_window_unlink (child); } /* Remove from hierarchy */ owl_window_unlink (w); G_OBJECT_CLASS (owl_window_parent_class)->dispose (object); } static void owl_window_finalize (GObject *object) { owl_window *w = OWL_WINDOW(object); if (w->pan) { del_panel(w->pan); w->pan = NULL; } G_OBJECT_CLASS (owl_window_parent_class)->finalize (object); } static void owl_window_init (owl_window *w) { } /** singletons **/ static WINDOW *_dummy_window(void) { static WINDOW *dummy = NULL; if (!dummy) { dummy = newwin(1, 1, 0, 0); } return dummy; } owl_window *owl_window_get_screen(void) { static owl_window *screen = NULL; if (!screen) { /* The screen is magical. It's 'shown', but the only mean of it going * invisible is if we're tore down curses (i.e. screen resize) */ screen = _owl_window_new(NULL, g.lines, g.cols, 0, 0); screen->is_screen = 1; owl_window_show(screen); } return screen; } /** Creation and Destruction **/ owl_window *owl_window_new(owl_window *parent) { if (!parent) parent = owl_window_get_screen(); return _owl_window_new(parent, 0, 0, 0, 0); } static owl_window *_owl_window_new(owl_window *parent, int nlines, int ncols, int begin_y, int begin_x) { owl_window *w; w = g_object_new (OWL_TYPE_WINDOW, NULL); if (w == NULL) g_error("Failed to create owl_window instance"); w->nlines = nlines; w->ncols = ncols; w->begin_y = begin_y; w->begin_x = begin_x; _owl_window_link(w, parent); if (parent && parent->is_screen) { w->pan = new_panel(_dummy_window()); set_panel_userptr(w->pan, w); } return w; } /** Hierarchy **/ void owl_window_unlink(owl_window *w) { /* make sure the window is unmapped first */ _owl_window_unrealize(w); /* unlink parent/child information */ if (w->parent) { if (w->prev) w->prev->next = w->next; if (w->next) w->next->prev = w->prev; if (w->parent->child == w) w->parent->child = w->next; w->parent = NULL; g_object_unref (w); } } static void _owl_window_link(owl_window *w, owl_window *parent) { if (w->parent == parent) return; owl_window_unlink(w); if (parent) { w->parent = parent; w->next = parent->child; if (w->next) w->next->prev = w; parent->child = w; g_object_ref (w); } } /* mimic g_list_foreach for consistency */ void owl_window_children_foreach(owl_window *parent, GFunc func, gpointer user_data) { owl_window *w; for (w = parent->child; w != NULL; w = w->next) { func(w, user_data); } } owl_window *owl_window_parent(owl_window *w) { return w->parent; } owl_window *owl_window_first_child(owl_window *w) { return w->child; } owl_window *owl_window_next_sibling(owl_window *w) { return w->next; } owl_window *owl_window_previous_sibling(owl_window *w) { return w->prev; } /** Internal window management **/ static void _owl_window_create_curses(owl_window *w) { if (w->is_screen) { resizeterm(w->nlines, w->ncols); w->win = stdscr; } else { /* Explicitly disallow realizing an unlinked non-root */ if (w->parent == NULL || w->parent->win == NULL) return; if (w->pan) { w->win = newwin(w->nlines, w->ncols, w->begin_y, w->begin_x); replace_panel(w->pan, w->win); } else { w->win = derwin(w->parent->win, w->nlines, w->ncols, w->begin_y, w->begin_x); } } } static void _owl_window_destroy_curses(owl_window *w) { if (w->is_screen) { /* don't deallocate the dummy */ w->win = NULL; } else { if (w->pan) { /* panels assume their windows always exist, so we put in a fake one */ replace_panel(w->pan, _dummy_window()); } if (w->win) { /* and destroy our own window */ delwin(w->win); w->win = NULL; } } } void owl_window_show(owl_window *w) { w->shown = 1; _owl_window_realize(w); if (w->pan) show_panel(w->pan); } void owl_window_show_all(owl_window *w) { FuncOneArg ptr = (FuncOneArg)owl_window_show; owl_window_show(w); owl_window_children_foreach(w, first_arg_only, &ptr); } void owl_window_hide(owl_window *w) { /* you can't unmap the screen */ if (w->is_screen) return; w->shown = 0; if (w->pan) hide_panel(w->pan); _owl_window_unrealize(w); } bool owl_window_is_shown(owl_window *w) { return w->shown; } bool owl_window_is_realized(owl_window *w) { return w->win != NULL; } bool owl_window_is_toplevel(owl_window *w) { return w->pan != NULL; } bool owl_window_is_subwin(owl_window *w) { return w->pan == NULL && !w->is_screen; } static bool _owl_window_should_realize(owl_window *w) { return owl_window_is_shown(w) && (!w->parent || owl_window_is_realized(w->parent)); } static void _owl_window_realize_later(owl_window *w) { if (owl_window_is_realized(w) || !_owl_window_should_realize(w)) return; owl_window_dirty(w); } static void _owl_window_realize(owl_window *w) { FuncOneArg ptr = (FuncOneArg)_owl_window_realize_later; /* check if we can create a window */ if (owl_window_is_realized(w) || !_owl_window_should_realize(w)) return; if (w->nlines <= 0 || w->ncols <= 0) return; _owl_window_create_curses(w); if (w->win == NULL) return; /* schedule a repaint */ owl_window_dirty(w); /* map the children */ owl_window_children_foreach(w, first_arg_only, &ptr); } static void _owl_window_unrealize(owl_window *w) { FuncOneArg ptr = (FuncOneArg)_owl_window_unrealize; if (w->win == NULL) return; /* unmap all the children */ owl_window_children_foreach(w, first_arg_only, &ptr); _owl_window_destroy_curses(w); w->dirty = w->dirty_subtree = 0; /* subwins leave a mess in the parent; dirty it */ if (w->parent) owl_window_dirty(w->parent); } /** Painting and book-keeping **/ void owl_window_set_cursor(owl_window *w) { if (cursor_owner) g_object_remove_weak_pointer(G_OBJECT(cursor_owner), (gpointer*) &cursor_owner); cursor_owner = w; if (w) g_object_add_weak_pointer(G_OBJECT(w), (gpointer*) &cursor_owner); owl_window_dirty(owl_window_get_screen()); } void owl_window_set_default_cursor(owl_window *w) { if (default_cursor) g_object_remove_weak_pointer(G_OBJECT(default_cursor), (gpointer*) &default_cursor); default_cursor = w; if (w) g_object_add_weak_pointer(G_OBJECT(w), (gpointer*) &default_cursor); owl_window_dirty(owl_window_get_screen()); } static owl_window *_get_cursor(bool *is_default) { *is_default = false; if (cursor_owner && owl_window_is_realized(cursor_owner)) return cursor_owner; *is_default = true; if (default_cursor && owl_window_is_realized(default_cursor)) return default_cursor; return owl_window_get_screen(); } void owl_window_dirty(owl_window *w) { if (!_owl_window_should_realize(w)) return; if (!w->dirty) { w->dirty = 1; while (w && !w->dirty_subtree) { w->dirty_subtree = 1; w = w->parent; } } } void owl_window_dirty_children(owl_window *w) { FuncOneArg ptr = (FuncOneArg)owl_window_dirty; owl_window_children_foreach(w, first_arg_only, &ptr); } static void _owl_window_redraw(owl_window *w) { if (!w->dirty) return; _owl_window_realize(w); if (w->win && !w->is_screen) { if (owl_window_is_subwin(w)) { /* If a subwin, we might have gotten random touched lines from wsyncup or * past drawing. That information is useless, so we discard it all */ untouchwin(w->win); } g_signal_emit(w, window_signals[REDRAW], 0, w->win); wsyncup(w->win); } w->dirty = 0; } static bool _owl_window_is_subtree_dirty(owl_window *w) { owl_window *child; if (w->dirty) return true; for (child = w->child; child != NULL; child = child->next) { if (child->dirty_subtree) return true; } return false; } static void _owl_window_redraw_subtree(owl_window *w) { FuncOneArg ptr = (FuncOneArg)_owl_window_redraw_subtree; if (!w->dirty_subtree) return; _owl_window_redraw(w); owl_window_children_foreach(w, first_arg_only, &ptr); /* Clear the dirty_subtree bit, unless a child doesn't have it * cleared because we dirtied a window in redraw. Dirtying a * non-descendant window during a redraw handler is * discouraged. Redraw will not break, but it is undefined whether * the dirty is delayed to the next event loop iteration. */ if (_owl_window_is_subtree_dirty(w)) { owl_function_debugmsg("subtree still dirty after one iteration!"); } else { w->dirty_subtree = 0; } } /* Redraw all the windows with scheduled redraws. NOTE: This function shouldn't be called outside the event loop */ void owl_window_redraw_scheduled(void) { owl_window *cursor; owl_window *screen = owl_window_get_screen(); bool default_cursor; if (!screen->dirty_subtree) return; _owl_window_redraw_subtree(screen); update_panels(); cursor = _get_cursor(&default_cursor); if (cursor && cursor->win) { /* If supported, hide the default cursor. */ curs_set(default_cursor ? 0 : 1); /* untouch it to avoid drawing; window should be clean now, but we must * clean up in case there was junk left over on a subwin (cleaning up after * subwin drawing isn't sufficient because a wsyncup messes up subwin * ancestors */ untouchwin(cursor->win); wnoutrefresh(cursor->win); } doupdate(); } /** Window position **/ void owl_window_get_position(owl_window *w, int *nlines, int *ncols, int *begin_y, int *begin_x) { if (nlines) *nlines = w->nlines; if (ncols) *ncols = w->ncols; if (begin_y) *begin_y = w->begin_y; if (begin_x) *begin_x = w->begin_x; } void owl_window_move(owl_window *w, int begin_y, int begin_x) { /* It is possible to move a window efficiently with move_panel and mvderwin, * but begy and begx are then wrong. Currently, this only effects the * wnoutrefresh to move cursor. TODO: fix that and reinstate that * optimization if it's worth the trouble */ owl_window_set_position(w, w->nlines, w->ncols, begin_y, begin_x); } void owl_window_set_position(owl_window *w, int nlines, int ncols, int begin_y, int begin_x) { int resized; if (w->nlines == nlines && w->ncols == ncols && w->begin_y == begin_y && w->begin_x == begin_x) { return; } resized = w->nlines != nlines || w->ncols != ncols; _owl_window_unrealize(w); w->begin_y = begin_y; w->begin_x = begin_x; w->nlines = nlines; w->ncols = ncols; if (resized) g_signal_emit(w, window_signals[RESIZED], 0); if (w->shown) { /* ncurses is screwy: give up and recreate windows at the right place */ _owl_window_realize_later(w); } } void owl_window_resize(owl_window *w, int nlines, int ncols) { owl_window_set_position(w, nlines, ncols, w->begin_y, w->begin_x); } /** Redrawing main loop hooks **/ static bool _owl_window_should_redraw(void) { return g.resizepending || owl_window_get_screen()->dirty_subtree; } static gboolean _owl_window_redraw_prepare(GSource *source, int *timeout) { *timeout = -1; return _owl_window_should_redraw(); } static gboolean _owl_window_redraw_check(GSource *source) { return _owl_window_should_redraw(); } static gboolean _owl_window_redraw_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { owl_colorpair_mgr *cpmgr; /* if a resize has been scheduled, deal with it */ owl_global_check_resize(&g); /* update the terminal if we need to */ owl_window_redraw_scheduled(); /* On colorpair shortage, reset and redraw /everything/. NOTE: if we * still overflow, this be useless work. With 8-colors, we get 64 * pairs. With 256-colors, we get 32768 pairs with ext-colors * support and 256 otherwise. */ cpmgr = owl_global_get_colorpair_mgr(&g); if (cpmgr->overflow) { owl_function_debugmsg("colorpairs: used all %d pairs; reset pairs and redraw.", owl_util_get_colorpairs()); owl_fmtext_reset_colorpairs(cpmgr); owl_function_full_redisplay(); owl_window_redraw_scheduled(); } return TRUE; } static GSourceFuncs redraw_funcs = { _owl_window_redraw_prepare, _owl_window_redraw_check, _owl_window_redraw_dispatch, NULL }; CALLER_OWN GSource *owl_window_redraw_source_new(void) { GSource *source; source = g_source_new(&redraw_funcs, sizeof(GSource)); /* TODO: priority?? */ return source; } barnowl-1.10/test-driver0000755000175000017500000001104013020637074012214 00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>$log_file # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: barnowl-1.10/configure.ac0000644000175000017500000001672613055166613012330 00000000000000dnl Process this file with autoconf to produce a configure script. AC_INIT([BarnOwl],[1.10],[bug-barnowl@mit.edu]) AM_INIT_AUTOMAKE([1.7.0 foreign std-options -Wall -Wno-portability]) AM_MAINTAINER_MODE([enable]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADER([config.h]) AC_PROG_CC AC_PROG_CC_C99 AC_PROG_LN_S AC_ARG_WITH([zephyr-default-format], [AS_HELP_STRING([--with-zephyr-default-format], [value for the default format zephyrgram field])], [ case $withval in yes) withval='Config error: see http://mit.edu/df';; no) withval='';; esac zephyr_default_format=$withval ], [zephyr_default_format='Config error: see http://mit.edu/df']) AC_DEFINE_UNQUOTED( [ZEPHYR_DEFAULT_FORMAT], ["$zephyr_default_format"], [Value for the default format zephyrgram field] ) AC_ARG_WITH([stack-protector], [AS_HELP_STRING([--with-stack-protector], [Enable gcc -fstack-protector])], [], [with_stack_protector=check]) AS_IF([test "x$with_stack_protector" != xno], [AX_CHECK_COMPILE_FLAG([-fstack-protector], [AM_CFLAGS="$AM_CFLAGS -fstack-protector"], [if test "x$with_stack_protector" != xcheck; then AC_MSG_FAILURE([--with-stack-protector selected, but gcc does support it.]) fi ])]) AC_CHECK_LIB(ncursesw, initscr,, AC_MSG_ERROR(No libncursesw found.)) AC_CHECK_LIB(panelw, update_panels,, AC_MSG_ERROR(No libpanelw found.)) AC_SEARCH_LIBS([gethostbyname], [nsl]) AC_SEARCH_LIBS([socket], [socket]) AC_SEARCH_LIBS([res_search], [resolv]) AC_ARG_WITH([zephyr], [AS_HELP_STRING([--with-zephyr], [Enable Zephyr support])], [], [with_zephyr=check]) AC_ARG_WITH([krb4], AS_HELP_STRING([--with-krb4], [Build with kerberos IV])) AS_IF([test "x$with_zephyr" != xno], [have_krb4=no AS_IF([test "x$with_krb4" != "xno"], [AC_MSG_CHECKING([for Kerberos IV]) AS_IF([krb5-config krb4 --libs >/dev/null 2>&1], [AC_MSG_RESULT([yes]) have_krb4=yes AC_DEFINE([HAVE_KERBEROS_IV], [1], [Define if you have kerberos IV]) AM_CFLAGS="${AM_CFLAGS} `krb5-config krb4 --cflags`" LIBS="${LIBS} `krb5-config krb4 --libs`" ], [AC_MSG_RESULT([no]) AS_IF([test "x$with_krb4" = "xyes"], [AC_MSG_ERROR([Kerberos IV requested but not found])])])]) AS_IF([test "x$have_krb4" != xyes], [PKG_CHECK_MODULES([LIBCRYPTO], [libcrypto], [AM_CFLAGS="${AM_CFLAGS} ${LIBCRYPTO_CFLAGS}" LIBS="${LIBS} ${LIBCRYPTO_LIBS}" ], [PKG_CHECK_MODULES([OPENSSL], [openssl], [AM_CFLAGS="${AM_CFLAGS} ${OPENSSL_CFLAGS}" LIBS="${LIBS} ${OPENSSL_LIBS}" ])])]) AC_CHECK_LIB([zephyr], [ZGetSender], [LIBS="$LIBS -lzephyr" AC_DEFINE([HAVE_LIBZEPHYR], [1], [Define if you have libzephyr]) AC_CHECK_LIB([zephyr], [ZInitLocationInfo], AC_DEFINE([HAVE_LIBZEPHYR_ZINITLOCATIONINFO], [1], [Have ZInitLocationInfo]),) AC_CHECK_LIB([com_err], [com_err]) AC_CHECK_HEADERS([com_err.h]) ], [if test "x$with_zephyr" != xcheck; then AC_MSG_FAILURE( [--with-zephyr was given, but libzephyr does not seem to be available.]) fi ])]) AC_CHECK_FUNCS([use_default_colors]) AC_CHECK_FUNCS([resizeterm], [], [AC_MSG_ERROR([No resizeterm found])]) AC_CHECK_FUNCS([des_string_to_key DES_string_to_key], [HAVE_DES_STRING_TO_KEY=1]) AC_CHECK_FUNCS([des_ecb_encrypt DES_ecb_encrypt], [HAVE_DES_ECB_ENCRYPT=1]) AC_CHECK_FUNCS([des_key_sched DES_key_sched], [HAVE_DES_KEY_SCHED=1]) dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(stdbool.h strings.h sys/ioctl.h sys/filio.h unistd.h) dnl Add CFLAGS for embeded perl PERL_CFLAGS=`perl -MExtUtils::Embed -e ccopts` AC_MSG_NOTICE([Adding perl CFLAGS ${PERL_CFLAGS}]) AM_CFLAGS="${AM_CFLAGS} ${PERL_CFLAGS}" dnl Find the location of perl XSUBPP AC_MSG_CHECKING(for the perl xsubpp precompiler) XSUBPPDIR="`cd "$srcdir" && perl -MExtUtils::MakeMaker -e 'print ExtUtils::MakeMaker->new({NAME => qw(owl)})->tool_xsubpp;' | grep \^XSUBPPDIR | sed -e 's/XSUBPPDIR = //g;'`" if test -n "${XSUBPPDIR}"; then AC_MSG_RESULT(${XSUBPPDIR}) else AC_MSG_ERROR(not found) fi if test -f "${XSUBPPDIR}/typemap"; then XSUBPPFLAGS="-typemap ${XSUBPPDIR}/typemap" else XSUBPPFLAGS="" fi dnl Add LIBS for embedded perl FOO=`perl -MExtUtils::Embed -e ldopts` AC_MSG_NOTICE([Adding perl LIBS ${FOO}]) LIBS=${LIBS}\ ${FOO} AC_CHECK_LIB([perl], [perl_alloc],, AC_MSG_ERROR([No libperl found])) AX_PROG_PERL_MODULES([AnyEvent],, [AC_MSG_ERROR([cannot find perl module AnyEvent.])]) AX_PROG_PERL_MODULES([Class::Accessor::Fast],, [AC_MSG_ERROR([cannot find perl module Class::Accessor::Fast.])]) AX_PROG_PERL_MODULES([ExtUtils::Depends],, [AC_MSG_ERROR([cannot find perl module ExtUtils::Depends])]) AX_PROG_PERL_MODULES([Glib],, [AC_MSG_ERROR([cannot find perl module Glib.])]) AX_PROG_PERL_MODULES([Module::Install::Base],, [AC_MSG_ERROR([cannot find perl module Module::Install::Base])]) AX_PROG_PERL_MODULES([PAR],, [AC_MSG_WARN([PAR.pm not found. Loadable modules will be disabled.])]) dnl Add CFLAGS and LIBS for glib-2.0 PKG_CHECK_MODULES(GLIB,[glib-2.0 >= 2.16 gobject-2.0 gthread-2.0]) AC_MSG_NOTICE([Adding glib-2.0 CFLAGS ${GLIB_CFLAGS}]) AM_CFLAGS="${GLIB_CFLAGS} ${AM_CFLAGS}" AC_MSG_NOTICE([Adding glib-2.0 LIBS ${GLIB_LIBS}]) LIBS="${GLIB_LIBS} ${LIBS}" if test "x${prefix}" = "xNONE"; then prefix="${ac_default_prefix}" fi dnl Add CFLAGS for glib-perl GLIB_PERL_CFLAGS=`perl -MExtUtils::Depends -e 'my $e = ExtUtils::Depends->new("BarnOwl","Glib"); my %h = $e->get_makefile_vars; print $h{"INC"}'` AC_MSG_NOTICE([Adding glib-perl CFLAGS ${GLIB_PERL_CFLAGS}]) AM_CFLAGS="${GLIB_PERL_CFLAGS} ${AM_CFLAGS}" dnl Checks for typedefs, structures, and compiler characteristics. AX_CFLAGS_WARN_ALL([AM_CFLAGS]) AX_APPEND_COMPILE_FLAGS([-Wstrict-prototypes -Wwrite-strings],[AM_CFLAGS]) dnl Shut gcc up about zero-length format strings; the warning's apparently for dnl efficiency reasons, which is bogus for custom functions. AX_APPEND_COMPILE_FLAGS([-Wno-format-zero-length],[AM_CFLAGS]) AX_APPEND_COMPILE_FLAGS([-Wno-pointer-sign -Wno-empty-body -Wno-unused-value],[LIBFAIM_CFLAGS]) AM_CONDITIONAL([ENABLE_ZCRYPT], [test "$HAVE_DES_STRING_TO_KEY" && dnl test "$HAVE_DES_KEY_SCHED" && dnl test "$HAVE_DES_ECB_ENCRYPT"]) AM_CFLAGS="$AM_CFLAGS -D_XOPEN_SOURCE=600" dnl Define _BSD_SOURCE because zephyr needs caddr_t. AM_CFLAGS="$AM_CFLAGS -D_BSD_SOURCE" dnl Define __EXTENSIONS__ for strcasecmp on Solaris. AM_CFLAGS="$AM_CFLAGS -D__EXTENSIONS__" dnl Define _XOPEN_SOURCE_EXTENDED for some features in ncurses, dnl including cchar_t. This should not be necessary with dnl _XOPEN_SOURCE=600, but some versions of ncurses dnl apparently still need it. AM_CFLAGS="$AM_CFLAGS -D_XOPEN_SOURCE_EXTENDED" AC_SUBST([AM_CFLAGS]) AC_SUBST([LIBFAIM_CFLAGS]) AC_SUBST(XSUBPPDIR) AC_SUBST(XSUBPPFLAGS) AC_PROG_INSTALL AC_PROG_RANLIB AC_CHECK_PROG([HAVE_ZIP], [zip], [yes], [no]) if test "x${HAVE_ZIP}" = "xno"; then AC_MSG_ERROR([cannot find a 'zip' binary.]) fi AC_CONFIG_LIBOBJ_DIR([compat]) AC_CHECK_DECLS([memrchr]) AC_REPLACE_FUNCS([memrchr]) AC_SUBST([abs_builddir]) AC_SUBST([abs_srcdir]) AC_CONFIG_FILES([Makefile compat/Makefile libfaim/Makefile perl/Makefile perl/modules/Makefile]) AC_OUTPUT barnowl-1.10/sepbar.c0000644000175000017500000000611613020626370011443 00000000000000#include "owl.h" static void sepbar_redraw(owl_window *w, WINDOW *sepwin, void *user_data); void owl_sepbar_init(owl_window *w) { g_signal_connect(w, "redraw", G_CALLBACK(sepbar_redraw), NULL); /* TODO: handle dirtiness in the sepbar */ owl_window_dirty(w); } static void sepbar_redraw(owl_window *w, WINDOW *sepwin, void *user_data) { const owl_messagelist *ml; const owl_view *v; int x, y, i; const char *foo, *appendtosepbar; int cur_numlines, cur_totallines; ml=owl_global_get_msglist(&g); v=owl_global_get_current_view(&g); werase(sepwin); wattron(sepwin, A_REVERSE); if (owl_global_is_fancylines(&g)) { whline(sepwin, ACS_HLINE, owl_global_get_cols(&g)); } else { whline(sepwin, '-', owl_global_get_cols(&g)); } if (owl_global_is_sepbar_disable(&g)) { getyx(sepwin, y, x); wmove(sepwin, y, owl_global_get_cols(&g)-1); return; } wmove(sepwin, 0, 2); if (owl_messagelist_get_size(ml) == 0) waddstr(sepwin, " (-/-) "); else wprintw(sepwin, " (%i/%i/%i) ", owl_global_get_curmsg(&g) + 1, owl_view_get_size(v), owl_messagelist_get_size(ml)); foo=owl_view_get_filtname(v); if (strcmp(foo, owl_global_get_view_home(&g))) wattroff(sepwin, A_REVERSE); wprintw(sepwin, " %s ", owl_view_get_filtname(v)); if (strcmp(foo, owl_global_get_view_home(&g))) wattron(sepwin, A_REVERSE); i=owl_mainwin_get_last_msg(owl_global_get_mainwin(&g)); if ((i != -1) && (i < owl_view_get_size(v)-1)) { getyx(sepwin, y, x); wmove(sepwin, y, x+2); wattron(sepwin, A_BOLD); waddstr(sepwin, " "); wattroff(sepwin, A_BOLD); } if (owl_global_get_rightshift(&g)>0) { getyx(sepwin, y, x); wmove(sepwin, y, x+2); wprintw(sepwin, " right: %i ", owl_global_get_rightshift(&g)); } if (owl_function_is_away()) { getyx(sepwin, y, x); wmove(sepwin, y, x+2); wattron(sepwin, A_BOLD); wattroff(sepwin, A_REVERSE); waddstr(sepwin, " AWAY "); wattron(sepwin, A_REVERSE); wattroff(sepwin, A_BOLD); } if (owl_mainwin_is_curmsg_truncated(owl_global_get_mainwin(&g))) { getyx(sepwin, y, x); wmove(sepwin, y, x+2); wattron(sepwin, A_BOLD); cur_numlines = owl_global_get_curmsg_vert_offset(&g) + 1; cur_totallines = owl_message_get_numlines(owl_view_get_element(v, owl_global_get_curmsg(&g))); wprintw(sepwin, " ", cur_numlines, cur_totallines); wattroff(sepwin, A_BOLD); } if (owl_global_get_curmsg_vert_offset(&g)) { getyx(sepwin, y, x); wmove(sepwin, y, x+2); wattron(sepwin, A_BOLD); wattroff(sepwin, A_REVERSE); waddstr(sepwin, " SCROLL "); wattron(sepwin, A_REVERSE); wattroff(sepwin, A_BOLD); } appendtosepbar = owl_global_get_appendtosepbar(&g); if (appendtosepbar && *appendtosepbar) { getyx(sepwin, y, x); wmove(sepwin, y, x+2); waddstr(sepwin, " "); waddstr(sepwin, owl_global_get_appendtosepbar(&g)); waddstr(sepwin, " "); } getyx(sepwin, y, x); wmove(sepwin, y, owl_global_get_cols(&g)-1); wattroff(sepwin, A_BOLD); wattroff(sepwin, A_REVERSE); } barnowl-1.10/examples/0000755000175000017500000000000013020626370011715 500000000000000barnowl-1.10/examples/owlconf.vtformat0000644000175000017500000000755313020626370015102 00000000000000### The owlconf config file -*- perl -*- ### ### This file is interpreted by the perl interpreter. ### If you wish to execute an owl command use the ### function owl::command(). i.e. ### ### owl::command("set zsigproc /mit/kretch/bin/getzsig"); ### ### will set the owl variable zsigproc. Subroutines created with ### the names below will be executed at the specified times: ### ### subroutine name properties ### --------------- ---------- ### owl::startup() run when owl first starts ### owl::shutdown() run when owl exits ### owl::format_msg() run when a new message arrives, the return ### value is used to display the message on the ### screen ### ### The following variables will be set each time a message is recevied: ### ### $owl::class, $owl::instance, $owl::recipient, ### $owl::sender, $owl::opcode, $owl::zsig, ### $owl::msg, $owl::time, $owl::host, @owl::fields ### # classes will be appreviated this way my %class_abbrev = ( "message" => "", "spleen" => "sp", "ccare" => "cc", "implied-consent" => "ic", "syseng" => "se", "install" => "i", ); sub owl::startup { owl::command("set logging off"); #owl::command("set zsigproc /home/nygren/bin/owlzsigs"); owl::command("set startuplogin off"); owl::command("set shutdownlogout off"); #owl::command("set personalbell on"); owl::command("set rxping on"); owl::command("set typewinsize 5"); } sub owl::shutdown { # system("/mit/kretch/bin/zkill > /dev/null 2> /dev/null"); } sub owl::format_msg { my ($out, $tmp); $owl::sender=~s/\@ATHENA\.MIT\.EDU$//; $owl::sender=~s/\@local-realm$//; if (uc($owl::opcode) eq "PING") { return("\@bold(PING) from \@bold($owl::sender)\n"); } elsif (uc($owl::class) eq "LOGIN") { if (uc($owl::opcode) eq "USER_LOGIN") { $out="\@bold(LOGIN)"; } elsif (uc($owl::opcode) eq "USER_LOGOUT") { $out="\@bold(LOGOUT)"; } else { $out="\@bold(UNKNOWN)"; } $out.=" for \@bold($owl::sender) at $fields[0] on $fields[2]\n"; return($out); } elsif (uc($owl::class) eq "MAIL") { $out = "\@bold(MAIL) "; if ($owl::msg =~ /^From:\s+(.+)\s*$/m) { $out .= "From $1 "; } if ($owl::msg =~ /^To:\s+(.+)\s*$/m) { $out .= "To $1 "; } if ($owl::msg =~ /^Subject:\s+(.+)\s*$/m) { $out .= "Subject $1 "; } return($out."\n"); } my $channel = $owl::class; if (defined $class_abbrev{lc($owl::class)}) { $channel = $class_abbrev{lc($owl::class)}; } if (lc($owl::class) ne "message" and lc($owl::instance) eq "personal") { $owl::instance = ""; } $channel .= "[".$owl::instance."]"; $channel = substr($channel,0,13); $header = sprintf "%-8s %-13s ", lc($owl::sender), lc($channel); if ($owl::msg =~ /=/) { # indent it $tmp=$owl::msg; $tmp=~s/^/ /g; $tmp=~s/\n/\n /g; $out.=$header."\n".$tmp; } else { # fill it my $pagewidth = 74; $out .= $header; $out .= fill_text($owl::msg, $pagewidth, 22, 1); } # note: no zsig added in this version # make personal messages bold if (uc($owl::class) eq "MESSAGE" && uc($owl::instance) eq "PERSONAL") { $out="\@bold{".$out."}\n"; } return($out); } sub fill_text { my ($in, $width, $indent, $unindent_first) = @_; $indent = 0 if (@_ < 3); my $unindent = $indent if ($unindent_first); my @words = split " ", $in; my $out = ""; my $outline = ""; if (!$unindent_first) { my $outline = " "x$indent; } for my $w (@words) { if (($outline ne "") && (length($outline)+length($w) > $width-$unindent)) { $out .= $outline."\n"; $outline = " "x$indent; $unindent = 0; } if ($outline =~ /.*\.$/) { $outline .= " "; } elsif ($outline ne "") { $outline .= " "; } $outline .= $w; } $out .= $outline . "\n"; } barnowl-1.10/examples/owlconf.simple0000644000175000017500000002322713020626370014525 00000000000000### The owlconf config file -*- perl -*- ### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! ### This is an example file intended to demonstrate how to use ### various features of owl. Some of the key bindings, in particular, ### are more for examples than things you may actually want to use. ### Make sure to read through it first and understand it before just using it. ### Don't blame me if anything in here ends up vaporizing your dog. ### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! ### ### This file is interpreted by the perl interpreter. ### If you wish to execute an owl command use the ### function owl::command(). i.e. ### ### owl::command("set zsigproc /mit/kretch/bin/getzsig"); ### ### will set the owl variable zsigproc. Subroutines created with ### the names below will be executed at the specified times: ### ### subroutine name properties ### --------------- ---------- ### owl::startup() run when owl first starts ### owl::shutdown() run when owl exits ### owl::format_msg() run when a new message arrives, the return ### value is used to display the message on the ### screen ### owl::receive_msg() run when a message is received, and after ### it has been added to the message list ### ### ### The following variables will be set each time a message is recevied ### and when owl::format_msg() and owl::receive_msg() are run. ### ### $owl::class, $owl::instance, $owl::recipient, $owl::direction, ### $owl::sender, $owl::opcode, $owl::zsig, ### $owl::msg, $owl::time, $owl::host, @owl::fields, $owl::id ### # NOTE: Lines beginning with a "#" are perl comments. # This subroutine is run whenever owl starts up. # The owl::command("foo") lines execute the owl command "foo". sub owl::startup { ################################################################ ## The following set the values of variables. ## Doing "help" will show you more about each variable. ## These lines will set things to the default. ## You can uncomment them and then change the value to get ## a different behavior (remove the "#" to an alternate value). ################################################################ ## Set this to off to disable the terminal bell. # owl::command('set -q bell on'); ## Set this to off to disable the terminal bell on personal zephyrs. # owl::command('set -q personalbell off'); ## Set this to on to enable logging of personal zephyrs # owl::command('set -q logging off'); ## This directory must exist and is where personal zephyrs are logged. ## By default, this is the ~/zlog/personal/ directory # owl::command('set -q logpath '.$ENV{'HOME'}.'/zlog/personal/'); ## Set this to on to enable logging of classes # owl::command('set -q classlogging off'); ## This directory must exist and is where class zephyrs are logged. ## By default, this is the ~/zlog/class/ directory # owl::command('set -q classlogpath '.$ENV{'HOME'}.'/zlog/class/'); ## If set to on, this will make is so that C-d doesn't ## send zephyrs by accident. # owl::command('set -q disable-ctrl-d off'); ## If set to on, outgoing messages will be displayed. # owl::command('set -q displayoutgoing on'); ## Displays received pings? # owl::command('set -q rxping off'); ## Send pings? # owl::command('set -q txping on'); ## Size of typing window at the bottom of the screen # owl::command('set -q typewinsize 8'); ## Which view to switch to after the 'V' or 'X' commands. # owl::command('set -q view_home all'); ## Default message to send when zaway is on (toggle with 'A') # owl::command('set -q zaway_msg_default "Not here now..."'); ## Default zephyr signature. # owl::command('set -q zsig "meep"'); ## Program to generate a zsig. # owl::command('set -q zsigproc "/mit/foo/bin/randzsig"'); ################################################################ ## The following create filters. Filters can be used to select ## on multiple zephyrs for operations. With 'views' you can ## look at only the zephyrs matching a particular filter. ## Use the 'view ' command or the 'v' key to switch views. ## The 'V' key will switch you back to your 'view_home' view. ## The M-D key will delete all messages in the current view ## ## ## The filter command creates a filter with the specified name, ## or if one already exists it is replaced. Example filter ## syntax would be: ## ## filter myfilter -c red ( class ^foobar$ ) or ( class ^quux$ and instance ^bar$ ) ## ## Valid matching fields are class, instance, recipient, sender, opcode ## and realm. Valid operations are 'and', 'or' and 'not'. Spaces must be ## present before and after parenthesis. If the optional color argument ## is used it specifies the color that messages matching this filter ## should be displayed in. Do 'show colors' to see the available colors. ## ################################################################ ## This would create a shortcut to only show personal messages ## with filter 'me' and to color them yellow. ## Replace myusername with yours. # owl::command('filter me -c yellow recipient myusername'); ## This would create a 'quiet' filter to not show messages ## on noisy classes and instances. # owl::command('filter quiet not ( class ^foo|bar|quux$ or instance ( ^baaz$ ) '); ## The 'trash' filter is used when you press 'T' to mark things ## for autodeletion. # owl::command('filter trash class ^mail$ or opcode ^ping$ or type ^admin$ or class ^login$'); } ## This is run when owl exits. Currently this does nothing. sub owl::shutdown { } ## This is run to format the contents of the message. ## It returns a string which is a formatted message. ## The following variables will be set each time before this is run: ## ## $owl::class, $owl::instance, $owl::recipient, ## $owl::sender, $owl::opcode, $owl::zsig, ## $owl::msg, $owl::time, $owl::host, @owl::fields, $owl::id sub owl::format_msg { my $out, $tmp; ## Strip out noise from the sender string. $owl::sender=~s/\@ATHENA\.MIT\.EDU$//; $owl::sender=~s/\@local-realm$//; $owl::recipient=~s/\@ATHENA\.MIT\.EDU$//; $owl::recipient=~s/\@local-realm$//; ## Format ping, login, and mail messages. ## uc(foo) upcases the string and "eq" does string comparison. if (uc($owl::opcode) eq "PING") { return("\@bold(PING) from \@bold($owl::sender)\n"); } elsif (uc($owl::class) eq "LOGIN") { if (uc($owl::opcode) eq "USER_LOGIN") { $out="\@bold(LOGIN)"; } elsif (uc($owl::opcode) eq "USER_LOGOUT") { $out="\@bold(LOGOUT)"; } else { $out="\@bold(UNKNOWN)"; } $out.=" for \@bold($owl::sender) at $fields[0] on $fields[2]\n"; return($out); } elsif (uc($owl::class) eq "MAIL" and uc($owl::instance) eq "INBOX") { $out = "\@bold(MAIL) "; if ($owl::msg =~ /^From:\s+(.+)\s*$/m) { $out .= "From $1 "; } if ($owl::msg =~ /^To:\s+(.+)\s*$/m) { $out .= "To $1 "; } if ($owl::msg =~ /^Subject:\s+(.+)\s*$/m) { $out .= "Subject $1 "; } return($out."\n"); } ## The remainder formats normal messages (eg, to classes and instances). ## Outgoing messages have different headers than incoming messages. ## Note that: ## $out .= "foo"; appends "foo" to the end of the variable $out. ## lc(bar) will convert bar to lowercase. ## "ne" does "not equal" for string comparison. ## sprintf fills in the %s's with the arguments later on the line. ## "foo"."bar" will append the two strings together. if ($owl::direction eq "out") { # Outgoing messages $out .= sprintf "[outgoing to %s] / %s", $owl::recipient, $owl::time; if ($owl::opcode ne "") {$out.=" op:$owl::opcode";} $out.="\n"; $out.= " \@bold($owl::sender)> "; if ($owl::zsig ne "") { my $zsig = $owl::zsig; $zsig =~ s/(\n.*)+$/ [...]/; if (length($zsig)+5+length($owl::sender) > 70) { $out.="# ..."; } else { $out.="# $zsig"; } } } else { # Incoming messages $out .= sprintf "[mit,%s,%s] / %s / %s", lc($owl::class), lc($owl::instance), $owl::time, lc($owl::host); if ($owl::opcode ne "") {$out.=" op:$owl::opcode";} $out.="\n"; $out.= " \@bold($owl::sender)> "; if ($owl::zsig ne "") { my $zsig = $owl::zsig; $zsig =~ s/(\n.*)+$/ [...]/; if (length($zsig)+5+length($owl::sender) > 70) { $out.="# ..."; } else { $out.="# $zsig"; } } } $out.="\n"; # This indents the body of the message and then appends it on. $tmp=$owl::msg; $tmp=~s/^/ /g; $tmp=~s/\n/\n /g; $out.=$tmp; # This makes personal messages bold. if (uc($owl::class) eq "MESSAGE" && uc($owl::instance) eq "PERSONAL" && $owl::direction eq "in") { $out="\@bold{".$out."}"; } # Finally, this appends a newline and returns the formatted message. return($out."\n"); } ## This is run when a message is received, and after ## it has been added to the message list. ## In most cases you won't need anything here. sub owl::receive_msg() { ## If this is uncommented, it would mark all messages ## with opcode "PING" for immediate deletion: # # if (uc($owl::opcode) eq "PING") { # owl::command("delete -id $owl::id"); # } ## If this is uncommented, it would mark all messages ## with class "LOGIN" for immediate deletion: # # if (uc($owl::login) eq "LOGIN") { # owl::command("delete -id $owl::id"); # } return 1; } barnowl-1.10/examples/owlconf.erik0000644000175000017500000003141513020626370014164 00000000000000### The owlconf config file -*- perl -*- ### ### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! ### This is an example file intended to demonstrate how to use ### various features of owl. Some of the key bindings, in particular, ### are more for examples than things you may actually want to use. ### Make sure to read through it first and understand it before just using it. ### Don't blame me if anything in here ends up vaporizing your dog. ### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! ### ### ### This file is interpreted by the perl interpreter. ### If you wish to execute an owl command use the ### function owl::command(). i.e. ### ### owl::command("set zsigproc /mit/kretch/bin/getzsig"); ### ### will set the owl variable zsigproc. Subroutines created with ### the names below will be executed at the specified times: ### ### subroutine name properties ### --------------- ---------- ### owl::startup() run when owl first starts ### owl::shutdown() run when owl exits ### owl::format_msg() formats messages that are passed to it ### owl::receive_msg() run when a message is received, and after ### it has been added to the message list ### ### The format_msg and receive_msg functions are passed owl::Message objects. ### The message attributes may be dereferenced with $m->attribute ### ### # tokens for sepbar are: # .username = ping # >username = login # id} = $msg_num; } sub mail_pop_curmsg () { my $m = owl::getcurmsg(); if (!$m->is_mail || !defined $mail_id_map{$m->id}) { &owl::command("pop-message"); } else { &owl::command(sprintf 'pexec pop -request c -request "retr %d" -request q', $mail_id_map{$m->id}); } } sub zlocatesender { my $m = owl::getcurmsg(); if ($m->{"type"} eq "zephyr") { my $sender = $m->{"sender"}; owl::command("zlocate $sender"); } } # adds a sepbartoken and also updates the appendtosepbar variable sub sepbartokens_add { my ($token) = @_; $token =~ s/"//g; # " unshift @sepbartokens, $token; pop @sepbartokens if (@sepbartokens > 80); sepbartokens_set(); } # trims a sepbartoken from the list also updates the appendtosepbar variable sub sepbartokens_trim { my ($token) = @_; @sepbartokens = map { if ($_ ne $token) { $_; } else { (); } } @sepbartokens; sepbartokens_set(); } my $loopctr=0; # trims a sepbartoken from the list also updates the appendtosepbar variable sub sepbartokens_set { owl::command(sprintf "set -q appendtosepbar \"%s %s %s\"", (scalar localtime), (join " ", @sepbartokens)); } my $restoreview = undef; sub swapview { my $curview = owl::command("getview"); if ($restoreview) { owl::command("view $restoreview"); $restoreview = undef; } else { $restoreview = $curview; owl::command("smartnarrow"); } } my $lastcolored = undef; sub colorthread { if ($lastcolored) { owl::command("filter $lastcolored -c default"); } my $smartfilt = owl::command("smartfilter"); if (!$smartfilt or $smartfilt eq $lastcolored) { owl::command("filter $lastcolored -c default"); $lastcolored = undef; } else { owl::command("filter $smartfilt -c green"); $lastcolored = $smartfilt; } } # Load in things which don't belong in an owlconf # that people might use as an example... sub personal_startup { my $personalconf = $ENV{"HOME"}."/.owl/personalconf"; if (-f $personalconf) { my $b = ""; open INB, $personalconf; for () { $b .= $_; } close INB; eval $b; } } sub owl::startup { owl::command("set -q logging on"); owl::command("set -q logpath ~/.zlog/owl/personal"); owl::command("set -q classlogpath ~/.zlog/owl/class"); owl::command("set -q logging on"); owl::command("set -q startuplogin off"); owl::command("set -q shutdownlogout off"); #owl::command("set personalbell on"); owl::command("set -q _burningears on"); owl::command("set -q rxping on"); owl::command("set -q typewinsize 5"); owl::command("filter me recipient %me% or ( sender %me% and class message and instance personal ) or class mail or type aim"); owl::command("filter owl instance ^owl.*"); owl::command(q(alias finger pperl $x=owl::getcurmsg()->hostname; `finger \@$x`;)); owl::command("bindkey recv f command finger"); owl::command("alias z zwrite"); owl::command("alias zw zwrite"); owl::command("alias v view"); owl::command("alias popmail perl mail_pop_curmsg();"); # toggle between a view and a smartnarrow with TAB owl::command("alias swapview perl swapview();"); owl::command("bindkey recv C-i command swapview"); # color the current thread owl::command("alias colorthread perl colorthread();"); owl::command("bindkey recv M-c command colorthread"); # zlocate current sender owl::command("bindkey recv L command perl zlocatesender();"); # Declare styles &owl::command("style vt perl format_msg_vt"); &owl::command("style brief perl format_msg_brief"); &owl::command("style custom perl format_msg_custom"); &owl::command("style debug perl format_msg_debug"); &owl::command("set -q default_style custom"); # Change to different view styles owl::command("bindkey recv \"C-s v\" command view -s vt"); owl::command("bindkey recv \"C-s c\" command view -s custom"); owl::command("bindkey recv \"C-s b\" command view -s brief"); owl::command("bindkey recv \"C-s d\" command view -s debug"); owl::command("bindkey recv \"C-s o\" command view -s standard"); # For fast-reading of zephyrs owl::command("bindkey recv M-k command ( smartnarrow ; delete view )"); owl::command("bindkey recv M-l command ( expunge ; view all )"); owl::command("bindkey recv M-K command ( smartnarrow ; delete view ; expunge ; view all )"); # Support for scroll mice &owl::command("bindkey recv \"M-[ A\" command recv:prev"); &owl::command("bindkey recv \"M-[ B\" command recv:next"); # This overrides the default "M" keybinding owl::command("bindkey recv M command popmail"); sepbartokens_add("..."); personal_startup(); } sub owl::shutdown { # not doing anything at the moment... } # run when a message is received, and after # it has been added to the message list. sub owl::receive_msg { my ($m) = @_; my ($out, $tmp); if ($m->is_admin && !$m->is_outgoing) { $m->delete(); return 1; } return 0 if (!$m->is_zephyr && !$m->is_aim); my $sender = $m->pretty_sender; if ($m->is_ping) { sepbartokens_add(".$sender"); $m->delete(); } elsif ($m->is_loginout) { $m->delete(); if ($m->is_login) { sepbartokens_add(">$sender"); sepbartokens_trim("<$sender"); } elsif ($m->is_logout) { sepbartokens_add("<$sender"); sepbartokens_trim(">$sender"); } } elsif ($m->is_mail) { mail_add_message($m); $m->delete(); sepbartokens_add("M"); } if ($m->is_personal) { sepbartokens_trim(".$sender"); sepbartokens_add(":$sender"); } return 1; } sub indent4 { my ($b) = @_; $b=~s/^/ /g; $b=~s/\n/\n /g; return $b; } # run to format a message sub format_msg_custom { my ($m) = @_; my ($out, $tmp); if ($m->is_admin) { $out = "\@bold([owl admin]) ".$m->header."\n"; $out.=indent4($m->body); return $out."\n"; } my $sender=$m->pretty_sender; if (($m->is_aim or $m->is_zephyr) && $m->is_loginout) { if ($m->is_login) { $out="\@bold(LOGIN)"; } elsif ($m->is_logout) { $out="\@bold(LOGOUT)"; } else { $out="\@bold(UNKNOWN)"; } $out.=" for \@bold($sender) on ".$m->type; if ($m->is_zephyr) { $out.=" at ".($m->login_host)." on ".($m->login_tty); } return("$out\n"); } if (!$m->is_zephyr && !$m->is_aim) { return "Unknown message type: ".$m->type."\n"; } if ($m->is_outgoing) { my $target = $m->recipient; if ($m->is_zephyr) { $target = $m->zwriteline; $target =~ s/^zwrite //; } $out = sprintf "\@bold([outgoing %s to %s]) / %s\n", $m->type, $target, $m->time; $out.=indent4($m->body); return "$out\n"; } if ($m->is_zephyr && $m->is_ping) { return("\@bold(PING) from \@bold($sender)\n"); } elsif ($m->is_zephyr && $m->is_mail) { $out = "\@bold(MAIL) "; if ($m->body =~ /^From:\s+(.+)\s*$/m) { $out .= "From $1 "; } if ($m->body =~ /^To:\s+(.+)\s*$/m) { $out .= "To $1 "; } if ($m->body =~ /^Subject:\s+(.+)\s*$/m) { $out .= "Subject $1 "; } return("$out\n"); } if ($m->is_zephyr) { $out = sprintf "[mit,%s,%s] / %s / %s", lc($m->class), lc($m->instance), $m->time, lc($m->host); if ($m->opcode ne "") {$out.=" op:".$m->opcode;} $out.="\n"; $out.= " \@bold($sender)> "; if ($m->zsig ne "") { my $zsig = $m->zsig; $zsig =~ s/(\n.*)+$/ [...]/; if (length($zsig)+5+length($sender) > 70) { $out.="# ..."; } else { $out.="# $zsig"; } } $out.="\n"; } else { $out = sprintf "[%s] / %s\n", lc($m->type), $m->time; $out.= " \@bold($sender)> "; $out.="\n"; } $out.=indent4($m->body); # make personal messages bold if ($m->is_personal) { $out="\@bold{".$out."}"; } return($out."\n"); } sub format_msg_debug { my ($m) = @_; return "\@bold(-------------MESSAGE-------------)\n".($m->serialize).".\n"; } sub format_msg_brief { my ($m) = @_; my $out = format_msg_vt($m); $out =~ s/\n/ /g; $out =~ s/ / /g; return($out."\n"); } sub format_msg_vt { my ($m) = @_; my ($out, $tmp); if ($m->is_admin) { $out = sprintf "%-29s \@i(%s)", "\@bold(OWL ADMIN)", $m->header; $tmp=$m->body; $tmp=~s/^/ /g; $tmp=~s/\n/\n /g; $out.="\n".$tmp; return $out; } my $sender=$m->pretty_sender; if ($m->is_outgoing) { my $target = $m->recipient; if ($m->is_zephyr) { $target = $m->zwriteline; $target =~ s/^zwrite //; } $out = sprintf "%-15s %-13s", "\@bold(OUTGOING)", "to $target via ".$m->type.": "; my $pagewidth = owl::getnumcols()-6; $out .= fill_text($m->body, $pagewidth, 22, 1); return $out; } if (!$m->is_zephyr && !$m->is_aim) { return "Unknown message type: ".$m->type."\n"; } if ($m->is_zephyr && $m->is_ping) { return (sprintf "%-15s %-13s\n", "\@bold(PING)", $sender); } elsif ($m->is_loginout) { my $state; if ($m->is_login) { $state="\@bold(LOGIN)"; } elsif ($m->is_logout) { $state="\@bold(LOGOUT)"; } else { $state="\@bold(UNKNOWN)"; } my $out = sprintf "%-15s %-13s ", $state, $sender; if ($m->is_zephyr) { $out .= sprintf "via %s on %s at %s", $m->type, $m->login_host, $m->login_tty; } else { $out .= sprintf "via %s", $m->type; } return "$out\n"; } elsif ($m->is_zephyr && $m->is_mail) { my $body = $m->body; $out = sprintf "%-15s %-13s ", "\@bold(MAIL)", ""; if ($body =~ /^From:\s+(.+)\s*$/m) { $out .= "From $1 "; } if ($body =~ /^To:\s+(.+)\s*$/m) { $out .= "To $1 "; } if ($body =~ /^Subject:\s+(.+)\s*$/m) { $out .= "Subject $1 "; } return($out."\n"); } my $channel = ""; my $body = $m->body; if ($m->is_zephyr) { my $inst = $m->instance; $channel = $m->class; if (lc($m->class) ne "message" and lc($m->instance) eq "personal") { $inst = ""; } $channel .= "[".$inst."]"; $channel = substr($channel,0,13); } else { $channel = "[".$m->type."]"; } $header = sprintf "%-8s %-13s ", lc($sender), lc($channel); if ($body =~ /=/) { # indent it $out.=$header."\n".indent4($body); } else { # fill it my $pagewidth = owl::getnumcols()-6; $out .= $header; $out .= fill_text($body, $pagewidth, 22, 1); } # note: no zsig added in this version # make personal messages bold if ($m->is_personal) { $out="\@bold{".$out."}"; } return($out); } sub fill_text { my ($in, $width, $indent, $unindent_first) = @_; $indent = 0 if (@_ < 3); my $unindent = $indent if ($unindent_first); my @words = split " ", $in; my $out = ""; my $outline = ""; if (!$unindent_first) { my $outline = " "x$indent; } for my $w (@words) { if (($outline ne "") && (length($outline)+length($w) > $width-$unindent)) { $out .= $outline."\n"; $outline = " "x$indent; $unindent = 0; } if ($outline =~ /.*\.$/) { $outline .= " "; } elsif ($outline ne "") { $outline .= " "; } $outline .= $w; } $out .= $outline . "\n"; } barnowl-1.10/owl.h0000644000175000017500000004310613020626370010775 00000000000000/* Copyright (c) 2006-2011 The BarnOwl Developers. All rights reserved. * Copyright (c) 2004 James Kretchmar. All rights reserved. * * This program is free software. You can redistribute it and/or * modify under the terms of the Sleepycat License. See the COPYING * file included with the distribution for more information. */ #ifndef INC_BARNOWL_OWL_H #define INC_BARNOWL_OWL_H #include #include "compat/compat.h" #include #ifndef OWL_PERL #define NCURSES_ENABLE_STDBOOL_H 1 #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libfaim/aim.h" #include #include #ifdef HAVE_LIBZEPHYR #include #endif #ifdef HAVE_COM_ERR_H #include #endif /* Perl and curses don't play nice. */ #ifdef OWL_PERL typedef struct _owl_fake_WINDOW WINDOW; typedef struct _owl_fake_PANEL PANEL; /* logout is defined in FreeBSD. */ #define logout logout_ #define HAS_BOOL #include #include "owl_perl.h" #undef logout #include "XSUB.h" #else typedef struct _owl_fake_SV SV; typedef struct _owl_fake_AV AV; typedef struct _owl_fake_HV HV; #endif #include "window.h" extern const char *version; /* Feature that is being tested to redirect stderr through a pipe. * There may still be some portability problems with this. */ #define OWL_STDERR_REDIR 1 #define OWL_DEBUG 0 #define OWL_DEBUG_FILE "/var/tmp/barnowl-debug" #define OWL_CONFIG_DIR "/.owl" /* this is relative to the user's home directory */ #define OWL_FMTEXT_ATTR_NONE 0 #define OWL_FMTEXT_ATTR_BOLD 1 #define OWL_FMTEXT_ATTR_REVERSE 2 #define OWL_FMTEXT_ATTR_UNDERLINE 4 #define OWL_FMTEXT_UC_BASE 0x100000 /* Unicode Plane 16 - Supplementary Private Use Area-B*/ #define OWL_FMTEXT_UC_ATTR ( OWL_FMTEXT_UC_BASE | 0x800 ) #define OWL_FMTEXT_UC_ATTR_MASK 0x7 #define OWL_FMTEXT_UC_COLOR_BASE ( OWL_FMTEXT_UC_BASE | 0x400 ) #define OWL_FMTEXT_UC_FGCOLOR OWL_FMTEXT_UC_COLOR_BASE #define OWL_FMTEXT_UC_BGCOLOR ( OWL_FMTEXT_UC_COLOR_BASE | 0x200 ) #define OWL_FMTEXT_UC_DEFAULT_COLOR 0x100 #define OWL_FMTEXT_UC_FGDEFAULT ( OWL_FMTEXT_UC_FGCOLOR | OWL_FMTEXT_UC_DEFAULT_COLOR ) #define OWL_FMTEXT_UC_BGDEFAULT ( OWL_FMTEXT_UC_BGCOLOR | OWL_FMTEXT_UC_DEFAULT_COLOR ) #define OWL_FMTEXT_UC_COLOR_MASK 0xFF #define OWL_FMTEXT_UC_ALLCOLOR_MASK ( OWL_FMTEXT_UC_COLOR_MASK | OWL_FMTEXT_UC_DEFAULT_COLOR | 0x200) #define OWL_FMTEXT_UC_STARTBYTE_UTF8 '\xf4' #define OWL_COLOR_BLACK 0 #define OWL_COLOR_RED 1 #define OWL_COLOR_GREEN 2 #define OWL_COLOR_YELLOW 3 #define OWL_COLOR_BLUE 4 #define OWL_COLOR_MAGENTA 5 #define OWL_COLOR_CYAN 6 #define OWL_COLOR_WHITE 7 #define OWL_COLOR_DEFAULT -1 #define OWL_COLOR_INVALID -2 #define OWL_TAB_WIDTH 8 #define OWL_EDITWIN_STYLE_MULTILINE 0 #define OWL_EDITWIN_STYLE_ONELINE 1 #define OWL_PROTOCOL_ZEPHYR 0 #define OWL_PROTOCOL_AIM 1 #define OWL_PROTOCOL_JABBER 2 #define OWL_PROTOCOL_ICQ 3 #define OWL_PROTOCOL_YAHOO 4 #define OWL_PROTOCOL_MSN 5 #define OWL_MESSAGE_DIRECTION_NONE 0 #define OWL_MESSAGE_DIRECTION_IN 1 #define OWL_MESSAGE_DIRECTION_OUT 2 #define OWL_DIRECTION_NONE 0 #define OWL_DIRECTION_DOWNWARDS 1 #define OWL_DIRECTION_UPWARDS 2 #define OWL_LOGGING_DIRECTION_BOTH 0 #define OWL_LOGGING_DIRECTION_IN 1 #define OWL_LOGGING_DIRECTION_OUT 2 #define OWL_SCROLLMODE_NORMAL 0 #define OWL_SCROLLMODE_TOP 1 #define OWL_SCROLLMODE_NEARTOP 2 #define OWL_SCROLLMODE_CENTER 3 #define OWL_SCROLLMODE_PAGED 4 #define OWL_SCROLLMODE_PAGEDCENTER 5 #define OWL_TAB 3 /* This *HAS* to be the size of TABSTR below */ #define OWL_TABSTR " " #define OWL_MSGTAB 7 #define OWL_TYPWIN_SIZE 8 #define OWL_HISTORYSIZE 50 /* Indicate current state, as well as what is allowed */ #define OWL_CTX_ANY 0xffff /* Only one of these may be active at a time... */ #define OWL_CTX_MODE_BITS 0x000f #define OWL_CTX_STARTUP 0x0001 #define OWL_CTX_READCONFIG 0x0002 #define OWL_CTX_INTERACTIVE 0x0004 /* Only one of these may be active at a time... */ #define OWL_CTX_ACTIVE_BITS 0xfff0 #define OWL_CTX_POPWIN 0x00f0 #define OWL_CTX_POPLESS 0x0010 #define OWL_CTX_RECWIN 0x0f00 #define OWL_CTX_RECV 0x0100 #define OWL_CTX_TYPWIN 0xf000 #define OWL_CTX_EDIT 0x7000 #define OWL_CTX_EDITLINE 0x1000 #define OWL_CTX_EDITMULTI 0x2000 #define OWL_CTX_EDITRESPONSE 0x4000 #define OWL_VARIABLE_OTHER 0 #define OWL_VARIABLE_INT 1 #define OWL_VARIABLE_BOOL 2 #define OWL_VARIABLE_STRING 3 #define OWL_OUTPUT_RETURN 0 #define OWL_OUTPUT_POPUP 1 #define OWL_OUTPUT_ADMINMSG 2 #define OWL_FILTER_MAX_DEPTH 300 #define OWL_KEYMAP_MAXSTACK 20 #define OWL_KEYBINDING_NOOP 0 /* dummy binding that does nothing */ #define OWL_KEYBINDING_COMMAND 1 /* command string */ #define OWL_KEYBINDING_FUNCTION 2 /* function taking no args */ #define OWL_DEFAULT_ZAWAYMSG "I'm sorry, but I am currently away from the terminal and am\nnot able to receive your message.\n" #define OWL_DEFAULT_AAWAYMSG "I'm sorry, but I am currently away from the terminal and am\nnot able to receive your message.\n" #define OWL_CMD_ALIAS_SUMMARY_PREFIX "command alias to: " #define OWL_WEBZEPHYR_PRINCIPAL "daemon/webzephyr.mit.edu" #define OWL_WEBZEPHYR_CLASS "webzephyr" #define OWL_WEBZEPHYR_OPCODE "webzephyr" #define OWL_ZEPHYR_NOSTRIP_HOST "host/" #define OWL_ZEPHYR_NOSTRIP_RCMD "rcmd." #define OWL_ZEPHYR_NOSTRIP_DAEMON5 "daemon/" #define OWL_ZEPHYR_NOSTRIP_DAEMON4 "daemon." #define OWL_REGEX_QUOTECHARS "!+*.?[]^\\${}()|" #define OWL_REGEX_QUOTEWITH "\\" #if defined(HAVE_DES_STRING_TO_KEY) && defined(HAVE_DES_KEY_SCHED) && defined(HAVE_DES_ECB_ENCRYPT) #define OWL_ENABLE_ZCRYPT 1 #endif /* Annotate functions in which the caller owns the return value and is * responsible for ensuring it is freed. */ #define CALLER_OWN G_GNUC_WARN_UNUSED_RESULT #define OWL_META(key) ((key)|010000) /* OWL_CTRL is definied in kepress.c */ #ifdef HAVE_LIBZEPHYR /* libzephyr doesn't use const, so we appease the type system with this kludge. * This just casts const char * to char * in a way that doesn't yield a warning * from gcc -Wcast-qual. */ static inline char *zstr(const char *str) { union { char *rw; const char *ro; } u; u.ro = str; return u.rw; } #endif /* Convert char *const * into const char *const *. This conversion is safe, * and implicit in C++ (conv.qual 4) but for some reason not in C. */ static inline const char *const *strs(char *const *pstr) { return (const char *const *)pstr; } typedef struct _owl_variable { char *name; int type; /* OWL_VARIABLE_* */ char *default_str; /* the default value as a string */ char *validsettings; /* documentation of valid settings */ char *summary; /* summary of usage */ char *description; /* detailed description */ bool takes_on_off; /* allow passing on/off in argument-less set/unset */ GClosure *set_fromstring_fn; /* sets the variable to a value * of the appropriate type. * unless documented, this * should make a copy. * returns 0 on success. */ GClosure *get_tostring_fn; /* converts val to a string; * caller must free the result */ /* These are only valid for OWL_VARIABLE_{INT,BOOL,STRING} */ GValue val; /* current value, if default get_fn/set_fn */ GCallback get_fn; /* returns a reference to the current value. * WARNING: this approach is hard to make * thread-safe... */ GCallback validate_fn; /* returns 1 if newval is valid */ GCallback set_fn; /* sets the variable to a value * of the appropriate type. * unless documented, this * should make a copy. * returns 0 on success. */ } owl_variable; typedef struct _owl_input { int ch; gunichar uch; } owl_input; typedef struct _owl_fmtext { GString *buff; } owl_fmtext; typedef struct _owl_dict_el { char *k; /* key */ void *v; /* value */ } owl_dict_el; typedef struct _owl_dict { int size; int avail; owl_dict_el *els; /* invariant: sorted by k */ } owl_dict; typedef owl_dict owl_vardict; /* dict of variables */ typedef owl_dict owl_cmddict; /* dict of commands */ typedef struct _owl_context { int mode; void *data; /* determined by mode */ char *keymap; owl_window *cursor; void (*deactivate_cb)(struct _owl_context*); void (*delete_cb)(struct _owl_context*); void *cbdata; } owl_context; typedef struct _owl_cmd { /* command */ char *name; char *summary; /* one line summary of command */ char *usage; /* usage synopsis */ char *description; /* long description of command */ int validctx; /* bitmask of valid contexts */ /* we should probably have a type here that says which of * the following is valid, and maybe make the below into a union... */ /* Only one of these may be non-NULL ... */ char *cmd_aliased_to; /* what this command is aliased to... */ /* These don't take any context */ CALLER_OWN char *(*cmd_args_fn)(int argc, const char *const *argv, const char *buff); /* takes argv and the full command as buff. * caller must free return value if !NULL */ void (*cmd_v_fn)(void); /* takes no args */ void (*cmd_i_fn)(int i); /* takes an int as an arg */ /* The following also take the active context if it's valid */ CALLER_OWN char *(*cmd_ctxargs_fn)(void *ctx, int argc, const char *const *argv, const char *buff); /* takes argv and the full command as buff. * caller must free return value if !NULL */ void (*cmd_ctxv_fn)(void *ctx); /* takes no args */ void (*cmd_ctxi_fn)(void *ctx, int i); /* takes an int as an arg */ SV *cmd_perl; /* Perl closure that takes a list of args */ } owl_cmd; typedef struct _owl_zwrite { char *cmd; char *zwriteline; char *class; char *inst; char *realm; char *opcode; char *zsig; char *message; GPtrArray *recips; int cc; int noping; } owl_zwrite; typedef struct _owl_pair { const char *key; char *value; } owl_pair; struct _owl_fmtext_cache; typedef struct _owl_message { int id; int direction; #ifdef HAVE_LIBZEPHYR bool has_notice; ZNotice_t notice; #endif struct _owl_fmtext_cache * fmtext; int delete; const char *hostname; GPtrArray *attributes; /* this is a list of pairs */ char *timestr; time_t time; } owl_message; #define OWL_FMTEXT_CACHE_SIZE 1000 /* We cache the saved fmtexts for the last bunch of messages we rendered */ typedef struct _owl_fmtext_cache { owl_message * message; owl_fmtext fmtext; } owl_fmtext_cache; typedef struct _owl_style { char *name; SV *perlobj; } owl_style; typedef struct _owl_mainwin { int curtruncated; int lasttruncated; int lastdisplayed; owl_window *window; } owl_mainwin; typedef struct _owl_editwin owl_editwin; typedef struct _owl_editwin_excursion owl_editwin_excursion; typedef struct _owl_viewwin { owl_fmtext fmtext; int textlines; int topline; int rightshift; owl_window *window; void (*onclose_hook) (struct _owl_viewwin *vwin, void *data); void *onclose_hook_data; gulong sig_resize_id; owl_window *content; gulong sig_content_redraw_id; owl_window *status; gulong sig_status_redraw_id; owl_window *cmdwin; } owl_viewwin; typedef struct _owl_popwin { owl_window *border; owl_window *content; gulong sig_redraw_id; gulong sig_resize_id; } owl_popwin; typedef struct _owl_msgwin { char *msg; owl_window *window; gulong redraw_id; } owl_msgwin; typedef struct _owl_messagelist { GPtrArray *list; } owl_messagelist; typedef struct _owl_regex { int negate; char *string; regex_t re; } owl_regex; typedef struct _owl_filterelement { int (*match_message)(const struct _owl_filterelement *fe, const owl_message *m); /* Append a string representation of the filterelement onto buf*/ void (*print_elt)(const struct _owl_filterelement *fe, GString *buf); /* Operands for and,or,not*/ struct _owl_filterelement *left, *right; /* For regex filters*/ owl_regex re; /* Used by regexes, filter references, and perl */ char *field; } owl_filterelement; typedef struct _owl_filter { char *name; owl_filterelement * root; int fgcolor; int bgcolor; } owl_filter; typedef struct _owl_view { char *name; owl_filter *filter; owl_messagelist *ml; const owl_style *style; int cachedmsgid; } owl_view; typedef struct _owl_history { GQueue hist; GList *cur; bool partial; } owl_history; typedef struct _owl_mainpanel { owl_window *panel; owl_window *typwin; owl_window *sepwin; owl_window *msgwin; owl_window *recwin; int recwinlines; } owl_mainpanel; typedef struct _owl_keybinding { int *keys; /* keypress stack */ int len; /* length of stack */ int type; /* command or function? */ char *desc; /* description (or "*user*") */ char *command; /* command, if of type command */ void (*function_fn)(void); /* function ptr, if of type function */ } owl_keybinding; typedef struct _owl_keymap { char *name; /* name of keymap */ char *desc; /* description */ GPtrArray *bindings; /* key bindings */ const struct _owl_keymap *parent; /* parent */ void (*default_fn)(owl_input j); /* default action (takes a keypress) */ void (*prealways_fn)(owl_input j); /* always called before a keypress is received */ void (*postalways_fn)(owl_input j); /* always called after keypress is processed */ } owl_keymap; typedef struct _owl_keyhandler { owl_dict keymaps; /* dictionary of keymaps */ const owl_keymap *active; /* currently active keymap */ int in_esc; /* escape pressed? */ int kpstack[OWL_KEYMAP_MAXSTACK+1]; /* current stack of keypresses */ int kpstackpos; /* location in stack (-1 = none) */ } owl_keyhandler; typedef struct _owl_buddy { int proto; char *name; int isidle; int idlesince; } owl_buddy; typedef struct _owl_buddylist { GPtrArray *buddies; } owl_buddylist; typedef struct _owl_zbuddylist { GPtrArray *zusers; } owl_zbuddylist; typedef struct _owl_errqueue { GPtrArray *errlist; } owl_errqueue; typedef struct _owl_colorpair_mgr { int next; short **pairs; bool overflow; } owl_colorpair_mgr; typedef struct _owl_popexec { int refcount; owl_viewwin *vwin; int winactive; pid_t pid; /* or 0 if it has terminated */ guint io_watch; } owl_popexec; typedef struct _owl_global { owl_mainwin *mw; owl_popwin *pw; owl_msgwin msgwin; owl_history cmdhist; /* command history */ owl_history msghist; /* outgoing message history */ owl_keyhandler kh; owl_dict filters; GList *filterlist; GPtrArray *puntlist; owl_vardict vars; owl_cmddict cmds; GList *context_stack; owl_errqueue errqueue; int lines, cols; int curmsg, topmsg; int markedmsgid; /* for finding the marked message when it has moved. */ int curmsg_vert_offset; owl_view current_view; owl_messagelist *msglist; WINDOW *input_pad; owl_mainpanel mainpanel; gulong typwin_erase_id; int rightshift; bool resizepending; char *homedir; char *confdir; char *startupfile; int direction; int haveconfig; int config_format; owl_editwin *tw; owl_viewwin *vw; void *perl; int debug; time_t starttime; time_t lastinputtime; time_t last_wakeup_time; char *startupargs; int nextmsgid; owl_colorpair_mgr cpmgr; pid_t newmsgproc_pid; owl_regex search_re; aim_session_t aimsess; aim_conn_t bosconn; int aim_loggedin; /* true if currently logged into AIM */ GSource *aim_event_source; /* where we get our AIM events from */ char *aim_screenname; /* currently logged in AIM screen name */ char *aim_screenname_for_filters; /* currently logged in AIM screen name */ owl_buddylist buddylist; /* list of logged in AIM buddies */ GQueue *messagequeue; /* for queueing up aim and other messages */ owl_dict styledict; /* global dictionary of available styles */ char *response; /* response to the last question asked */ int havezephyr; int haveaim; int ignoreaimlogin; owl_zbuddylist zbuddies; GList *zaldlist; int pseudologin_notify; struct termios startup_tio; guint aim_nop_timer; int load_initial_subs; FILE *debug_file; char *kill_buffer; int interrupt_count; #if GLIB_CHECK_VERSION(2, 31, 0) GMutex interrupt_lock; #else GMutex *interrupt_lock; #endif } owl_global; /* globals */ extern owl_global g; #include /* These were missing from the Zephyr includes before Zephyr 3. */ #if defined HAVE_LIBZEPHYR && defined ZCONST int ZGetSubscriptions(ZSubscription_t *, int *); int ZGetLocations(ZLocations_t *,int *); #endif /* We have to dynamically bind these ourselves */ extern gboolean (*gvalue_from_sv) (GValue * value, SV * sv); extern SV * (*sv_from_gvalue) (const GValue * value); extern GClosure * (*perl_closure_new) (SV * callback, SV * data, gboolean swap); #endif /* INC_BARNOWL_OWL_H */ barnowl-1.10/zwrite.c0000644000175000017500000002262513020626370011516 00000000000000#include "owl.h" CALLER_OWN owl_zwrite *owl_zwrite_new_from_line(const char *line) { owl_zwrite *z = g_slice_new(owl_zwrite); if (owl_zwrite_create_from_line(z, line) != 0) { g_slice_free(owl_zwrite, z); return NULL; } return z; } CALLER_OWN owl_zwrite *owl_zwrite_new(int argc, const char *const *argv) { owl_zwrite *z = g_slice_new(owl_zwrite); if (owl_zwrite_create(z, argc, argv) != 0) { g_slice_free(owl_zwrite, z); return NULL; } return z; } G_GNUC_WARN_UNUSED_RESULT int owl_zwrite_create_from_line(owl_zwrite *z, const char *line) { int argc; char **argv; int ret; /* parse the command line for options */ argv = owl_parseline(line, &argc); if (argc < 0) { owl_function_error("Unbalanced quotes in zwrite"); return -1; } ret = owl_zwrite_create(z, argc, strs(argv)); g_strfreev(argv); return ret; } G_GNUC_WARN_UNUSED_RESULT int owl_zwrite_create(owl_zwrite *z, int argc, const char *const *argv) { int badargs = 0; char *msg = NULL; /* start with null entries */ z->cmd=NULL; z->realm=NULL; z->class=NULL; z->inst=NULL; z->opcode=NULL; z->zsig=NULL; z->message=NULL; z->cc=0; z->noping=0; z->recips = g_ptr_array_new(); z->zwriteline = owl_argv_quote(argc, argv); if (argc && *(argv[0])!='-') { z->cmd=g_strdup(argv[0]); argc--; argv++; } while (argc) { if (!strcmp(argv[0], "-c")) { if (argc<2) { badargs=1; break; } z->class=owl_validate_utf8(argv[1]); argv+=2; argc-=2; } else if (!strcmp(argv[0], "-i")) { if (argc<2) { badargs=1; break; } z->inst=owl_validate_utf8(argv[1]); argv+=2; argc-=2; } else if (!strcmp(argv[0], "-r")) { if (argc<2) { badargs=1; break; } z->realm=owl_validate_utf8(argv[1]); argv+=2; argc-=2; } else if (!strcmp(argv[0], "-s")) { if (argc<2) { badargs=1; break; } z->zsig=owl_validate_utf8(argv[1]); argv+=2; argc-=2; } else if (!strcmp(argv[0], "-O")) { if (argc<2) { badargs=1; break; } z->opcode=owl_validate_utf8(argv[1]); argv+=2; argc-=2; } else if (!strcmp(argv[0], "-m")) { if (argc<2) { badargs=1; break; } /* we must already have users or a class or an instance */ if (z->recips->len < 1 && (!z->class) && (!z->inst)) { badargs=1; break; } /* Once we have -m, gobble up everything else on the line */ argv++; argc--; msg = g_strjoinv(" ", (char**)argv); break; } else if (!strcmp(argv[0], "-C")) { z->cc=1; argv++; argc--; } else if (!strcmp(argv[0], "-n")) { z->noping=1; argv++; argc--; } else { /* anything unattached is a recipient */ g_ptr_array_add(z->recips, owl_validate_utf8(argv[0])); argv++; argc--; } } if (badargs) { owl_zwrite_cleanup(z); return(-1); } if (z->class == NULL && z->inst == NULL && z->recips->len == 0) { owl_function_error("You must specify a recipient for zwrite"); owl_zwrite_cleanup(z); return(-1); } /* now deal with defaults */ if (z->class==NULL) z->class=g_strdup("message"); if (z->inst==NULL) z->inst=g_strdup("personal"); if (z->realm==NULL) z->realm=g_strdup(""); if (z->opcode==NULL) z->opcode=g_strdup(""); /* z->message is allowed to stay NULL */ if(msg) { owl_zwrite_set_message(z, msg); g_free(msg); } return(0); } void owl_zwrite_populate_zsig(owl_zwrite *z) { /* get a zsig, if not given */ if (z->zsig != NULL) return; z->zsig = owl_perlconfig_execute(owl_global_get_zsigfunc(&g)); } void owl_zwrite_send_ping(const owl_zwrite *z) { int i; char *to; if (z->noping) return; if (strcasecmp(z->class, "message")) { return; } for (i = 0; i < z->recips->len; i++) { to = owl_zwrite_get_recip_n_with_realm(z, i); if (owl_zwrite_recip_is_personal(to)) send_ping(to, z->class, z->inst); g_free(to); } } /* Set the message with no post-processing*/ void owl_zwrite_set_message_raw(owl_zwrite *z, const char *msg) { g_free(z->message); z->message = owl_validate_utf8(msg); } void owl_zwrite_set_message(owl_zwrite *z, const char *msg) { int i; GString *message; char *tmp = NULL, *tmp2; g_free(z->message); if (z->cc && owl_zwrite_is_personal(z)) { message = g_string_new("CC: "); for (i = 0; i < z->recips->len; i++) { tmp = owl_zwrite_get_recip_n_with_realm(z, i); g_string_append_printf(message, "%s ", tmp); g_free(tmp); tmp = NULL; } tmp = owl_validate_utf8(msg); tmp2 = owl_text_expand_tabs(tmp); g_string_append_printf(message, "\n%s", tmp2); z->message = g_string_free(message, false); g_free(tmp); g_free(tmp2); } else { tmp=owl_validate_utf8(msg); z->message=owl_text_expand_tabs(tmp); g_free(tmp); } } const char *owl_zwrite_get_message(const owl_zwrite *z) { if (z->message) return(z->message); return(""); } int owl_zwrite_is_message_set(const owl_zwrite *z) { if (z->message) return(1); return(0); } int owl_zwrite_send_message(const owl_zwrite *z) { int i, ret = 0; char *to = NULL; if (z->message==NULL) return(-1); if (z->recips->len > 0) { for (i = 0; i < z->recips->len; i++) { to = owl_zwrite_get_recip_n_with_realm(z, i); ret = send_zephyr(z->opcode, z->zsig, z->class, z->inst, to, z->message); /* Abort on the first error, to match the zwrite binary. */ if (ret != 0) break; g_free(to); to = NULL; } } else { to = g_strdup_printf( "@%s", z->realm); ret = send_zephyr(z->opcode, z->zsig, z->class, z->inst, to, z->message); } g_free(to); return ret; } int owl_zwrite_create_and_send_from_line(const char *cmd, const char *msg) { owl_zwrite z; int rv; rv = owl_zwrite_create_from_line(&z, cmd); if (rv != 0) return rv; if (!owl_zwrite_is_message_set(&z)) { owl_zwrite_set_message(&z, msg); } owl_zwrite_populate_zsig(&z); owl_zwrite_send_message(&z); owl_zwrite_cleanup(&z); return(0); } const char *owl_zwrite_get_class(const owl_zwrite *z) { return(z->class); } const char *owl_zwrite_get_instance(const owl_zwrite *z) { return(z->inst); } const char *owl_zwrite_get_opcode(const owl_zwrite *z) { return(z->opcode); } void owl_zwrite_set_opcode(owl_zwrite *z, const char *opcode) { g_free(z->opcode); z->opcode=owl_validate_utf8(opcode); } const char *owl_zwrite_get_realm(const owl_zwrite *z) { return(z->realm); } const char *owl_zwrite_get_zsig(const owl_zwrite *z) { if (z->zsig) return(z->zsig); return(""); } void owl_zwrite_set_zsig(owl_zwrite *z, const char *zsig) { g_free(z->zsig); z->zsig = g_strdup(zsig); } int owl_zwrite_get_numrecips(const owl_zwrite *z) { return z->recips->len; } const char *owl_zwrite_get_recip_n(const owl_zwrite *z, int n) { return z->recips->pdata[n]; } /* Caller must free the result. */ CALLER_OWN char *owl_zwrite_get_recip_n_with_realm(const owl_zwrite *z, int n) { if (z->realm[0]) { return g_strdup_printf("%s@%s", owl_zwrite_get_recip_n(z, n), z->realm); } else { return g_strdup(owl_zwrite_get_recip_n(z, n)); } } bool owl_zwrite_recip_is_personal(const char *recipient) { return recipient[0] && recipient[0] != '@'; } bool owl_zwrite_is_personal(const owl_zwrite *z) { /* return true if at least one of the recipients is personal */ int i; for (i = 0; i < z->recips->len; i++) if (owl_zwrite_recip_is_personal(z->recips->pdata[i])) return true; return false; } void owl_zwrite_delete(owl_zwrite *z) { owl_zwrite_cleanup(z); g_slice_free(owl_zwrite, z); } void owl_zwrite_cleanup(owl_zwrite *z) { owl_ptr_array_free(z->recips, g_free); g_free(z->cmd); g_free(z->zwriteline); g_free(z->class); g_free(z->inst); g_free(z->opcode); g_free(z->realm); g_free(z->message); g_free(z->zsig); } /* * Returns a zwrite line suitable for replying, specifically the * message field is stripped out. Result should be freed with * g_free. * * If not a CC, only the recip_index'th user will be replied to. */ CALLER_OWN char *owl_zwrite_get_replyline(const owl_zwrite *z, int recip_index) { /* Match ordering in zwrite help. */ GString *buf = g_string_new(""); int i; /* Disturbingly, it is apparently possible to z->cmd to be null if * owl_zwrite_create_from_line got something starting with -. And we * can't kill it because this is exported to perl. */ owl_string_append_quoted_arg(buf, z->cmd ? z->cmd : "zwrite"); if (z->noping) { g_string_append(buf, " -n"); } if (z->cc) { g_string_append(buf, " -C"); } if (strcmp(z->class, "message")) { g_string_append(buf, " -c "); owl_string_append_quoted_arg(buf, z->class); } if (strcmp(z->inst, "personal")) { g_string_append(buf, " -i "); owl_string_append_quoted_arg(buf, z->inst); } if (z->realm && z->realm[0] != '\0') { g_string_append(buf, " -r "); owl_string_append_quoted_arg(buf, z->realm); } if (z->opcode && z->opcode[0] != '\0') { g_string_append(buf, " -O "); owl_string_append_quoted_arg(buf, z->opcode); } if (z->cc) { for (i = 0; i < z->recips->len; i++) { g_string_append_c(buf, ' '); owl_string_append_quoted_arg(buf, z->recips->pdata[i]); } } else if (recip_index < z->recips->len) { g_string_append_c(buf, ' '); owl_string_append_quoted_arg(buf, z->recips->pdata[recip_index]); } return g_string_free(buf, false); } barnowl-1.10/zcrypt.c0000644000175000017500000005322313020626370011523 00000000000000/* zcrypt.c -- Read in a data stream from stdin & dump a decrypted/encrypted * * datastream. Reads the string to make the key from from the first * * parameter. Encrypts or decrypts according to -d or -e flag. (-e is * * default.) Will invoke zwrite if the -c option is provided for * * encryption. If a zephyr class is specified & the keyfile name omitted * * the ~/.crypt-table will be checked for "crypt-classname" and then * * "crypt-default" for the keyfile name. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_KERBEROS_IV #include #else #include #endif #include "filterproc.h" extern const char *version; /* Annotate functions in which the caller owns the return value and is * responsible for ensuring it is freed. */ #define CALLER_OWN G_GNUC_WARN_UNUSED_RESULT #define MAX_KEY 128 #define MAX_LINE 128 #define MAX_RESULT 4096 #ifndef TRUE #define TRUE -1 #endif #ifndef FALSE #define FALSE 0 #endif #define ZWRITE_OPT_NOAUTH (1<<0) #define ZWRITE_OPT_SIGNATURE (1<<1) #define ZWRITE_OPT_IGNOREVARS (1<<2) #define ZWRITE_OPT_VERBOSE (1<<3) #define ZWRITE_OPT_QUIET (1<<4) #define ZCRYPT_OPT_MESSAGE (1<<5) #define ZCRYPT_OPT_IGNOREDOT (1<<6) typedef struct { int flags; const char *signature; char *message; } ZWRITEOPTIONS; CALLER_OWN char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance); int ParseCryptSpec(const char *spec, const char **keyfile); CALLER_OWN char *BuildArgString(char **argv, int start, int end); CALLER_OWN char *read_keystring(const char *keyfile); int do_encrypt(int zephyr, const char *class, const char *instance, ZWRITEOPTIONS *zoptions, const char* keyfile, int cipher); int do_encrypt_des(const char *keyfile, const char *in, int len, FILE *out); int do_encrypt_aes(const char *keyfile, const char *in, int len, FILE *out); int do_decrypt(const char *keyfile, int cipher); int do_decrypt_aes(const char *keyfile); int do_decrypt_des(const char *keyfile); #define M_NONE 0 #define M_ZEPHYR_ENCRYPT 1 #define M_DECRYPT 2 #define M_ENCRYPT 3 #define M_RANDOMIZE 4 #define M_SETKEY 5 enum cipher_algo { CIPHER_DES, CIPHER_AES, NCIPHER }; typedef struct { int (*encrypt)(const char *keyfile, const char *in, int len, FILE *out); int (*decrypt)(const char *keyfile); } cipher_pair; cipher_pair ciphers[NCIPHER] = { [CIPHER_DES] = { do_encrypt_des, do_decrypt_des}, [CIPHER_AES] = { do_encrypt_aes, do_decrypt_aes}, }; static void owl_zcrypt_string_to_schedule(char *keystring, des_key_schedule *schedule) { #ifdef HAVE_KERBEROS_IV des_cblock key; #else des_cblock _key, *key = &_key; #endif des_string_to_key(keystring, key); des_key_sched(key, *schedule); } void usage(FILE *file, const char *progname) { fprintf(file, "Usage: %s [-Z|-D|-E|-R|-S] [-F Keyfile] [-c class] [-i instance]\n", progname); fprintf(file, " [-advqtluon] [-s signature] [-f arg] [-m message]\n"); fprintf(file, " One or more of class, instance, and keyfile must be specified.\n"); } int main(int argc, char *argv[]) { char *cryptspec = NULL; const char *keyfile; int cipher; int error = FALSE; int zephyr = FALSE; const char *class = NULL, *instance = NULL; int mode = M_NONE; int c; int messageflag = FALSE; ZWRITEOPTIONS zoptions; zoptions.flags = 0; enum { OPT_VERSION = CHAR_MAX + 1, OPT_HELP, }; static const struct option options[] = { {"version", no_argument, NULL, OPT_VERSION}, {"help", no_argument, NULL, OPT_HELP}, {NULL, 0, NULL, 0} }; while ((c = getopt_long(argc, argv, "ZDERSF:c:i:advqtluons:f:m", options, NULL)) != -1) { switch(c) { case OPT_VERSION: /* Version */ printf("This is zcrypt version %s\n", version); exit(0); case OPT_HELP: /* Help */ usage(stdout, argv[0]); exit(0); case 'Z': /* Zephyr encrypt */ mode = M_ZEPHYR_ENCRYPT; break; case 'D': /* Decrypt */ mode = M_DECRYPT; break; case 'E': /* Encrypt */ mode = M_ENCRYPT; break; case 'R': /* Randomize the keyfile */ mode = M_RANDOMIZE; break; case 'S': /* Set a new key value from stdin */ mode = M_SETKEY; break; case 'F': /* Specify the keyfile explicitly */ if (cryptspec != NULL) error = TRUE; cryptspec = optarg; break; case 'c': /* Zwrite/zcrypt: class name */ if (class != NULL) error = TRUE; class = optarg; break; case 'i': /* Zwrite/zcrypt: instance name */ if (instance != NULL) error = TRUE; instance = optarg; break; case 'a': /* Zwrite: authenticate (default) */ zoptions.flags &= ~ZWRITE_OPT_NOAUTH; break; case 'd': /* Zwrite: do not authenticate */ zoptions.flags |= ZWRITE_OPT_NOAUTH; break; case 'v': /* Zwrite: verbose */ zoptions.flags |= ZWRITE_OPT_VERBOSE; break; case 'q': /* Zwrite: quiet */ zoptions.flags |= ZWRITE_OPT_QUIET; break; case 't': /* Zwrite: no expand tabs (ignored) */ break; case 'l': /* Zwrite: ignore '.' on a line by itself (ignored) */ zoptions.flags |= ZCRYPT_OPT_IGNOREDOT; break; case 'u': /* Zwrite: urgent message */ instance = "URGENT"; break; case 'o': /* Zwrite: ignore zephyr variables zwrite-class, zwrite-inst, */ /* zwrite-opcode */ zoptions.flags |= ZWRITE_OPT_IGNOREVARS; break; case 'n': /* Zwrite: prevent PING message (always used) */ break; case 's': /* Zwrite: signature */ zoptions.flags |= ZWRITE_OPT_SIGNATURE; zoptions.signature = optarg; break; case 'f': /* Zwrite: file system specification (ignored) */ break; case 'm': /* Message on rest of line*/ messageflag = TRUE; break; case '?': error = TRUE; break; } if (error || messageflag) break; } if (class != NULL || instance != NULL) zephyr = TRUE; if (messageflag) { zoptions.flags |= ZCRYPT_OPT_MESSAGE; zoptions.message = BuildArgString(argv, optind, argc); if (!zoptions.message) { fprintf(stderr, "Memory allocation error.\n"); error = TRUE; } } else if (optind < argc) { error = TRUE; } if (mode == M_NONE) mode = (zephyr?M_ZEPHYR_ENCRYPT:M_ENCRYPT); if (mode == M_ZEPHYR_ENCRYPT && !zephyr) error = TRUE; if (!error && cryptspec == NULL && (class != NULL || instance != NULL)) { cryptspec = GetZephyrVarKeyFile(argv[0], class, instance); if(!cryptspec) { fprintf(stderr, "Unable to find keyfile for "); if(class != NULL) { fprintf(stderr, "-c %s ", class); } if(instance != NULL) { fprintf(stderr, "-i %s ", instance); } fprintf(stderr, "\n"); exit(-1); } } if (error || !cryptspec) { usage(stderr, argv[0]); exit(1); } cipher = ParseCryptSpec(cryptspec, &keyfile); if(cipher < 0) { fprintf(stderr, "Invalid cipher specification: %s\n", cryptspec); exit(1); } if (mode == M_RANDOMIZE) { /* Choose a new, random key */ /* FILE *fkey = fopen(fname, "w"); if (!fkey) printf("Could not open key file for writing: %s\n", fname); else { char string[100]; fputs(fkey, string); fclose(fkey); } */ fprintf(stderr, "Feature not yet implemented.\n"); } else if (mode == M_SETKEY) { /* Set a new, user-entered key */ char newkey[MAX_KEY]; FILE *fkey; if (isatty(0)) { printf("Enter new key: "); /* Really should read without echo!!! */ } if(!fgets(newkey, MAX_KEY - 1, stdin)) { fprintf(stderr, "Error reading key.\n"); return 1; } fkey = fopen(keyfile, "w"); if (!fkey) fprintf(stderr, "Could not open key file for writing: %s\n", keyfile); else { if (fputs(newkey, fkey) != strlen(newkey) || putc('\n', fkey) != '\n') { fprintf(stderr, "Error writing to key file.\n"); fclose(fkey); exit(1); } else { fclose(fkey); fprintf(stderr, "Key update complete.\n"); } } } else { if (mode == M_ZEPHYR_ENCRYPT || mode == M_ENCRYPT) error = !do_encrypt((mode == M_ZEPHYR_ENCRYPT), class, instance, &zoptions, keyfile, cipher); else error = !do_decrypt(keyfile, cipher); } /* Always print the **END** message if -D is specified. */ if (mode == M_DECRYPT) printf("**END**\n"); return error; } int ParseCryptSpec(const char *spec, const char **keyfile) { int cipher = CIPHER_DES; char *cipher_name = strdup(spec); char *colon = strchr(cipher_name, ':'); *keyfile = spec; if (colon) { char *rest = strchr(spec, ':') + 1; while(isspace(*rest)) rest++; *colon-- = '\0'; while (colon >= cipher_name && isspace(*colon)) { *colon = '\0'; } if(strcmp(cipher_name, "AES") == 0) { cipher = CIPHER_AES; *keyfile = rest; } else if(strcmp(cipher_name, "DES") == 0) { cipher = CIPHER_DES; *keyfile = rest; } } free(cipher_name); return cipher; } /* Build a space-separated string from argv from elements between start * * and end - 1. malloc()'s the returned string. */ CALLER_OWN char *BuildArgString(char **argv, int start, int end) { int len = 1; int i; char *result; /* Compute the length of the string. (Plus 1 or 2) */ for (i = start; i < end; i++) len += strlen(argv[i]) + 1; /* Allocate memory */ result = (char *)malloc(len); if (result) { /* Build the string */ char *ptr = result; /* Start with an empty string, in case nothing is copied. */ *ptr = '\0'; /* Copy the arguments */ for (i = start; i < end; i++) { char *temp = argv[i]; /* Add a space, if not the first argument */ if (i != start) *ptr++ = ' '; /* Copy argv[i], leaving ptr pointing to the '\0' copied from temp */ while ((*ptr = *temp++)) ptr++; } } return result; } #define MAX_BUFF 258 #define MAX_SEARCH 3 /* Find the class/instance in the .crypt-table */ CALLER_OWN char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance) { char *keyfile = NULL; char *varname[MAX_SEARCH]; int length[MAX_SEARCH], i; char buffer[MAX_BUFF]; const char *home; char *filename; char result[MAX_SEARCH][MAX_BUFF]; int numsearch = 0; FILE *fsearch; memset(varname, 0, sizeof(varname)); /* Determine names to look for in .crypt-table */ if (instance) varname[numsearch++] = g_strdup_printf("crypt-%s-%s:", (class?class:"message"), instance); if (class) varname[numsearch++] = g_strdup_printf("crypt-%s:", class); varname[numsearch++] = g_strdup("crypt-default:"); /* Setup the result array, and determine string lengths */ for (i = 0; i < numsearch; i++) { result[i][0] = '\0'; length[i] = strlen(varname[i]); } /* Open~/.crypt-table */ home = getenv("HOME"); if (home == NULL) home = g_get_home_dir(); filename = g_build_filename(home, ".crypt-table", NULL); fsearch = fopen(filename, "r"); if (fsearch) { /* Scan file for a match */ while (!feof(fsearch)) { if (!fgets(buffer, MAX_BUFF - 3, fsearch)) break; for (i = 0; i < numsearch; i++) if (strncasecmp(varname[i], buffer, length[i]) == 0) { int j; for (j = length[i]; buffer[j] == ' '; j++) ; strcpy(result[i], &buffer[j]); if (*result[i]) if (result[i][strlen(result[i])-1] == '\n') result[i][strlen(result[i])-1] = '\0'; } } /* Pick the "best" match found */ keyfile = NULL; for (i = 0; i < numsearch; i++) if (*result[i]) { keyfile = result[i]; break; } if (keyfile != NULL) { /* Prepare result to be returned */ char *temp = keyfile; keyfile = (char *)malloc(strlen(temp) + 1); if (keyfile) strcpy(keyfile, temp); else fprintf(stderr, "Memory allocation error.\n"); } fclose(fsearch); } else fprintf(stderr, "Could not open key table file: %s\n", filename); for(i = 0; i < MAX_SEARCH; i++) { g_free(varname[i]); } g_free(filename); return keyfile; } static pid_t zephyrpipe_pid = 0; /* Open a pipe to zwrite */ FILE *GetZephyrPipe(const char *class, const char *instance, const ZWRITEOPTIONS *zoptions) { int fildes[2]; pid_t pid; FILE *result; const char *argv[20]; int argc = 0; if (pipe(fildes) < 0) return NULL; pid = fork(); if (pid < 0) { /* Error: clean up */ close(fildes[0]); close(fildes[1]); result = NULL; } else if (pid == 0) { /* Setup child process */ argv[argc++] = "zwrite"; argv[argc++] = "-n"; /* Always send without ping */ if (class) { argv[argc++] = "-c"; argv[argc++] = class; } if (instance) { argv[argc++] = "-i"; argv[argc++] = instance; } if (zoptions->flags & ZWRITE_OPT_NOAUTH) argv[argc++] = "-d"; if (zoptions->flags & ZWRITE_OPT_QUIET) argv[argc++] = "-q"; if (zoptions->flags & ZWRITE_OPT_VERBOSE) argv[argc++] = "-v"; if (zoptions->flags & ZWRITE_OPT_SIGNATURE) { argv[argc++] = "-s"; argv[argc++] = zoptions->signature; } argv[argc++] = "-O"; argv[argc++] = "crypt"; argv[argc] = NULL; close(fildes[1]); if (fildes[0] != STDIN_FILENO) { if (dup2(fildes[0], STDIN_FILENO) != STDIN_FILENO) exit(0); close(fildes[0]); } close(fildes[0]); execvp(argv[0], (char **)argv); fprintf(stderr, "Exec error: could not run zwrite\n"); exit(0); } else { close(fildes[0]); /* Create a FILE * for the zwrite pipe */ result = (FILE *)fdopen(fildes[1], "w"); zephyrpipe_pid = pid; } return result; } /* Close the pipe to zwrite */ void CloseZephyrPipe(FILE *pipe) { fclose(pipe); waitpid(zephyrpipe_pid, NULL, 0); zephyrpipe_pid = 0; } #define BASE_CODE 70 #define LAST_CODE (BASE_CODE + 15) #define OUTPUT_BLOCK_SIZE 16 void block_to_ascii(unsigned char *output, FILE *outfile) { int i; for (i = 0; i < 8; i++) { putc(((output[i] & 0xf0) >> 4) + BASE_CODE, outfile); putc( (output[i] & 0x0f) + BASE_CODE, outfile); } } CALLER_OWN char *slurp_stdin(int ignoredot, int *length) { char *buf; char *inptr; if ((inptr = buf = (char *)malloc(MAX_RESULT)) == NULL) { fprintf(stderr, "Memory allocation error\n"); return NULL; } while (inptr - buf < MAX_RESULT - MAX_LINE - 20) { if (fgets(inptr, MAX_LINE, stdin) == NULL) break; if (inptr[0]) { if (inptr[0] == '.' && inptr[1] == '\n' && !ignoredot) { inptr[0] = '\0'; break; } else inptr += strlen(inptr); } else break; } *length = inptr - buf; return buf; } CALLER_OWN char *GetInputBuffer(ZWRITEOPTIONS *zoptions, int *length) { char *buf; if (zoptions->flags & ZCRYPT_OPT_MESSAGE) { /* Use the -m message */ buf = strdup(zoptions->message); *length = strlen(buf); } else { if (isatty(0)) { /* tty input, so show the "Type your message now..." message */ if (zoptions->flags & ZCRYPT_OPT_IGNOREDOT) printf("Type your message now. End with the end-of-file character.\n"); else printf("Type your message now. End with control-D or a dot on a line by itself.\n"); } else { zoptions->flags |= ZCRYPT_OPT_IGNOREDOT; } buf = slurp_stdin(zoptions->flags & ZCRYPT_OPT_IGNOREDOT, length); } return buf; } CALLER_OWN char *read_keystring(const char *keyfile) { char *keystring; FILE *fkey = fopen(keyfile, "r"); if(!fkey) { fprintf(stderr, "Unable to open keyfile %s\n", keyfile); return NULL; } keystring = malloc(MAX_KEY); if(!fgets(keystring, MAX_KEY-1, fkey)) { fprintf(stderr, "Unable to read from keyfile: %s\n", keyfile); free(keystring); keystring = NULL; } fclose(fkey); return keystring; } /* Encrypt stdin, with prompt if isatty, and send to stdout, or to zwrite if zephyr is set. */ int do_encrypt(int zephyr, const char *class, const char *instance, ZWRITEOPTIONS *zoptions, const char *keyfile, int cipher) { FILE *outfile = stdout; char *inbuff = NULL; int buflen; int out = TRUE; inbuff = GetInputBuffer(zoptions, &buflen); if(!inbuff) { fprintf(stderr, "Error reading zcrypt input!\n"); return FALSE; } if (zephyr) { outfile = GetZephyrPipe(class, instance, zoptions); if (!outfile) { fprintf(stderr, "Could not run zwrite\n"); if (inbuff) free(inbuff); return FALSE; } } out = ciphers[cipher].encrypt(keyfile, inbuff, buflen, outfile); if (zephyr) CloseZephyrPipe(outfile); free(inbuff); return out; } int do_encrypt_des(const char *keyfile, const char *in, int length, FILE *outfile) { des_key_schedule schedule; unsigned char input[8], output[8]; const char *inptr; int num_blocks, last_block_size; char *keystring; int size; keystring = read_keystring(keyfile); if(!keystring) { return FALSE; } owl_zcrypt_string_to_schedule(keystring, &schedule); free(keystring); inptr = in; num_blocks = (length + 7) / 8; last_block_size = ((length + 7) % 8) + 1; /* Encrypt the input (inbuff or stdin) and send it to outfile */ while (TRUE) { /* Get 8 bytes from buffer */ if (num_blocks > 1) { size = 8; memcpy(input, inptr, size); inptr += 8; num_blocks--; } else if (num_blocks == 1) { size = last_block_size; memcpy(input, inptr, size); num_blocks--; } else size = 0; /* Check for EOF and pad the string to 8 chars, if needed */ if (size == 0) break; if (size < 8) memset(input + size, 0, 8 - size); /* Encrypt and output the block */ des_ecb_encrypt(&input, &output, schedule, TRUE); block_to_ascii(output, outfile); if (size < 8) break; } putc('\n', outfile); return TRUE; } int do_encrypt_aes(const char *keyfile, const char *in, int length, FILE *outfile) { char *out; int err, status; const char *argv[] = { "gpg", "--symmetric", "--no-options", "--no-default-keyring", "--keyring", "/dev/null", "--secret-keyring", "/dev/null", "--batch", "--quiet", "--no-use-agent", "--armor", "--cipher-algo", "AES", "--passphrase-file", keyfile, NULL }; err = call_filter(argv, in, &out, &status); if(err || status) { g_free(out); return FALSE; } fwrite(out, strlen(out), 1, outfile); g_free(out); return TRUE; } /* Read a half-byte from stdin, skipping invalid characters. Returns -1 if at EOF or file error */ int read_ascii_nybble(void) { char c; while (TRUE) { if (fread(&c, 1, 1, stdin) == 0) return -1; else if (c >= BASE_CODE && c <= LAST_CODE) return c - BASE_CODE; } } /* Read both halves of the byte and return the single byte. Returns -1 if at EOF or file error. */ int read_ascii_byte(void) { int c1, c2; c1 = read_ascii_nybble(); if (c1 >= 0) { c2 = read_ascii_nybble(); if (c2 >= 0) { return c1 * 0x10 + c2; } } return -1; } /* Read an 8-byte DES block from stdin */ int read_ascii_block(unsigned char *input) { int c; int i; for (i = 0; i < 8; i++) { c = read_ascii_byte(); if (c < 0) return FALSE; input[i] = c; } return TRUE; } /* Decrypt stdin */ int do_decrypt(const char *keyfile, int cipher) { return ciphers[cipher].decrypt(keyfile); } int do_decrypt_aes(const char *keyfile) { char *in, *out; int length; const char *argv[] = { "gpg", "--decrypt", "--no-options", "--no-default-keyring", "--keyring", "/dev/null", "--secret-keyring", "/dev/null", "--batch", "--no-use-agent", "--quiet", "--passphrase-file", keyfile, NULL }; int err, status; in = slurp_stdin(TRUE, &length); if(!in) return FALSE; err = call_filter(argv, in, &out, &status); free(in); if(err || status) { g_free(out); return FALSE; } fwrite(out, strlen(out), 1, stdout); g_free(out); return TRUE; } int do_decrypt_des(const char *keyfile) { des_key_schedule schedule; unsigned char input[8], output[8]; char tmp[9]; char *keystring; /* DES decrypts 8 bytes at a time. We copy those over into the 9-byte 'tmp', which has the final byte zeroed, to ensure that we always have a NULL-terminated string we can call printf/strlen on. We don't pass 'tmp' to des_ecb_encrypt directly, because it's prototyped as taking 'unsigned char[8]', and this avoids a stupid cast. We zero 'tmp' entirely, not just the final byte, in case there are no input blocks. */ memset(tmp, 0, sizeof tmp); keystring = read_keystring(keyfile); if(!keystring) return FALSE; owl_zcrypt_string_to_schedule(keystring, &schedule); free(keystring); while (read_ascii_block(input)) { des_ecb_encrypt(&input, &output, schedule, FALSE); memcpy(tmp, output, 8); printf("%s", tmp); } if (!tmp[0] || tmp[strlen(tmp) - 1] != '\n') printf("\n"); return TRUE; } barnowl-1.10/help.c0000644000175000017500000001370613020626370011122 00000000000000#include "owl.h" void owl_help(void) { const owl_variable *v; owl_fmtext fm; const char *varname; GPtrArray *varnames; int i; owl_fmtext_init_null(&fm); owl_fmtext_append_bold (&fm, "OWL HELP\n\n"); owl_fmtext_append_normal (&fm, " If you're new to BarnOwl, the first thing you should type is\n\n" " :show quickstart\n\n" " For help on a specific command use 'help '\n" " For information on advanced keys, use 'show keymaps'.\n" " For information on advanced commands, use 'show commands'.\n" " For information on variables, use 'show variables'.\n\n"); owl_fmtext_append_bold (&fm, " Basic Keys:\n" ); owl_fmtext_append_normal (&fm, " n Move to next non-deleted message\n" " p Move to previous non-deleted message\n" " C-n , down Move to next message\n" " C-p , up Move to previous message\n" " < , > Move to first, last message\n" " right , left Scroll screen left or right\n" " C-v Page down\n" " M-v Page up\n" " i Print more information about a message\n" " P Move to the next personal message\n" " M-P Move to the previous personal message\n" " C-space Move the mark (asterisk) to the current message\n" " C-x C-x Move the mark to the current message while moving to previous mark\n" "\n" " d Mark message for deletion\n" " u Undelete a message marked for deletion\n" " x Expunge deleted messages\n" " X Expunge deleted messages and switch to home view\n" " T Mark all 'trash' messages for deletion\n" " M-D Mark all messages in current view for deletion\n" " M-u Unmark all messages in the current view for deletion\n" "\n" " z Start a zwrite command\n" " a Start an aimwrite command\n" " r Reply to the current message\n" " R Reply to sender\n" " C-r Reply but allow editing of reply line\n" "\n" " M-n View zephyrs in selected conversation\n" " M-N View zephyrs in selected conversation of instance\n" " M-p View only personal zephyrs\n" " V Change to back to home view ('all' by default)\n" " v Start a view command\n" " ! Invert the current view\n" "\n" " l Print a zephyr/AIM buddy listing\n" " A Toggle away\n" " o Toggle one-line display mode\n" " w Open a URL in the current message\n" " C-l Refresh the screen\n" " C-z Suspend BarnOwl\n" " h Print this help message\n" " : , M-x Enter command mode\n" "\n" " / Forward search\n" " ? Reverse search\n" "\n\n" ); owl_fmtext_append_bold (&fm, " Basic Commands:\n" ); owl_fmtext_append_normal (&fm, " quit, exit Exit BarnOwl\n" " help Get help about commands\n" " show Show information about BarnOwl (see detailed help)\n" "\n" " zwrite Send a zephyr\n" " aimlogin Login to AIM\n" " aimwrite Send an AIM message\n" "\n" " addbuddy Add a zephyr or AIM buddy\n" " zaway Turn zaway on or off, or set the message\n" " zlocate Locate a user\n" " subscribe Subscribe to a zephyr class or instance\n" " unsubscribe Unsubscribe to a zephyr class or instance\n" " blist Print a list of zephyr and AIM buddies logged in\n" " search Search for a text string\n" "\n" " set Set a variable (see list below)\n" " print Print a variable's value (variables listed below)\n" " startup Set a command to be run at every BarnOwl startup\n" " unstartup Remove a command to be run at every BarnOwl startup\n" "\n" " getsubs Print a list of current subscriptions\n" " unsuball Unsubscribe from all zephyr classes\n" " load-subs Load zephyr subscriptions from a file\n" " zpunt Suppress messages from a zephyr triplet\n" " zlog Send a login or logout notification\n" " zlist Print a list of zephyr buddies logged in\n" " alist Print a list of AIM buddies logged in\n" " info Print detailed information about the current message\n" " filter Create a message filter\n" " view View messages matching a filter\n" " viewuser View messages to or from a particular user\n" " viewclass View messages to a particular class\n" " expunge Expunge messages marked for deletion\n" " bindkey Create a new key binding\n" " alias Create a command alias\n" " dump Dump messagelist as text to a file\n" "\n" " about Print information about BarnOwl\n" " status Print status information about the running BarnOwl\n" " version Print the version number of BarnOwl\n" "\n"); /* help for variables */ owl_fmtext_append_bold(&fm, "Variables:\n"); varnames = owl_variable_dict_get_names(owl_global_get_vardict(&g)); for (i = 0; i < varnames->len; i++) { varname = varnames->pdata[i]; if (varname && varname[0]!='_') { v = owl_variable_get_var(owl_global_get_vardict(&g), varname); owl_variable_describe(v, &fm); } } owl_ptr_array_free(varnames, g_free); owl_fmtext_append_normal(&fm, "\n"); owl_function_popless_fmtext(&fm); owl_fmtext_cleanup(&fm); } barnowl-1.10/pair.c0000644000175000017500000000062213020626370011116 00000000000000#include "owl.h" void owl_pair_create(owl_pair *p, const char *key, char *value) { p->key=key; p->value=value; } void owl_pair_set_key(owl_pair *p, const char *key) { p->key=key; } void owl_pair_set_value(owl_pair *p, char *value) { p->value=value; } const char *owl_pair_get_key(const owl_pair *p) { return(p->key); } char *owl_pair_get_value(const owl_pair *p) { return(p->value); } barnowl-1.10/ChangeLog0000644000175000017500000026643213055166600011611 000000000000001.10 * No changes above what's already in 1.10rc1 1.10rc1 * Numerous autotools/build machinery fixes -andersk@mit.edu * Numerous code correctness and simplification/cleanup fixes -andersk@mit.edu * Add and use a cpanfile documenting perl module dependencies -jgross@mit.edu * Add Travis configuration -jgross@mit.edu * Avoid strchrnul -andersk@mit.edu * Numerous IRC fixes -jgross@mit.edu * Improve smartnarrow and smartfilter documentation -jgross@mit.edu * filterproc: Rewrite using GIOChannel -andersk@mit.edu * Implement :twitter-favorite -nelhage@nelhage.com * Kill the client-side tweet length check. -nelhage@nelhage.com * squelch the Twitter legacy_list_api warnings -nelhage@nelhage.com * Use SSL for Twitter by default -adehnert@mit.edu * Humanize zsigs -andersk@mit.edu * Show Zephyr charset in info popup -andersk@mit.edu * Fix Jabber SRV record support (at one point fixed connecting via jabber to google talk or facebook) -james2vegas@aim.com * fix cmd_join in BarnOwl/Module/IRC.pm -james2vegas@aim.com * Add a ~/.owl/ircchannels file, persist channels -jgross@mit.edu * Added hooks for user going idle or active. -jgross@mit.edu * Support channel-or-user IRC commands, and setup irc-msg to use it. -ezyang@mit.edu * Refactor perl calls through a single method -jgross@mit.edu * Really support building Perl modules from a separate builddir -andersk@mit.edu * Get rid of all our embedded copies of Module::Install -andersk@mit.edu * Don't let new_variable_* overriding previously set values -rnjacobs@mit.edu * Messages sent to 'class messages' are not personal -jgross@mit.edu * Expose message_matches_filter to perl -jgross@mit.edu * Fail fast on -c filsrv, which most people won't have permission to send to -rnjacobs@mit.edu * zcrypt: Use getopt_long for argument parsing -andersk@mit.edu * zcrypt: Accept -help and --version -andersk@mit.edu * barnowl --help: Write to stdout and exit successfully -andersk@mit.edu * Don't swallow errors in :unsuball -davidben@mit.edu * Allow testing in a separate build directory -andersk@mit.edu * Add support for arbitrary Perl subs for getters and setters for barnowl variables -glasgall@mit.edu * owl_zephyr_loadsubs: Don’t leak memory on error opening ~/.zephyr.subs -andersk@mit.edu * Make :loadsubs reload instanced personals too -davidben@mit.edu * Fix some undefined behavior in filter.c, caught by clang scan-build -jgross@mit.edu * Die on a failed zephyr_zwrite; don't silently ignore it -jgross@mit.edu * Fix a memory leak in zcrypt.c, caught by clang scan-build -jgross@mit.edu * zcrypt: Make gpg stop messing around in ~/.gnupg -andersk@mit.edu * Fix display of pseudologins -davidben@mit.edu * Unbundle random Facebook module libraries -davidben@mit.edu * Replace deprecated GLib < 2.31.0 APIs -andersk@mit.edu * Abstract g->interrupt_lock -andersk@mit.edu * zephyr: Replace outgoing default format with a small URL -geofft@mit.edu 1.9 * Update Jabber module for Net::DNS changes -james2vegas@aim.com * Update and make configurable the Zephyr default format -adehnert@mit.edu * Fix a crash when zcrypt fails -andersk@mit.edu * Fix building with OpenSSL before 0.9.8 -andersk@mit.edu * Make :loadsubs reload instanced personals too -davidben@mit.edu * Make Perl zephyr_zwrite call die() when it fails -jgross@mit.edu * Tell gpg calls from zcrypt to ignore ~/.gnupg -andersk@mit.edu * Replace outgoing zephyr default format with a small URL -geofft@mit.edu * Add getnumlines() to perl interface -asedeno@mit.edu * Include names of invalid filters on filter errors -adehnert@mit.edu * Don't incorrectly mark decryption failures as decrypted -davidben@mit.edu * Hide the default cursor when possible -davidben@mit.edu * Complete viewperson and vp as viewuser and vu -davidben@mit.edu * Set z_charset = ZCHARSET_UTF_8 -andersk@mit.edu * Allow zsender spoofing on cross-realm classes -andersk@mit.edu * Append the realm to the zsender if missing -andersk@mit.edu * Redisplay on setting colorztext -jgross@mit.edu * Rename default config file to .owl/init.pl -kevinr@free-dissociation.com * Add completion for jabberlogout -adehnert@mit.edu * Switch to interactive context before sourcing the startup file -davidben@mit.edu * Add completion for reload-module -adehnert@mit.edu * editwin callback for canceling the editwin -jgross@mit.edu * Fix dirtying windows inside a redraw handler -davidben@mit.edu * Facebook module -ezyang@mit.edu * Complete unstartup command just like startup command -jgross@mit.edu * Fix the description of disable-ctrl-d -jgross@mit.edu * Use wbkgrndset instead of wbkgdset in _owl_fmtext_wcolor_set -davidben@mit.edu * Show the time zone in :info -jgross@mit.edu * Treat [!.?]" as end of sentence in edit:fill-paragraph -jgross@mit.edu * Correctly display multiline fields in :info -jgross@mit.edu 1.8.1 * Only add outgoing messages for personal part of half-personal messages -andersk@mit.edu * Don’t write CC: line on zwrite -C '' -andersk@mit.edu * Don’t send public pings on zwrite '' or zwrite @REALM -andersk@mit.edu * Don’t treat zwrite '' as personal -andersk@mit.edu * Stop pretending to support zwrite * -andersk@mit.edu * Show foreign realms on non-personal zephyrs like Owl did -andersk@mit.edu * Fix memory leak in zcrypt -davidben@mit.edu * Don't attempt to switch filters in :view -d if invalid -davidben@mit.edu * Fixed typo in unbindkey usage error -rileyb@mit.edu * Fix bug generating filter text in 256-color mode -asedeno@mit.edu * Remove ^noc from reply-lockout -geofft@mit.edu * Avoid quadratic loops when receiving zephyrs -andersk@mit.edu * Fix hang on empty zcrypt messages -adehnert@MIT.EDU 1.8 * Compute the home directory in zcrypt consistently with BarnOwl -davidben@mit.edu * Make help show the correct keybinding for A -jgross@mit.edu * Add a delete-and-expunge command. -jgross@mit.edu * Fix a bug in the expunge command -jgross@mit.edu * Replace 'Owl' with 'BarnOwl' in user visible places -jgross@mit.edu * Allow zsigs to be '0' -jgross@mit.edu * Reformat the man page to look more like others -davidben@mit.edu * Consistently use BarnOwl or barnowl -davidben@mit.edu * Update autoconf macros -andersk@mit.edu * history: Do not deduplicate a partial entry -andersk@mit.edu * Drop show timers feature -davidben@mit.edu * Add new dependencies, AnyEvent and perl-Glib -davidben@mit.edu * Bump required glib version to 2.16 -davidben@mit.edu * Don't leak timestr when setting time in a perl message -asedeno@mit.edu * Build with -Wwrite-strings -andersk@mit.edu * Build with C99 -davidben@mit.edu * Jabber: Handle nicks with leading dashes (e.g. Facebook XMPP) -ezyang@mit.edu * Move log-writing onto a background thread. -adam@crossproduct.net * Remove the length limit on field values in :info -jgross@mit.edu * Show how far you are in a long message -jgross@mit.edu * stderr_redirect_handler: Handle partial or failed reads -andersk@mit.edu * Inform the user when an unpunt command does nothing -davidben@mit.edu * Replace custom event loop with GLib's GMainLoop -davidben@mit.edu * Encode glib version requirements in pkg-config check -asedeno@mit.edu * Fix color pair usage on ncurses builds without ext-color -davidben@mit.edu * IRC: Fix reconnect behavior. -nelhage@mit.edu * IRC: Make nick-change events LOGIN messages instead of ADMIN. -nelhage@mit.edu * IRC: Port module to AnyEvent::IRC. -asedeno@mit.edu, nelhage@nelhage.com * Ability to set exposure arbitrarily (like "zctl set exposure") -jgross@mit.edu * Kill --remove-debug option -davidben@mit.edu * exec: Fix input redirection of multistatement commands -andersk@mit.edu * Correctly set the realm in outgoing zwrite errors -davidben@mit.edu * Correctly compute the realm for outgoing messages -davidben@mit.edu * In duplicated outgoing zephyrs only reply on the relevant recipient -davidben@mit.edu * Create per-recipient copies of outgoing messages for non-CC'd personals -liudi@mit.edu * Add black to :show colors -andersk@mit.edu * Fix reporting of errors from libzephyr -kcr@1ts.org * Load Encode module for IRC. -timhill@alum.mit.edu * IRC: Sort the output of :irc-names -nelhage@mit.edu * Prepend "UNAUTH: " to displayed sender for unauthenticated zephyrs -adam@crossproduct.net * For ‘punt’ with one argument, quote the filter name -andersk@mit.edu * Fix spurious error running ‘punt’ with no arguments -andersk@mit.edu * Only handle CCs in messages sent directly to you. -davidben@mit.edu * Update copyright notices for 2011 -davidben@mit.edu * If a smartfilter fails to parse, handle the error -davidben@mit.edu * Replace per-editwin killbuf with a global one. -adam@crossproduct.net * Don't use error_message if we are building without Zephyr. -nelhage@mit.edu * Fix replying to outgoing zwrite when -m is passed -davidben@mit.edu * Fix a number of quoting bugs -davidben@mit.edu * Check passwd entries to determine home dir -davidben@mit.edu 1.7.1 * Append sender's realm to CC'd unqualified names when replying. -adam@crossproduct.net * Don't reset ncurses colorpairs in the middle of drawing. -davidben@mit.edu * Fix viewuser when an unqualified name is given. -davidben@mit.edu 1.7 * Fix quoting bugs in smartfilter, zpunt, and numerous other commands. -davidben@mit.edu * Download Twitter consumer keys from barnowl.mit.edu. -nelhage@MIT.EDU * Fix unsub when .zephyr.subs is a symlink. -jgross@MIT.EDU * Display subject as XMPP personal context (if set). -adehnert@mit.edu * Allow adding text to the command history. -adehnert@mit.edu * Fix webzephyr handling. -asedeno@mit.edu * Fix searching for text containing '!'. -andersk@mit.edu * Fix a number of memory leaks. -davidben@mit.edu * Correctly narrow on personals from realm-less senders. -davidben@mit.edu * Add a random zsig function -kevinr@free-dissociation.com * Implement searching in popup windows (help, etc.). davidben@mit.edu * When a zwrite fails, display a more accurate error than "Waiting for ack". davidben@mit.edu * Fix editwin motion for empty first lines -davidben@mit.edu * Handle incoming messages with tab characters better. -davidben@mit.edu * Use fpathconf to disable signals -asedeno@mit.edu * Fix tab-completion of aliases. -nelhage@mit.edu * Fix a crash and some bugs in 'zcrypt'. -nelhage@mit.edu * Display the cleartext on outgoing zcrypted personals. -nelhage@mit.edu * Add owl_window framework to allow more flexible UI. -davidben@mit.edu * Display submap bindings in :show keymap KEYMAP. -davidben@mit.edu * Make unit test environment more consistent with standard BarnOwl. -nelhage@mit.edu * Jabber: Set long_sender in a MUC to the full sender JID (from presence). -andersk@mit.edu * Do not instantiate various timers unless used. -davidben@mit.edu * Make smartnarrow work better on CC:'d personals. -nelhage@mit.edu * Set edit:maxwrapcols to 70 by default. -andersk@mit.edu * Allow disabling of both automatic wrapping and filling, display soft line-breaks. -nelhage@mit.edu * Fix a bug in editwin redraw with echochar set. -nelhage@mit.edu * Refactor resize code to cut down on flicker and relayout the popwin. -davidben@mit.edu * Make viewperson, vp aliases for viewuser. -kevinr@free-dissociation.com * Import Twitter module into main tree. -nelhage@mit.edu 1.6.2 * Use a uniquified debug file location. -nelhage@mit.edu * Open the debug file using O_EXCL and an explicit mode. -nelhage@mit.edu * Don't send AIM passwords to the debug log. -geofft@mit.edu * Remove some dead AIM code that sends local files to the server. -geofft@mit.edu * Handle errors from ZPending and ZReceiveNotice (CVE-2010-2725). -nelhage@mit.edu * Include the public repository URL in the README -alexmv@mit.edu * Install the documentation in 'make install'. -nelhage@mit.edu * Add a configure flag to enable/disable building with krb4. -wthrowe@mit.edu * Fix an infinite loop on 'view -r args'. -nelhage@mit.edu * Free paths to Zephyr dot-files when non-existant -davidben@mit.edu * Jabber: Accept a -m argument to jwrite to set the message. -nelhage@mit.edu 1.6.1 * Jabber: Explain how to set your nick when joining a MUC. -andersk@mit.edu * Jabber: Make smartnarrow -i filter on subject. -andersk@mit.edu * Jabber: Fix completion of MUC names. -nelhage@mit.edu * Improve help for bindkey and unbindkey -leonidg@mit.edu * Fix a segfault in smartnarrow. -nelhage@mit.edu * Fix a race in handling of resize events. -andersk@mit.edu 1.6 * Support filtering on whether a message has been deleted. -nelhage@mit.edu * Properly quote strings containing newlines or tabs. -nelhage@mit.edu * Check for an unset mark in owl_editwin_replace_region. -nelhage@mit.edu * Add the "narrow-related" variable. -geofft@mit.edu * Fix a display bug under perl 5.12. -nelhage@mit.edu * Only use typewindelta when opening multiline editwins. -nelhage@ksplice.com * Add some checks to ./configure. -nelhage@mit.edu * Fix a use-after-free in popexec.c -nelhage@mit.edu * Make pseudologins asynchronous -asedeno@mit.edu * Fix some bugs in editwin handling and clean up code. -nelhage@ksplice.com * Add new command unbindkey for removing keybindings -leonidg@mit.edu * zcrypt: Implement AES encryption support using GPG. -nelhage@mit.edu * Add usage messages to everything in scripts/ -nelhage@mit.edu * Split zcrypt into an external, standalong binary. -nelhage@mit.edu * Fix minor documentation typo -alexmv@mit.edu * Document the init/cleanup vs. new/delete naming conventions. -andersk@mit.edu * Clean up code naming conventions to help avoid memory leaks.. -andersk@mit.edu * Add edit:help command for zsh-style in-edit help -davidben@mit.edu * Use libpanel to simplify and improve display layer. -davidben@mit.edu * Jabber: Mention [-a ] in :help jwrite. -andersk@mit.edu * Fix zcrypt when compiling without krb4 -oremanj@MIT.EDU * Send multiple PRIVMSGs for IRC messages entered as multiple paragraphs -oremanj@mit.edu * Require automake ≥ 1.7.0, and don’t warn about portability to non-GNU make. -andersk@mit.edu * Makefile.am: Use only direct children in SUBDIRS, to appease automake 1.7. -andersk@mit.edu * IRC: irc-disconnect on a pending reconnect should cancel it. -nelhage@mit.edu * Complete several commands that accept a filename. -nelhage@mit.edu * Complete the 'print' and 'bindkey' commands. -nelhage@mit.edu 1.5.1 * Fix numerous memory leaks. -andersk@mit.edu * owl_message_get_cc_without_recipient: Don’t overflow the output buffer. -andersk@mit.edu (Fixes CVE-2010-0793) * owl_command_aimwrite: Fix a buffer overflow on aimwrite -m. -andersk@mit.edu * zcrypt: Don’t read off the end of misaligned input messages. -andersk@mit.edu * Fix zcrypt when compiling without krb4 -oremanj@MIT.EDU * Fix a crash narrowing to certain messages. -andersk@mit.edu * Fix a subtle bug in the perl bindings. -nelhage@mit.edu * Squelch an 'uninitialized' warning in recv:shift-left. -nelhage@mit.edu 1.5 * Show the prompt in short editwins when scrolling back to the start. -nelhage@mit.edu * Improve handling of some Jabber messages. -asedeno@mit.edu * Allow ^Z to be rebound. -nelhage@mit.edu * Skip some IRC admin messages by default, controlled by irc:skip -alexmv@mit.edu * Reconnect and re-join channels on IRC disconnect -alexmv@mit.edu * Correct the --with-libzephyr help string to --with-zephyr. -andersk@mit.edu * Improve performance narrowing to certain filters. -nelhage@mit.edu * Add completion for :filter* -adehnert@mit.edu * Fix filter* -adehnert@mit.edu * Mark the current mark with an asterisk -davidben@mit.edu * Complete class names for the 'unsub' command. -nelhage@mit.edu * Make control characters human-readable -kcr@1ts.org * Further complete the show command -davidben@mit.edu * Fix a bug reflowing text in the editwin. -davidben@mit.edu * Reconnect to MUCs when reconnecting to Jabber. -asedeno@mit.edu * Fix spurious trailing newlines in zsigs. -andersk@mit.edu * Fix the behavior of the zsig variable. -kcr@1ts.org * Drop owl_animate_hack. -asedeno@mit.edu * Add IRC server and channel listing to buddylist -alexmv@mit.edu * Make Jabber try to reconnect when disconnected, at exponential intervals -alexmv@mit.edu * Better documentation for jabberlogout. -asedeno@mit.edu * jabberlogout -a --> jabberlogout -A -asedeno@mit.edu * Change the default jabber resource to 'barnowl' -asedeno@mit.edu * Updated Jabber documentation for consistency. -zhangc@mit.edu * Document :bindkey more clearly. -geofft@mit.edu 1.4 * Fix description of edit:history-next -davidben@mit.edu * Don’t loop infinitely on matching the empty string. -andersk@mit.edu * Fix a typo in the jroster help message. -asedeno@mit.edu * IRC: Handle 'nosuchchannel' events. -nelhage@mit.edu * Add a function for perl to query whether Zephyr is available. -nelhage@mit.edu * Add a perl hook that is called once Zephyr is initialized. -nelhage@mit.edu * AIM: Decode incoming messages properly. -nelhage@mit.edu * AIM: Correctly send outgoing IMs with high-bit characters. -nelhage@mit.edu * IRC: Encode outgoing messages as utf-8. -nelhage@mit.edu * Return unicode strings to perl. -nelhage@mit.edu * IRC: Fix '-a' with commands that take a channel. -nelhage@mit.edu * Catch ^Z and display a message instead of suspending. -nelhage@mit.edu * Fix missing commands from command completion. -nelhage@mit.edu * Make kill-region stop killing extra bytes after multibyte characters. -andersk@mit.edu * Squelch some 'uninitialized' warnings in IRC completion. -nelhage@mit.edu * Add minimal completion for 'aimwrite'. -nelhage@mit.edu * Zephyr completion: Convert fields to lowercase for completing. -nelhage@mit.edu * Implement a shift_words method on completion contexts. -nelhage@mit.edu * Export skiptokens to perl. -nelhage@mit.edu * owl_text_quote: Don’t leak a kretch-sized buffer. -andersk@mit.edu * Spread the background color across the right hand side of messages -kcr@1ts.org * Perl callout for zsig computation + move default to perl -kcr@1ts.org * BarnOwl::get_zephyr_variable gets you a .zephyr.vars variable -kcr@1ts.org * Correctly prototype functions with no parameters as foo(void), not foo(). -andersk@mit.edu * Cause unsub to warn user if user wasn't subbed -davidben@mit.edu * Refresh popwin border when we redisplay viewwin -davidben@mit.edu * owl_command_zcrypt: Fix a compile warning building without zcrypt. -nelhage@mit.edu * Compile with warnings enabled by default. -andersk@mit.edu * Add equivalent long options for all short options. -nelhage@mit.edu * Remove defunct TODO and BUGS files. -nelhage@mit.edu * editwin: Properly update points inside a replaced region. -nelhage@mit.edu * Shift-R on CC zephyrs should go to the sender only -adehnert@mit.edu * BarnOwl::Module::Jabber: Quote jroster auth, deauth commands. -andersk@mit.edu * Use automake’s silent-rules mode if available, for quieter build output. -andersk@mit.edu * Add configurable time display -adehnert@mit.edu * Add BarnOwl::redisplay() -asedeno@mit.edu * Bind C-v and M-v in popless windows -nelhage@mit.edu * Fix an off by one error in some editwin code. -asedeno@mit.edu * Make zdots work even if the buffer has trailing whitespace. -nelhage@mit.edu * Fix pseudo-login interation with zephyr initialization. -asedeno@mit.edu * Correct the --with-libzephyr help message in the configure script. -broder@mit.edu * Set the UTF-8 flag on on strings we pass to Perl. -nelhage@mit.edu * aim.c, perlconfig.c: Fix format string bugs. -andersk@mit.edu * BarnOwl::Completion: Use multi-argument quote. -andersk@mit.edu * Jabber: Add quoting for editwin prompt. -andersk@mit.edu * IRC: Add quoting for reply commands and editwin prompt. -andersk@mit.edu * Fix quoting for filterappend, filterand, filteror. -andersk@mit.edu * skiptokens: Handle quotes more correctly. -nelhage@mit.edu 1.3 * Clean up the edit window code significantly. -kcr * Support inputting tabs in the editwin. -kcr * Support C-y for yanking text in the editwin. -kcr * Implement some convenience commands for working with filters. -adehnert * IRC: Fix "ARRAY(0x...)" at the start of 'whois' output. -nelhage * Expands tabs to 8 spaces in incoming and outgoing messages. -nelhage * Make 'zwrite -C ... -m ...' add a CC: line. -nelhage * Switch the build system to use automake. -nelhage * Make BarnOwl::$COMMAND to warn if it tokenizes its arguments. -nelhage * Expose more editwin functionality to perl. -nelhage * Quash a zephyr 3 warning by adding some missing consts. -andersk * Fix crash on malformed multi command. -andersk * owl_command_punt_unpunt: Plug memory leak. -andersk * stderr_redirect_handler: Plug a memory leak. -andersk * Jabber: Sort roster entries. -asedeno * Get rid of a whole bunch of useless casts. -andersk * Reimplement search in terms of owl_regex. -andersk * Export owl_function_debugmsg to perl as BarnOwl::debug(). -nelhage * Implement a tab-completion framework. -nelhage * Tab-complete commands. -nelhage * Tab-complete zephyr commands. -nelhage * Tab-complete help command. -davidben * Tab-complete :jwrite. -asedeno * Tab-complete :filter. -davidben * Tab-complete IRC commands. -broder * Tab-complete the :show command. nelhage * Tab-complete :vu and :vc. -nelhage * Tab-complete :set and :getvar. -davidben * Tab-complete :view. -davidben * Improve JID resolution. -asedeno * Quash some unused variable warnings building --without-zephyr. -andersk * Use 'const' modifiers in the source where appropriate. -andersk 1.2.1 * Fix building with Zephyr support. -nelhage * Support --with-stack-protector in 'configure'. -nelhage 1.2 * Fix some typos in source and messages. -adehnert * Support an explicit --with{out,}-zephyr configure option. -nelhage * Display a nicer error in :blist if .anyone doesn't exist. -geofft * Don't zcrypt shift-R replies to zcrypted messages -adehnert * Export a time_t for messages to perl as 'unix_time' -nelhage * Get rid of cryptic numeric messages after IRC commands. -ezyang * IRC: Include IRC admin messages in the 'irc' filter. -geofft * Fix M-LEFT and M-RIGHT bindings. -nelhage * Fix replycmd to use right class/instance -adehnert * Allow SIGINT to interrupt getting the Zephyr buddy list -nelhage * Break perlwrap.pm into multiple files. -nelhage * Handle errors in perlwrap.pm better. -nelhage * Don't attempt to send a Zephyr logout if we never initialized Zephyr. -nelhage * Display personals better in OneLine mode. -adehnert * Display context for pings -adehnert * Support --program-{prefix,suffix,transform}. -nelhage * Send instanced pings and give useful error messages -adehnert * Add to default BarnOwl subs. -adehnert * Maintain instance when using shift-R on personals -adehnert * Improve handling of outgoing instanced personals -adehnert * Don't require personals to be -i personal. -geofft * Display context for personals, so as to make usable. -geofft * Implement mark and swap in the message list. -asedeno * Fix handling of C-SPACE. -nelhage * Fix some warnings. -nelhage * Handle SIGINT, and make ^C interrupt searches. -nelhage * Fix the usage line for punt/unpunt -nelhage * Small bugfixes to release scripts. -nelhage 1.1.1 * Fix bogus errors 'subscribing to login messages'. -nelhage * Correctly send Zephyr login notices at startup. -nelhage * Fix compilation with Zephyr support. -alexmv * Fix an issue with incoming Zephyrs being delayed. -asedeno * Fix display of zpunt lines. -asedeno * Handle invalid regular expressions better (fix a segfault). -nelhage * Correctly handle zpunts with recipient %me%. -nelhage * Always send outgoing Zephyrs in utf-8. -nelhage * Fix documentation for 'zsig' and 'zisgproc'. -nelhage * Fix personal replies on webzephyr. -geofft * Fix two memory leaks formatting messages. -nelhage, andersk * Fix Makefile on platforms with Solaris tar. -nelhage 1.1 * Support building with -fstack-protector. -hartmans * Don't save partial passwords in editwin history. -nelhage * Improve IRC documentation. -nelhage * Don't use the 'zsender' variable for personals. -geofft * Implement irc-quote and irc-mode. -nelhage * Leave a one-column margin when wordwrapping. -nelhage * Remove some autotools-generated files. -andersk * Include IRC in the default build. -nelhage * Add a wordwrapping variant of the default style. -nelhage * Don't send stderr to admin messages. -nelhage * Remove a build-dependency on krb4. -hartmans * Allow the creation of type zephyr messages from perl. -geofft * Initialize Zephyr asynchronously at startup. -nelhage 1.0.5 * Implement initial support for real timers. -nelhage * Fix some compile warnings. -nelhage * Don't ignore the --datarootdir setting. -andersk * Replace questionable sprintf(buf, "%s...", buf, ...) pattern. -andersk * Show IRC /me messages with the conventional * instead of bold -andersk * Rip out the openurl function and related variables. -andersk * Stop leaking perl variables in :perl. -nelhage * Display multi-line error messages as admin messages. -nelhage * Fix a bug rendering multi-byte characters in the last column of the window. -andersk * Map Esc-A/B/C/D like arrow keys everywhere. -geofft * Fix a bug trying to disconnect from Jabber with no accounts connected. -asedeno * Call perl_sys_init3 to make libperl work on several other platforms. -hartmans * Bind the 'Delete' key to delete the next character. -andersk * Fix a double-free in owl_zephyr_delsub. -geofft * Don't fill-paragraph the ending dot of the buffer. -price * Fix numerous unsafe uses of sprintf(). -nelhage (Fixes CVE-2009-0363) 1.0.4 * Added a ':show quickstart' command. -geofft * Allow filters that reference a sub filter more than once non-cyclically. -nelhage * Make 'version' return 'BarnOwl' not 'Owl' * Escape interpolated regexes in filters. -andersk * Various code cleanups. -andersk * Fix format string injection bugs. -andersk * Clean up various code warnings. -nelhage * Replace questionable sprintf(buf, "%s...", buf, ...) pattern. -andersk * Show IRC /me messages with the conventional * instead of bold. -andersk * Rip out the openurl function and webbrowser variable. -andersk 1.0.3 * Moved BarnOwl source control to git on github. * Only call the zsig proc when we actually send a message. -asedeno * Strip out BOMs from Jabber messages. -asedeno * Fix logging of personal jabbers from JIDs containing / -nelhage * Fix Jabber breakage under reload-modules. -asedeno * Make reload-moduled correctly re-run startup hooks. -asedeno * Squelch Jabbers with no bodies, such as typing notifications. -asedeno * Various small spelling and grammar fixes. -geofft * Fix a segfault when sending short zcrypted messages. -asedeno 1.0.2.1 * Fix :reload-module's interactions with PAR modules 1.0.2 * Fix a segfault on retrieving zephyr subs when the user doesn't have any or has expired tickets. -asedeno * Don't complain about non-existant ~/.owl/startup when starting. -asedeno * Fix narrowing to personals in IRC. -alexmv * Don't segfault retrieving subscriptions without valid tickets. -asedeno * Load modules even if .owlconf doesn't run successfully. -nelhage * Update the manpage for barnowl. -nelhage * Better support for irc-names, irc-topic, and irc-whois. -geofft * Display /quit messages in IRC -geofft. * Add a new perl hook for all new messages. -geofft * Fix a bug causing corrupted input in the editwin on end-of-line. -nelhage * Add better support for adding hooks in perl that behave correctly on module reload. -nelhage * Added a :reload-module command to reload a single module. -nelhage * Fixed quoting issues replying to jabber users or MUCs containing whitespace or quites. -nelhage 1.0.1 * Remove an unneeded .orig file from libfaim/ - hartmans * Update the copyright notice in ':show license' - nelhage * Add a jabber:spew variable that controls whether unrecognized Jabber messages (such as pubsub requests) are displayed. - nelhage * Make the 'style' command assume the main:: package for unqualified subroutine references. Reported by Jesse Vincent. - nelhage * Rename doc/contributors to the more canonical AUTHORS - nelson 1.0.0 * Don't fail silently when sourcing a file; actually let the user know. - asedeno * Only hang for 1s, rather than 10s, if there is no zhm - nelhage * Merge the unicode branch to trunk. BarnOwl is now unicode aware and can send, receive, input and display UTF-8 encoded messages. Unicode changelog: * Put glib's CFLAGS and LDFLAGS at the beginning of the corresponding variables. - nelhage * Unicode branch: Fix building without zephyr. - asedeno * Fix a unicode branch wordwrap problem. - asedeno * Fixing an obscure wrapping bug that nelhage and I tracked down. - asedeno * Rename configure.in to configure.ac so Debian autoconf DTRT. - nelhage * Fix a bug in owl_editwin_move_to_previousword() which would skip over single letter words. - asedeno * I think I like this better. - asedeno * Fix nelhage's key_left bug. Don't spin at the locktext boundary. - asedeno * fix a typo in OWL_FMTEXT_UTF8_BGDEFAULT * fix a parsing issue for attributes - asedeno * Better compliance with UTF-8 processing. Stop trying to pull in a UTF-8 character as soon as we know something has gone wrong. - asedeno * Removing more hackery I left behind after doing things the right way. - asedeno * editwin.c - fix a wrapping bug I introduced in the last revision. It could leave us with a buffer that was not valid UTF- 8 - asedeno * editwin.c - lots of utf-8 cleanup that I had been putting off. util.c - a can we break here'' function based on perl's Text::WrapI18N - asedeno * Remove more bad hacks. - asedeno * Remove a debug message I accidentally left in. Remove the hours old check_utf8 hackery in favor of actually marking strings as UTF-8 from the C side. - asedeno * editwin.c: make locktext deal with UTF-8 * Jabber - More utf-8 sanitizing. * Pet peeve - tabs. That should be the end of it for now. - asedeno * Shuffling a line of code to where it actually should be. - asedeno * Patches to jabber libraries for better UTF-8 handling. - asedeno * fix a typo that was causing background problems * pass defaults attributes through in the truncate functions - asedeno * Eliminating a warning by un-internalizing a new fmtext function. - asedeno * Do not use bit 0x80 to indicate meta. We have other uses for that bit. * shift it above ncurses's KEY_MAX instead. - asedeno * drop unused struct member * fixing post-processing in the editwin. - asedeno * Preserve colors when highlighting search terms. - asedeno * ignore KEY_RESIZE if we know what that is. We don't need an unhandled keypress every time we resize the terminal. - asedeno * more strict utf-8 byte fetching. This probably still needs more work. - asedeno * Strip formmating characters when dumping to file. - asedeno * fixing bugs in editwin bufflen calculations. - asedeno * Fix search code so higlighting actually works. - asedeno * Remove options for libcurses and libncurses. This really only works with libncursesw. - asedeno * text entry: first pass at utf-8 text entry. * Change wcwidth() calls to mk_wcwidth() - asedeno * First pass at outbound zephyr -> iso-8859-1 sanitizing. Not that we can input anything other than ascii yet... * Fixing bug encountered when last field was not null- terminated. - asedeno * First pass at incoming zephyr -> UTF-8 sanitizing. This only operates on incoming data so far. We still need to clean outgoing data -- the plan is to attempt conversion to ISO-8859-1, and use that if it works. - asedeno * Reworked the fmtext format to use in-line formatting. Characters used for formatting are part of Unicode Supplemental Private Area-B, or Plane 16. * include wchar.h * replace hand-rolled width detection with wcswidth. * pad with space if we end up halfway into a character at the start of a line. * UTF-8 - first pass * make owl_text_truncate_cols() and owl_fmtext_truncate_cols() understand character width. This may need more work. Some code duplication - see if we can refactor. * stristr() rewritten to yse g_utf_casefold() instead of downstr(), and restructured to have a single return. * only_whitespace() rewritten for unicode. * Fix sending jabbers to JIDs beginning with `+' - nelhage * Compile zcrypt.c with -w so I don't get all these warnings in my compile output whenever I change any headers - nelhage * Implement /me for outgoing IRC messages - geofft * Add a makefile rule to support emacs flymake-mode - nelhage * Bind the combinations the iPhone sends for arrow keys [probably other terminals, too] - nelhage * avoid null pointer dereference if msg is NULL (or a 0 length is claimed) - shadow * Move styles from the current mishmash of different options to a unified perl object interface. - nelhage * Refactor default style code somewhat to be more easily extensible - nelhage * Put glib's CFLAGS and LDFLAGS at the beginning of the corresponding variables. - nelhage * IRC: /list, /who, and /stats commands - geofft * IRC: Make M-N mostly, rather than completely, useless. - geofft * Fix two small bugs in styling pointed out by broder - nelhage * Document create_style - nelhage * Move time_hhmm into a format_time method - nelhage * Remove prototypes from perlwrap.pm - nelhage * Quote regexp filter elements with spaces in them. - asedeno * Deal with smart-narrowing when the user's screenname has spaces in it. - asedeno * Add a new struct member to the global to hold an escaped aim screenname. populate the aforementioned new struct member. - asedeno * Removed our debian subdirectory, per Debian guidelines, at broder's request. - geofft * Make `all' the first target so we build the modules by default - nelhage * Commit inc/ under IRC so we build on systems with too old a M::I - nelhage * updating contributors - nelhage * Clean up licensing information and add a COPYING file - nelhage * Update bugs email to a more professional looking address, and remove the Development build warning. - nelhage BarnOwl r989 (2008-03-21) * Stick modules on the beginning of @INC, not the end - nelhage * Merge in the select branch. BarnOwl's main loop now uses a select() based event loop rather than continually polling, and uses much less CPU. - asedeno * Fix a bug where an explicit (local) realm foiled owl_message_get_cc_without_recipient(). (per quentin) - geofft * HTML Filtering fix for BODY tag - austein * Add parenthesis to fix a perl error in IRC - nelhage * Make IRC admin messages actually display their content - nelhage * Fix a file descriptor leak. - asedeno * Fix loading PAR modules that weren't present at startup - nelhage * Update perlwrap.pm documentation for the select() BarnOwl - nelhage * Render IRC notices as normal messages - nelhage * ensure that even if ioctl(,TIOCGWINSZ,) returns 0s we never set g->lines (and g->cols) to 0 - shadow * Generate less ugly error spew if a module fails to load - nelhage * Added :webzephyr command with keybinding W. - geofft * Fix a race condition in which zephyrs received during init are not noticed until the next zephyr after entering the mainloop. - asedeno BarnOwl r941 (2008-02-18) * unicode/glib branch Remove a debug message I accidentally left in. Remove the hours old check_utf8 hackery in favor of actually marking strings as UTF-8 from the C side. - asedeno * unicode/glib branch Remove more bad hacks. - asedeno * Rewrite ::Connection to not subclass Net::IRC::Connection to avoid stupid namespace conflicts - nelhage * svn:ignore for great justice - nelhage * Attempt to load BarnOwl::MessageList::SQL and error if it fails. Note that the aforementioned class n'existe pas - nelhage * unicode/glib branch editwin.c - lots of utf-8 cleanup that I had been putting off. util.c - a can we break here'' function based on perl's Text::WrapI18N - asedeno * unicode/glib branch editwin.c - fix a wrapping bug I introduced in the last revision. It could leave us with a buffer that was not valid UTF- 8 - asedeno * dropping one unnecessary time(NULL) call. - asedeno * unicode/glib branch removing more hackery I left behind after doing things the right way. - asedeno * unicode/glib branch better compliance with UTF-8 processing. Stop trying to pull in a UTF-8 character as soon as we know something has gone wrong. - asedeno * First prototype of a SQL-backed message list. This is probably horribly broken, and is painfully slow at the moment. - nelhage * minor changes to IRC * Resizing should not leave the current message off screen. - asedeno * Added initial IRC support. Not built or installed by default. - geofft * Preserve colors when highlighting search terms. - asedeno * Handle zephyrs to users on non -c message better [trac #39] - nelhage * Make :reload-modules work correctly with PARs - nelhage * Document (nearly) every public function in the BarnOwl:: namespace - nelhage * strip IRC coloring from IRC messages - nelhage * Document ::Hook and ::Hooks - nelhage * Nuke the stylefunc_default C code - nelhage * Nuke some refs to owl_message_get_notice - nelhage * Clearing the line should preserve the echochar. - asedeno * Fix logins to jabber.org - reported by gendalia - asedeno * Move oneline style to perl. [trac #43] - nelhage * Fix the error messages sending to users who don't exist or aren't signed on. - nelhage * Jabber Buddy Lists: * Query the jabber:show_offline_buddies once when invoking onGetBuddyList() * Don't bold online roster entries when hiding offline ones - asedeno * Portability - removing C++ style comments. - asedeno * Add the variable 'zsender' to customize the outgoing Zephyr username. - geofft * Bind M-left and M-right by default in the editor - nelhage * eliminate a segfault. - asedeno BarnOwl r796 (2008-01-08) * Define variables at the top of blocks for better ANSI C-ness (patch by Chris Laas) [trac #18] - nelhage * Implement :punt and :unpunt to punt arbitrary filters, rather than just z- triplets. [trac #6] - nelhage * Show non-personal pings like stock owl does. [trac #12] - nelhage * Fix problems with jabber servers keeping the same stream id when negotiating TLS tracked down by Greg Hudson. - asedeno * When we're narrowing to an instance, properly include un-instances. This fixes narrowing to any instance that starts with ``un-'' - nelhage * Don't read before the start of the string for an instance - nelhage * Adding an explicit -f - to the tar commands for FreeBSD compatibility (reported by ecprice) - nelhage * Some fixes for FreeBSD. - ecprice * Do ~-expansion in :loadsubs. [trac #26] - nelhage * Validate JIDs passed to jmuc join. [trac #25] - nelhage * Show full JIDs for users in non-anonymous JIDs in :jmuc presence. [trac #24] - nelhage * Don't crash if we hit `i' on a zephyr containing non-ASCII iso-8859- *. - nelhage * added -m flag to aimwrite - matt * aimwrite -m displays according to displayoutgoing - austein * Make the usleep call more reasonable for less CPU usage - asedeno * Add zip as build-depends - nelhage * bind END in popless windows. [trac #41] - nelhage * Allow C-r on outgoing messages (useful for CCs) - chmrr * Identify ourselves as barnowl more consistently - chmrr * Report subscription errors more accurately. - chmrr BarnOwl r751 (2007-08-01) * Refactored message processing: All new messages, incoming or outgoing, get added to the owl_global_messagequeue by protocol code, and then passed to owl_proces_message, which serves as a single central code path for adding messages to the message list. - nelhage * Properly pass the usage when defining the jabberlogin command - nelhage * Outgoing messages now log as much information as incoming messages - chmrr * Fix a pointer corruption issue if we redefine the current style. - nelhage * Adding 3 variables for the Jabber module: jabber:show_offline_buddies, jabber:auto_away_timeout, jabber:auto_xa_timeout - asedeno * Don't include self when replying to CC'd messages - chmrr * Outgoing CC'd messages get logged to all recipients - chmrr * Incoming CC'd zephyrs logged to all people they were sent to - chmrr * Change the width at which we hard-wrap outgoing zephyrs by default so that zephyrs will fit on screen with the default style. (suggested by andersk) - nelhage * Added a -s switch to change the location of the config dir (~/.owl) - nelhage * Don't allow you to go off the end of an empty message list. [trac #9] - nelhage * Allow you to send to -c message -i personal * - nelhage * Make zephyr smartnarrow use the `personal' and `private' distinction properly [trac #2] - nelhage * Change the default personal filter to for zephyr. - nelhage * Display opcodes with the default style - nelhage BarnOwl r720 (2007-05-29) * Correctly define a ``private'' zephyr as one that is sent to a recipient that is neither empty nor starts with ``@'' - nelhage * Fix builds under make -j - nelhage * Fix sending of zcrypted zephyrs - nelhage * Rewrite perl internals to factor out module loading. - nelhage * Fix display of zephyrs with empty instances - nelhage * Implemented a Module::Install plugin for building barnowl plugins - nelhage * Modified the makefile to build and install perl modules - nelhage * Fix the bug in which rejoining a MUC you're already in (nick change) results in the MUC appearing multiple times when you show presence info for all MUCs. - asedeno * Implemented loading of both PAR and unpacked modules, and module reloading. - nelhage * Make the Makefile build and install perl modules on a clean install. - nelhage * Implemented an LRU cache of the message list fmtexts. This reduces memory usage by roughly 1MB/kilo-zephyrs in steady state. - nelhage * Escape $ in regexes (e.g. smartnarrowed instances) - nelhage * Adding 256-color support. This requires a version of ncurses that supports ABI-6. Colors beyond the first eight are refered to by number. - asedeno * Correctly escape {} and () in regular expressions - nelhage * When generating filters, change single quotes and double quotes into dots, so they line parser doesn't choke on them. This fixes problems smart-narrowing to instances such as "this'll break it". - asedeno * Improving the private/personal distinction: * ``private'' means to/or from an individual, not a chat/class/etc. * ``personal'' means ``matches the personal filter'' - nelhage * Beep on personal messages, not private, by default. - nelhage * Some small doc fixes (thanks to jwalden for pointing them out). - nelhage * Added the ability to define new variables from perl. - nelhage * Documented said ability via BarnOwl::new_variable_* - nelhage * Add a "setsearch" command which sets the search highlight string without moving the cursor. - glasser BarnOwl r657 (2007-03-06) * Fix libfaim to make it compile - nelhage * Apply some memory leak patches by alexmv and yoz - nelhage * Make smartnarrow un- and .d-aware - chmrr * Add a `getstyle' command - asedeno * Make Test failures print file/line numbers - nelhage * Fixed regression tests for booleans variables. - asedeno * Add a perl perl hook into owl's main loop. - asedeno * Added the ability to install real commands from perl code - nelhage * Fix a hang in owl_editwin_move_to_previousword - nelhage * Updated the version number and startup message - nelhage * Added initial support for creating and injecting messages into the display from perl. - nelhage * Added the ability for perl code to hang arbitrary reply commands off of messages. - nelhage * Expose the edit window hooks to perl - nelhage * Removed references to -ldes - kchen * Exposed owl_function_error and owl_function_makemsg as commands - nelhage * Implemented initial Jabber support. - asedeno * Implemented initial Jabber groupchat support. - asedeno * Added a perl hook to the buddy list display - nelhage * Added a get_data_dir function to the perl interface - hartmans * Don't include the default typemap in xsubpp compile line - hartmans * Cause perl to always be loaded, even if no owlconf is present. - hartmans * Implemented an extensible perl module system - hartmans * Exposed owl_fuction_popless_text() and owl_fuction_popless_ztext() to perl - asedeno * Support multiple simaltaneous Jabber connections - asedeno * Fixed a segfault on subbing without a .zephyr.subs file - nelhage * Implemented Jabber Roster support - asedeno * Don't quit if we can't contact the hostmaster. - nelhage * Support filters based on arbitrary message attributes - nelhage * Rewrote and massively cleaned up the filter system internals. - nelhage * Fixed the ``personal'' filter to work better with all protocols - nelhage * Made `smartnarrow' more generic, and implemented it for jabber. - nelhage * Changed executable name to "barnowl" - nelhage * Renamed the `owl::' package to BarnOwl:: - nelhage * Dynamically link perl libraries - nelhage * Added background color support - asedeno * Added idle-time tracking, and updated jabber to automatically set away status - asedeno * Implemented shortnames for jabber rosters and jwriting. - nelhage * Fixed a crash when smartnarrowing to instances with lots of periods or other regular expression metacharacters. - nelhage * Support comments in ~/.owl/startup - asedeno * Dispal tweaks for MIT's -c discuss messages. - asedeno * Don't override perl's idea of the switches we need to do embedding. - shadow * Make the default style perl, rather than C. - nelhage * Refactor the default style to be protocol generic - nelhage * Prefer ~/.barnowlconf to .owlconf, if it exists. - nelhage * Intern hostnames and message attribute keys for a slight memory saving. - nelhage * Use libncursesw when available - asedeno 2.1.12pre Don't crash when sending/logging outgoing AIM message and not logged in [BZ 90] Don't crash when senging to someone not on AIM buddy list [BZ 94] (patch from Alex Vandiver) 2.1.11 Don't crash doing zlocate with bad tickets. [BZ 12] Metion the path for the owlconf in intro.txt [BZ 54] Print better error message if startup fails due to unreadable .owlconf [BZ 57] In load-subs: Print an error message if the file is unreadable or doesn't exist, UNLESS load-subs is called with no arguments. In that case only print an error if the file exists but isn't readable. Still prints an error either way if zephyr reports a failure. [BZ 19] Fixed some small memory leaks in logging if files unwriteable If the variable logfilter is set it names a filter. Any messages matching this filter are logged. This is an independent mechanism from the other logging variables. If you want to control all logging with logfilter the other variables must be set to their default (off) settings. [BZ 37] Relatively substantial changes made under the hood to support filter logging. Now have more consistent interfaces to creating messages etc. Still needs more work though. Deal gracefully with being resized as small as 1x1 [BZ 3] 2.1.10 Fix a new problem finding libdes425 Don't crash on very long hostnames [BZ 52] In 'sub' command, create .zephyr.subs if it doesn't exist [BZ 15] A fix for certain resize crashes (partly from alexmv) [BZ 55] Turn off ISTRIP (gildea) 2.1.9 Include /usr/include/kerberosIV if it's found 2.1.8 Do OLC formatting for anything coming from olc.matisse Improvements to popup size algorithm (from gildea) Improved 'show colors' with non-colored labels 2.1.7 The colorclass command is added, to make colorization easy Handle MIT Athena OLC zephyrs correctly Updated ktools website / bug address Do ntohs() when printing zephyr port in zephyr info Updated man page 2.1.6 Fixed three bugs found by Valgrind. Fixed a case where doing "aim addbuddy" instead of "addbuddy aim" would cause a segfault. pexec will now incrimentally display data as it is output by the child process. Additionally, commands running under pexec may now be killed by quitting out of the popless window. Added muxevents select loop dispatcher. File descriptors may be registered with muxevents and handlers will be dispatched to when data is available for non-blocking read/write/except. Switched the stderr_redir stuff to use muxevents. Print C-\ correctly (from gildea) Dropped first brace in muxevents functions for consistency Catch SIGHUP and SIGTERM and do a proper logout 2.1.5 Added a licence The 'personalbell' variable can now be set to 'on' 'off' or the name of a filter to match against The 'loglogins' variable now controls whether login/logout messages are logged. It is off by default. For now this affects only AIM messages, later zephyr login/logout messages will also be logged if this is set to 'on' Added 'show license' 2.1.4 Normalize and downcase AIM names for logging Fixed a bug where sending a null zsig could cause a crash Better 'away' toggling if only one protocol is away. 2.1.3 Added perl filter elements. Similar to having "filter " in a filter, you may also have "perl " where is passed an owl::Message object and returns 0 or 1 depending on whether the message matches that element of the filter. Don't print an error about loading subs if there is no .zephyr.subs Do the initial zephyr_buddy_check when pseduologin set to true. Updated man page 2.1.2 removed unused filter_depth variable Fixed memory bug on receiving pings 2.1.1 Filters of filters now work. Removed the "possibly not readable" part of the config parsing error In the sepbar, reverse video the view name when it's not set to view_home (as opposed to the static 'all'). The '!' key (bound to 'view -r') now creates a negative version of the current view and switches to it. i.e. "show me all the messages that are not these" Added the 'ignorelogins' variable Log when outgoing personal message fails Removed file descriptor from sigpipe catcher printer just for now, since the field does not exist on OSX Added an ifndef for socklen_t in libfaim/ft.c Added the 'aim search' command. The popup on callback may be dangerous, should switch to an admin msg for results, or add a new event queue First pass at AIM away messages. It is a little different from what most clients seem to do, in that an away reply is sent for each message received. Most clients only reply to the first one per away-session. Now have a set of 'aaway' commands and variables just like the 'zaway' ones (except that changing the 'aaway' variable talks to the server) The new 'away' command does everything for both AIM *and* zephyr. There is a known funkiness here, where if you turn one away on, and then use 'away' (or 'A') to toggle, you will turn on off and the other on. Just leaving it for now. Should do better in the next patch. The 'A' key is bound to 'away' Status bar can now read AWAY, Z-AWAY or A-AWAY. Changed C-n to scroll down just a line in popless If the config exists but is not readable, print an error before exiting Only print forced AIM logout message once. Don't bind F1 to help in edit context Fix bug in 'getsubs' with no tickets New code for getting users from .anyfile Added the 'pseudologins' variable, and code to do it new attributes 'pseudo' 'logintty' and 'loginhost' Don't print extra new lines in popless_file New zephyr_get_field function 2.0.14 Fixed missing word in startup message Better 'status' command Use '+' for popwin corners when 'fancylines' is off Allow TERMINFO to be overridden in the envrionment Command line arg -D turns on debugging and deletes previous debugging file Do ~ expansion in 'dump' command. Current directory added to 'status' command Massive changes to libfaim and aim 2.0.13 Changed startup message for new mailing list blist now prints AIM info even if .anyone is unreadable Catch SIGPIPE and print an error rather than crashing. [It's possible that this may have some portability issues under Solaris and we may need to add some configure stuff around SA_SIGINFO...] Handle the case in aim_bstream_send where aim_send returns -1, although there is likely an underlying problem here that would lead to this case. Print the username on aim login failure, not something random like the password. ;) Un-word-wrap text when sending AIM messages. Replace the main loop continue in the keyboard handler with an else. 2.0.12 Command history now doesn't allow the last entry to be repeated If format_msg returns "" print "" Better align oneline admin and loopback messages Print an admin message indicating when subscriptions can not be loaded on startup Set aim_ignorelogin_timer to 15 by default Admin message on login/logout of AIM Fixed double quoting in smartzpunt Added timestamp to login/logout messages Fixed replies to loopback messages Fixed smartnarrow on classes/instances with spaces Added the 'loggingdirection' variable All loopback messages log to 'loopback' now Print an error message if trying an invalid color for a filter Fixed bug causing > not to go to end of editwin every time 2.0.11 Updated basic help Display CC: in outgoing CC messages More AIM logout detection Don't proclaim "interfaces changed" on first build. Added the 'loopback' message type Added the 'loopwrite' command Added a timestamp to the default style Zpunt now works with weird regex characters Smart filters now work with weird regex characters 2.0.10 Allow 'hostname' in filters. Fixed bug in reporting when no one is subbed to a class Added an extral newline in logging incoming zephyrs An admin message is displayed when you are logged out of AIM Print an error message and admin message if an AIM send fails 2.0.9 Added the 'fancylines' variable. Added the 'show startup' command. Added feature for capturing stderr messages from commands and displaying them in the errors buffer. Create an admin message explaning that a zephyr couldn't be sent Better reporting of perl errors (both into the errqueue and also clearing the error after displaying it). Allow default_style to be specified in config. Added errqueue Added command "show errors" Fixed bug removing newlines in backup files 2.0.8 Increased size of screen name field in buddy listing Fixed bug with idle times causing broken pipes. New libfaim Added the 'source' command. Make sure that a newline is always at the end of messages returned by perl style formatting functions. Add owl::login and owl::auth to legacy variables populated for format_msg. Additions to intro.txt and advanced.txt documents. (Still in progress.) Add base methods for login_host and login_tty and others that return undef. New API for perl message formatting functions. Legacy variables are still supported for owl::format_msg and owl::receive_msg, but these functions are now also passed an owl::Message object which contains methods for accessing the contents of the message. See perlwrap.pm (and docs TBD) for the available methods. *** WARNING: The exact API for owl::Message has *** not yet stabilized. Added "style" command for creating new styles. Usage: style perl Added support for "show styles". Changed global style table from list to dictionary. Changed AIM password prompt from "Password:" to "AIM Password:". Messages are reformatted after a window resize to allow styles to take into account the width of the window. When perl throws an error, the message is put in the msgwin if possible. Added perl functions for: owl::getcurmsg() -- returns an owl::Message object for the active message in the current view. owl::getnumcols() -- returns the column width of the window owl::zephyr_getrealm() -- returns the zephyr realm owl::zephyr_getsender() -- returns the zephyr sender Made owl::COMMAND("foo"); be syntactic sugar for owl::command("COMMAND foo"); Added perlwrap.pm to contain perl code to be compiled into the binary. This is transformed into perlwrap.c by encapsulate.pl. Renamed readconfig.c to perlconfig.c and changed variables accordingly. Minor bugfixes in cmd.c and commands.c Improved intro doc 2.0.7 Idletimes now appear in the buddylisting Failed AIM logins are now correctly reported Owl will build now without zephyr, enabling it to act as a standalone AIM client. There is now a zcrypt command Replies to zcrypted messages now work Don't allow zwrite if zephyr isn't present Cleaned up some warnings from linux gcc. Fixed bug that can cause response stuff to crash Improved status command Fixed bug in buddy stuff 2.0.6 aimlogin will now accept the screenname without a password and ask for the password such that it is not echo'd to the terminal 'addbuddy aim' and 'delbuddy aim' now work Bug fix to make zwrite -m work with -c/-i Fixed documentation bug in aimwrite Initialze $owl::auth Fix in autoconf for des425 Reformatted editwin.c and added capability of doing password-style echoing 2.0.5 Fix in finding des for building zcrypt Fixed description for alert_action variable More detailed usage from -h Special cased replies for webzephyr users on classes and login notifications for webzephyr users Fixed bug that caused a crash on zpunt with '*' for an instance AIM logout and then login now works. Fixed bug causing view -d not to work. Added hostname and tty name to LOGIN/LOGOUT zephyrs on oneline style 2.0.4 Made command line option -n actually work Implemented styles, including the 'default' 'basic' and 'oneline' styles. A 'perl' style is available if a format_msg() function is found in .owlconf Added the 'default_style' variable Added the 'toggle-oneline' command The 'o' key is bound to 'toggle-oneline' Internally, the one view now has a name, 'main', and message recalcuations are done in place when its filter is changed. Added filter field 'login' which can take the values 'login' 'logout' or 'none' Added the perl variable $owl::login, just as above Updated the 'login' and 'trash' filters appropriately Fix for checking for DES in build system Bug fix in using makemsg when no curses window is present The variable $owl::auth now exists in perl Use new internal function to delete zephyr subs from file New 'sepbar_disable' variable can turn off sepbar info display Updated contributor info Added the 'show view' command Bug fix in owl_regex Fixed personal aim messages logging to class directory Log "LOGIN" or "LOGOUT" for AIM buddy messages zwrite -m now correctly displays an outgoing message and logs zwrite -s now works Strip spaces in AIM usernames on aimwrite send Removed libfaim/config.log from CVS Fixed some easy fixed-length buffers Wordwrap incoming AIM messages Fixed bug causing buddies not to be added to buddy list during ingorelogin timer Translate < > & "   &ensp, &emsp, &endash and &emdash 2.0.3 Don't ring the terminal bell on mail messages. Nuke Make the build work a little better on OSX Fixed a bug in fmtext Expanded the size of the hostname buffer 2.0.2 Fixed bug in 'startup' command. 2.0.1 Moved newmsgproc stuff to a function procedure Added the 'newlinestrip' variable, on by default, that strips leading and trailing newlines from incoming messages. Fixed a case sensitivity probelm in owl_message_is_personal and owl_message_is_private The message object now uses a list of attributes internally, in prep. for supporting new messaging protocols owl_function_info now uses fmtext instead of one staticly sized buffer in owl_message_get_cc() require that the colon be present after cc. Added some defenses against resize crashes, and put in debug messages if they're encountered In filters 'true' and 'false' are now valid tokens. The 'all' filter has been redefinied to be 'true' and there is a 'none' filter defined as 'false' Fixed bug in 'unsub' command that could cause file corruption In the zlist function, give a more detailed error message if the file cannot be opened. Renamed old instances of zsig_exec in the code to zsigproc Don't print the stderr from zsigproc Added a 'loadloginsubs' command to load login subscriptions from a file Added a 'loadsubs' command to eventually phase out the 'load-subs' command Made M-n work on classes and instances with spaces in them Zaway now obeys the smart strip variable Hacked the build system to not have the -E link problem on Athena Added ZResetAuthentication in a number of places to fix problems with stale tickets Added some hooks for malloc debugging M-p is bound to 'view personal' by default loadsubs and loadloginsubs only print messages if in interactive mode added the 'alert_filter' variable, defaults to 'none'. added the 'alert_action' variable, which is an owl command that will be executed when new messages arive that match the alert_filter added the 'term' command which takes the 'raise' and 'deiconify' options. It assumes xterm for now. only 'make distclean' will nuke core and ~ files now fixes to owl_function_do_newmsgproc from Stephen converted functions.c to new code style, which I'm giving a shot Makefile.in: define DATADIR, for default owlconf. Makefile.in: provide "all" and "install" rules. configure.in: try also libdes and libkrb4, for people using heimdal configure.in: see if des_ecb_encrypt is already prototyped. configure.in: minor changes to work with new autoconf without needing acconfig.h. configure.in: find the install program. configure.in: test for use_default_colors since some versions of solaris don't have it, so we can at least compile something vaguely working there. keypress.c: ifdefs for keys not defined on at least some solarises. owl.c: don't call use_default_colors if we don't have it readconfig.c: added *commented out* code to try to find a system-default owlconf if the user doesn't have one. Have to ponder if I want this zcrypt.c: don't prototype des_ecb_encrypt if there is a prototype in des.h. zcrypt.c: include owl.h so we get the configure-generated config.h Change to codelist.pl to deal with new code style Remove some ancient stuff from zcrypt.c General cleanup to Makefile.in CTRL and META are now OWL_CTRL and OWL_META. OWL_CTRL moved to keypress.c do_encrypt declaired static if we don't have des functions, do not try to build in zcrypt kill the newmsgproc function on exit Added libfaim Added basic AIM support, including the "aimlogin", "aimwrite" and "aimlogout" commands New built-in filters 'aim' and 'zephyr'. Do ZResetAuthentication() before zlog_in and zlog_out as well. Print AIM login / logout notifications The 'alist' command prints a list of aim buddies logged in The 'blist' command prints users from all protocols The 'l' key is now bound to 'blist' instead of 'zlist' Started work on 'addbuddy' and 'delbuddy' command but they DO NOT WORK yet Removed a bit of faim code that allowed commands to be executed. The 'B' key is now bound to 'alist' Added the 'startup' and 'unstartup' commands The $HOME/.owl directory is created on startup if it does not exist Added the 'aim_ingorelogin_timer' variable 'addbuddy zephyr ' and 'delbuddy zephyr ' now work. 'isloginout' and 'isprivate' are now message attributes improved 'info' function lists seperate info for zephyr, aim and also prints all message attributes AIM logging (both in and out) now works Disabled 'addbuddy' and 'delbuddy' for aim since it doesn't work yet Hacked the Perl build stuff not to link with iconv 1.2.8 Class pings are displayed differently now Updated owlconf.simple example to format outgoing messages. 1.2.7 Outgoing messages now go through the config for formatting Zaway now makes an outgoing message, instead of an admin message The 'zlocate' command can now handle multiple users The simple user format for "To:" is in effect again Prettyed up the zwrite line for using 'reply' on a zaway Added a workaround for a libzephyr bug that caused zwrites to fail if zephyrs were sent just before and just after renewing tickets Fixed a memory bug in getsubs Added receive support for zcrypt messages Added the 'zcrypt' variable which controls whether or not zcrypt messages are decrypted 'reply' is disabled for zcrypt until sending zcrypt works Started implementing zcrypt command More updates to the intro doc 1.2.6 Started adding code for newmsgproc. It doesn't fully work yet! Don't use it. Added search, '/' and '?' to basic help. Will attempt to keep the current message as close as possible to the previous current message after an expunge. "set " and "unset " now work for boolean variables. Fixed a bug in owl_function_calculate_topmsg_normal that caused a segfault Fixed some typos in the intro doc Removed old zlog functions from zephyr.c Implemented the dump command New startup message 1.2.5 Patch to fix memory bug in replying to CC messages If we're on Athena and have static krb (or other) libraries, use them Added "athstatic" program to the release, which handles the above Cast to an int for isspace, to make gcc -Wall quiet Added 'zlist' and 'l' to basic help. 1.2.4 'zlog in' will now take an optional thrid argument to set the 'tty' variable before setting the zlocation There is now a 'zlist' command that acts like 'znol -l' 'l' is bound to 'zlist' Fixed memory leak uninitialzed memory read in fmtext viewwin will now say "End" instead of "More" when at the end Added a debugging message indicating the result of topmsg calculations You can now use %me% in filters The built-in personal filter is updated to do so Fixed a bug in moving the pointer after an expunge Fixed up the normal scrolling code. Now it should always land on a message, but it's still not optimal. Added the variable 'smartstrip' which will strip kerberos instances out for the 'reply' command. Added -R/usr/athena/lib to the build for Athena Started updating the intro document Small changes to help / about The 'subscribe' and 'unsubscribe' commands (and their aliases) now update .zephyr.subs by default. If either is given the '-t' (for "temporary") option the .zephyr.subs will not be updated Turned off beeping for hitting the top or bottom of the list of messages Made daemon.webzephyr a special case for smartstrip Added 'out' as a default filter for outgoing messages 1.2.3 Added filters "ping", "auto" and "login" by default. Added "body" as a valid field to match on in a filter. Temporary fix to bug where C-SPACE would cause the key handler to lock up. Messages now have a direciton (in, out or none). Filters can match on this direction Outbound messages are no longer type 'admin' but are of the appropriate message type (i.e. 'zephyr') and are direction 'out'. Smartnarrow now works on outgoing messages 'info' updated to show more information for admin and outgoing messages Renamed pretty_sender to short_zuser and renamed long_sender to long_zuser Moved zsig generation to the zwrite object Print the zsig used for outgoing messages The tty variable now controls the zephyr location tty name 1.2.2 Added the 'search' command. '/' is a keybinding for 'search' '?' is a keybinding for 'search -r' Fixed stristr, which was completely broken renamed owl_fmtext_ztext_stylestrip to owl_function_ztext_styletsrip and put it in functions.c Attempts to stay near the current message when switching views. When switching from an empty view to one we've previously been in, the new current message position will attempt to be close to the current position from the last time we visited that view. Fixed bug in readconfig.c that prevented building under perl 5.005. Switched "C-x C-x" to only "startcommand quit" 'getsubs' prints closer to the order you sub in. Modified the behavior of last so that "> >" will clear the screen. The new behavior of last is: Moves the pointer to the last message in the view. If we are already at the last message in the view, blanks the screen and moves just past the end of the view so that new messages will appear starting at the top of the screen. Fixed a typo in the help for smartzpunt. Fixed functions to handle curmsg being past the end of the view. 1.2.1 New framework for command handling. New framework for keymap handling. Added commands for everything that is bound to a key (do 'show commands' to get the full list). Added 'multi' and '(' commands to allow multiple commands to be specified on a line. Added user keybindings with bindkey command. Added command aliases (eg, "alias foo bar"). Added undelete command that parallels the delete command. Added additional options to delete command. The reply command now takes arguments. Added 'edit:insert-text' command. Added 'show zpunts' to show active punt filters. Added 'show variable ' and 'show variables'. Added 'show command ' and 'show commands'. Added 'show keymap ' and 'show keymaps'. Added 'M-u' to undelete all messages in current view. Fixed dotsend so that the zephyr will still send if there is whitespace after the dot but not on the same line. This should resolve an issue where dotsend wouldn't work if you'd gone up and edited a zephyr. Bug in page down fixed C-t will transpose characters Fix the scrolling bug where we would sometimes fail to scroll the screen down, leaving the current message off the bottom of the screen. Refixed 'login or login' typo in help Fixed M-u description Removed 'first' and 'last' from basic command help Added M-N to basic key help Added M-D, M-u to basic key help Fixed a quoting problem in configure.in Changed top of help to use 'show' instead of M-x Fixed a bug in the summary field for user-created aliases Added "reply zaway" which sends a zaway response to the current msg. Added "edit:delete-prev-word" command and bound M-BACKSPACE to it. Some buffer overruns fixed Variables now have a summary and a long description. Only the summary is shown with help. The long description is shown with "show variable foo". Added a 'scrollmode' variable which determines how the screen will scroll as the cursor moves. The default behaves identically to previous versions of owl. The following modes are supported: normal - This is the owl default. Scrolling happens when it needs to, and an attempt is made to keep the current message roughly near the middle of the screen. (default) top - The current message will always be the the top message displayed. neartop - The current message will be one down from the top message displayed, where possible. center - An attempt is made to keep the current message near the center of the screen. paged - The top message displayed only changes when user moves the cursor to the top or bottom of the screen. When it moves, the screen will be paged up or down and the cursor will be near the top or the bottom. pagedcenter - The top message displayed only changes when user moves the cursor to the top or bottom of the screen. When it moves, the screen will be paged up or down and the cursor will be near the center. 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. 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. The "disable-ctrl-d" variable may also be set to "middle" which will result in ctrl-d only sending at the end of the message. This is now the default. This also added a command "editmulti:done-or-delete". Fixed a bug in the "reply -e" command. Always clear the command buffer before executing the command. (So that interactive commands can sanely do start-command.) Fixed preservation of e->dotsend across owl_editwin_clear(). Added history for multiline edit windows (eg, for zephyr composition). The M-n and M-p keys will cycle through the history ring. In particular, it is now possible to edit the command line of a zephyr being composed: C-c it and restart it and then M-p to get the aborted composition back. Added owl::send_zwrite(command, message) to the perl glue to allow for the direct sending of multi-line messages. For example: owl::send_zwrite("-c foo -i bar", "hello"); Changed owl_fmtext_print_plain to return an alloc'd string to avoid buffer overrun risks. Added owl::ztext_stylestrip("...") function to perlglue which returns the ztext with formatting stripped out. Added colorztext variable which can be used to disable @color() strings arriving in messages after it is set. (Currently, changing its value won't reformat messages). Outgoing zephyr logging now obeys the logpath variable. The '~' character in logpath and classlogpath now gets replaced with the user's home directory. Added simple implementation of smartnarrow-to-admin that creates a "type-admin" autofilter. This was done mostly so that M-C-n and M-C-p do something sane on admin messages. Added opera to the allowed options to the webbrowser variable. Fixed some buffer overruns in the "reply" command. When repying to "all" on a message that begins with "CC:" (eg, sent with "zwrite -C", the reply line will be constructed from the sender and the usernames on the CC: line of the message being replied to. There is no such thing as C-R, so left C-r as it is but added: M-r --- edit reply to all M-R --- edit reply to sender Added RCS Id strings to all files. 'show keymaps' shows details of all keymaps after summary list. Added --no-move option to delete command. In particular, delete-and-always-move-down may now be implemented with '( delete --no-move ; next --skip-deleted )'. Folded the nextmsg and prevmsg commands and functions together into one command which takes arguments. Added '--filter ' option (eg, for next_personal), '--skip-deleted' option, and '--last-if-none'/'--first-if-none' options. Help updated accordingly. In particular, the 'personal' filter is now used for 'next personal'. Added --smart-filter and --smart-filter-instance options to the next and prev commands. Updated examples/owlconf.erik with the above. Made owl_function_fast*filt return a string and not do the narrowing, to make it more general. Added a smartfilter command that creates a filter based on the current message and returns the name of the filter. Added M-C-n and M-C-p keybindings to "move to next message matching current" and "move to previous message matching current" Added variables edit:maxfillcols and edit:maxwrapcols which will limit how wide editing paragraphs may get before they get wrapped. This is a max and may be narrower depending on the current size of the window. If 0, the max is unlimited. Default is 70 columns for edit:maxfillcols and unlimited for edit:maxwrapcols. Added smartzpunt command with key binding of "C-x k". This starts a zpunt command filled in with the proposed zpunt. Fixed a memory reference bug in delete and undelete commands. Added support for perl to call directly back into owl. Changed the implementation of owl::command("...") to immediately call back into owl. This allows perl to get the return value of strings returned by owl commands. Added the getview command which returns the name of the current view's filter. Added the getvar command which returns the value of a variable. Added an example to examples/owlconf.erik which uses TAB to narrow and restore the view. Added an example to examples/owlconf.erik which uses M-c to color messages matching the current one green. Integrated change to fix problem with popup blinking on new zephyrs. C-l and resizes will now refresh an open viewwin (eg, help). Updated doc/code.txt to include info about filters, commands, contexts, and keybindings. Exec commands cleaned up to not have buffer-size limitations and to not mess up spaces. exec also returns a string of the output now. Integrated changes from 1.1.3, and added docs for "zlocate -d" and new show commands. Show with arguments produces help on show. Fix a bug in readconfig caught by efence (where we'd try to read before the beginning of a string if it was empty). The perl command doesn't do makemsg directly, but instead returns the string and it will get printed if it was run interactively. 1.1.3 'show subs' and 'show subscriptions' are now the same as 'getsubs' zlocate now takes an optional -d argument 'show terminal' / 'show term' '>' / last doesn't set the last message at the top of the screen now implemented _followlast as an unsupported feature include 'default' in the 'show colors' list added help for 'zpunt' and 'zunpunt' changed the bug address in the startup message can now do 'show status' can now do 'show version' 'status' / 'show status' includes the owl version number now 'show terminal' includes whether the terminal can change colors fixed off by one bugs in paging / scrolling viewwin don't downcase the sender when getting the log name for personals support @owl::fields as well as @fields downcase class/inst filter names in auto filters 1.1.2 Fixed memory mishandling bug Fixed bug in redfining the filter attached to the current view M-n will narrow to message, instance on non-personal, class MESSAGE messages M-N behavies like M-n except that on class messages it narrows to class and instance line wrap earlier, to account for tabbing fixed typo in help 'status' command now displays info on terminal color support zephyr @ formatting is now case independant added support for color terminals zephyr @color(foo) now works 'D' for deleted messages is now not bold, unless it's the current message F1 displays the help screen added filter colors added the 'colorview' command added the 'show colors' command users who don't have a .zephyr.subs get a simpler format for incoming messages If colors are available 'show filters' will show a filter in the color associated with it. Added the zpunt and zunpunt commands Lines in the subs file starting with '-' are zpunted Include login/logout messages in auto user filters 'V' changes to the home view ('all' by default) 1.1.1 Fixed perl, aperl, and pperl commands to deal with quoting and spaces in a saner manner. Removed all owl_get_* methods for booleans and switched cases where they were used to owl_is_* Changes to owlconf.erik to use some new features. Increased the size of the help buffer (as it was overflowing and truncating the help message). Variables prefixed with a _ are not shown in help or by printallvars (and prefixed Not Yet Implemented variables with this). Fix typo in help include stdio.h in functions.c remove stale "q to quit" from bottom of info message fix downward scrolling more than a page use authentication for zlocate, by default fixed buffer over run in info command on long messages call 'perl ' from Makefile to avoid hardcoding perl paths in Makefile don't build owl_prototypes.h unless necessary store the time for admin messages display admin message time in 'info' command fixed an editwin M-> last character bug 1.1 reply is a normal function now 'R' does reply to sender 'T' tells you how many messages were marked for deletion local realm removed from login / logout messages added command history better runtime / starttime reporting in 'status' command leave the pointer near the current message after expunge C-l recenters editwin implemented zlocate @italic works the same as @i on reply only quote class / instance when necessary C-r allows you to edit the reply line don't use unecessary options in reply line display 'info' errors in msgwin, not popup impelemnted aexec, pexec commands the zsig now goes through ztext formatting messages have id numbers now 'info' prints the msgid added the 'filter' command added the 'view' command added the 'show filter' command added the 'viewclass' (and 'vc') commands added the 'viewuser' (and 'vu') commands M-n will filter to the current class or user 'v' starts a view command M-D will delete all messages in current view added the 'delete' (and 'del') command load-subs with no argument loads the default subs file '' is now when the *current* message is truncated the reply-lockout filter (with default) specifices messages that cannot be replied to. in the configfile owl::receive_msg is run whenever a message is received added the beep command added the contributors file declare ZGetSubscriptions and ZGetLocations since the includes don't seem to fixed bug in displaying last line in popwin if no final '\n' 'T' uses the 'trash' filter now zaway_msg, zaway_msg_default and zaway are all user variables now. zsig variable overrides zsigproc If there's no appendtosepbar don't interfear with the sepbar Changed: owl_message_get_numlines will return 0 of m is NULL Added login messages to messages marked by owl_function_delete_automsgs Added owl_function_delete_by_id(id) which acts independent of view Added "-id " option to delete command Fixed an arg checking bug in delete command Added owl::id to perl namespace with message id Fixed a memory corruption bug in readconfig.c (where right after the strdup to "out", we'd strcat a \n onto the end. This would be triggered whenever owl::format_msg returned a string not ending in a newline Added 'X' keybinding which expunges and then switches to a view defined by the variable "view_home" which defaults to "all" Consolidated readconfig.c somewhat to remove duplication. owl_config_execute now returns a string. Added an example config file that does vt-style formatting. (examples/owlconf.vtformat) Added the 'perl', 'aperl', and 'pperl' commands which will evaluate perl expressions. Fixed bug where pclose zsigproc would cause zombies Can set zsigproc or zsig to "" to disable Added support for multiple browsers (galeon and none were added). Configure with the "webbrowser" variable. Changing typewinsize height triggers resize event. Added zsig variable which will be used if no zsigproc and non-empty. Added "make test" rule to Makefile which will run regression tests, and added regression testing framework to tester Fixed codelist.pl to ignore static declarations. Added dict.c which contains string->ptr dictionary routines and the owl_dict type. These include regression tests. Overhaul/rewrite of variable handling. Variables are now managed in an owl_vardict (in g.vars) which contains a dictionary of owl_variable's. Each owl_variable has dispatch functions for validating values, setting it and getting it, and for setting it to and from string values. The variable.c file contains the list of variables. Stubs for the owl_global__get functions and friends are generated from variable.c by stubgen.pl. The help.c messages for variables now calls into variable.c so all information about most variables is in one place. Cleaned out code from global.c and command.c that was made obselete by variable overhaul. The set command now takes a -q option to not log a message. Fixed a bug where set and print with no arguments would print "Undefined variable" in addition to running owl_function_printallvars. debug is now a variable that can be turned on and off. Fixed mail,inbox message parsing in examples/owlconf.erik Made zaway_msg and zaway_msg_default into variables Changed owl_function_makemsg and owl_function_debugmsg to use varargs (ie, so they can now take a format string with args). Don't allow " and \ characters in URLs with the "w" command. Removed lots of build warnings. Popwins are wider by default so help messages fit better. Added an atokenize_free function. Fixes to work with an older version of libzephyr. Added dependencies on header files to Makefile.in Added pageup and pagedown key bindings to message list Added pageup and pagedown to viewwin Added configfile section to doc/intro.txt (from example config file) Added appendtosepbar variable which may contain text which will be appended to the sepbar. This allows the configfile to put information about pings and logins into the sepbar. (It may be worth also providing a variable which enables this by default, but for now this allows for experimenting with what works well.) Added doc/code.txt which gives a brief overview of the code. Added tags makefile rule and added TAGS to distclean rule. 1.0.1 fix frees in loadsubs and loadloginsubs don't return in owl_free 1.0 'print' and 'set' with no arguments prints all variables Added the 'unsubscribe' and 'unsub' command Renamed the 'unsub' command to 'unsuball' Added the 'getsubs' command which is like zctl ret Fixed bug in logging messages sent to more than one recipient Support '-C', '-O', and '-n' options to zwrite Fixed bug in owl_editwin_delete_char when there are no later chars after the cursor Make "more" and "truncated" work in the status bar enable printing of zsigproc and loginsubs variables only allow message scrolling if the message is actually off the screen 'T' will mark all automated message for deletion 'P' will go to the next personal message 'M-P' will go to the previous personal message replying to a login message goes to the user now added a status command added the intro doc to the release fixed off by one bug in viewwin added complete online help pass $owl::realm in configfile fixed editwin wordwrapping on the last line fixed editwin problem with key_right past the last char print an error and quit if the configfile can't be parsed got rid of owl_mainwin_calculate_topmsg fixed off by one error in calculating topmsg upwards you can now reply to an admin message don't display an error about keypress on window resize 0.11 fixed bug in viewing messages longer than the screen indicate in the sepbar if there is a non zero vert offset send on '.' on a line by itself added disable-ctrl-d variable fixed bug where C-k did not delete the last \n in the buffer make non-character meta keys work use ZSendNotice instead of ZSendList implemented <, >, M-< and M-> in viewwin removed the spaces at the bottom of viewwin added 'about' command fixed bug using 'M' with no current message changed message object to use char *'s to save on memory change malloc, realloc, strdup and free to use owl hooks so that debugging can be added 0.10.1 fixed a trailing space bug in the parser impelemented the "burning ears" feature have admin messages do ztext parsing fixed bug in reporting which M- key was pressed C-g will now cancel commands like C-c 0.10 implemented owl_function_full_redisplay(). C-l uses owl_function_full_redisplay(). when a popwin exists to a full redisplay. (fixes bug) improved the owl_editwin_process_char logic removed all unnecessary wrefresh's and replaced with wnoutrefesh owl_editwin_redisplay now takes an argument to optionally doupdate() improved the cut-and-paste speed by not doing a usleep the first time through the loop after getting a keypress. nuked typwin.c and associated stuff. It's useless now. added viewwin code for paging windows curly braces work for zephyr formatting @i in zephyr formatting will be displayed as underlined text turned off idlok implemented viewwin implemented viewwi in popwin for pageable popwins help, info now use pageable popwins bound 'M' to bring the current message up in a popwin return, space bar, 'b' and backspace now scroll within a message turned off resize message C-v and M-v page the main window implemented owl_message_is_mail some build cleanup 0.9 added owl_message_is_personal and have things use it added owl_message_is_private fixed 'print personalbell' and have 'set personalbell' print a message bold only on message_is_personal display the realm if not local implemented M-f, M-b, M-d, M-<, M-> in editwin implemnted word wrapping in editwin implemented M-q (paragraph-fill) in editwin fixed bug that caused owl to segfault logging a 'weird' class M-x is a keysym for ':' added smart bolding and userclue fixed a bug causing pings to beep even if rxping is off 0.8.1 fixed bug in logging code 0.8 implemented personal logging implemented class logging implemented resize of typewin fixed the backspace problem -v command line option prints the version number 0.7 load-subs will report error opening file skip comment lines in loadsubs and loadloginsubs changed internal references to rxping and txping fix replying to a blank instance added subscribe command subscribe to login messages from .anyone by default 'loginsubs' variarble controlls automated login messages redisplay the editwin after a resize leave the cursor in the editwin if active fix problems in the build system added displayoutgoing variable temporarily removed error printing for zlog in / out 0.61 fixed bug in "message sent to " for zwrite 0.6 help updated zaway key set to caps A support zephyring other realms rxping variable for receiving pings txping variable for sending pings function in place to resize typwin C-l to refresh personal bell variable beta message now an admin message 0.5 Added the debug command and flag Fixed bug in printing fields in info command Added owl_fmtext_append_ztext and use it Better formating for pings and login zephyrs make tester depends on proto barnowl-1.10/stubgen.pl0000755000175000017500000000342113020626370012026 00000000000000print qq(/* THIS FILE WAS AUTOGENERATED BY STUBGEN.PL --- DO NOT EDIT BY HAND!!! */\n\n); print qq(#include "owl.h"); foreach $file (@ARGV) { open(FILE, $file); print "/* -------------------------------- $file -------------------------------- */\n"; while () { if (m|^\s*OWLVAR_([A-Z_0-9]+)\s*\(\s*"([^"]+)"\s*/\*\s*%OwlVarStub:?([a-z0-9_]+)?\s*\*/|) { # " my $vartype = $1; my $varname = $2; my $altvarname = $2; $altvarname = $3 if ($3); if ($vartype =~ /^BOOL/) { print "void owl_global_set_${altvarname}_on(owl_global *g) {\n"; print " owl_variable_set_bool_on(owl_variable_get_var(&g->vars, \"$varname\"));\n}\n"; print "void owl_global_set_${altvarname}_off(owl_global *g) {\n"; print " owl_variable_set_bool_off(owl_variable_get_var(&g->vars, \"$varname\"));\n}\n"; print "int owl_global_is_$altvarname(const owl_global *g) {\n"; print " return owl_variable_get_bool(owl_variable_get_var(&g->vars, \"$varname\"));\n}\n"; } elsif ($vartype =~ /^PATH/ or $vartype =~ /^STRING/) { print "void owl_global_set_$altvarname(owl_global *g, const char *text) {\n"; print " owl_variable_set_string(owl_variable_get_var(&g->vars, \"$varname\"), text);\n}\n"; print "const char *owl_global_get_$altvarname(const owl_global *g) {\n"; print " return owl_variable_get_string(owl_variable_get_var(&g->vars, \"$varname\"));\n}\n"; } elsif ($vartype =~ /^INT/ or $vartype =~ /^ENUM/) { print "void owl_global_set_$altvarname(owl_global *g, int n) {\n"; print " owl_variable_set_int(owl_variable_get_var(&g->vars, \"$varname\"), n);\n}\n"; print "int owl_global_get_$altvarname(const owl_global *g) {\n"; print " return owl_variable_get_int(owl_variable_get_var(&g->vars, \"$varname\"));\n}\n"; } } } close(FILE); print "\n"; } barnowl-1.10/perlglue.xs0000644000175000017500000002671213020626370012222 00000000000000/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #define OWL_PERL #include "owl.h" #define SV_IS_CODEREF(sv) (SvROK((sv)) && SvTYPE(SvRV((sv))) == SVt_PVCV) typedef char utf8; /************************************************************* * NOTE ************************************************************* * These functions, when they are intended to be user-visible, * are documented in perl/lib/BarnOwl.pm. If you add functions * to this file, add the appropriate documentation there! * * If the function is simple enough, we simply define its * entire functionality here in XS. If, however, it needs * complex argument processing or something, we define a * simple version here that takes arguments in as flat a * manner as possible, to simplify the XS code, put it in * BarnOwl::Internal::, and write a perl wrapper in BarnOwl.pm * that munges the arguments as appropriate and calls the * internal version. */ MODULE = BarnOwl PACKAGE = BarnOwl const utf8 * command(cmd, ...) const char *cmd PREINIT: char *rv = NULL; const char **argv; int i; CODE: { if (items == 1) { rv = owl_function_command(cmd); } else { /* Ensure this is NULL-terminated. */ argv = g_new0(const char *, items + 1); argv[0] = cmd; for(i = 1; i < items; i++) { argv[i] = SvPV_nolen(ST(i)); } rv = owl_function_command_argv(argv, items); g_free(argv); } RETVAL = rv; } OUTPUT: RETVAL CLEANUP: g_free(rv); SV * getcurmsg() CODE: RETVAL = owl_perlconfig_curmessage2hashref(); OUTPUT: RETVAL int getnumcols() CODE: RETVAL = owl_global_get_cols(&g); OUTPUT: RETVAL int getnumlines() CODE: RETVAL = owl_global_get_lines(&g); OUTPUT: RETVAL time_t getidletime() CODE: RETVAL = owl_global_get_idletime(&g); OUTPUT: RETVAL const utf8 * zephyr_getrealm() CODE: RETVAL = owl_zephyr_get_realm(); OUTPUT: RETVAL const utf8 * zephyr_getsender() CODE: RETVAL = owl_zephyr_get_sender(); OUTPUT: RETVAL const utf8 * ztext_stylestrip(ztext) const char *ztext PREINIT: char *rv = NULL; CODE: rv = owl_function_ztext_stylestrip(ztext); RETVAL = rv; OUTPUT: RETVAL CLEANUP: g_free(rv); const utf8 * zephyr_smartstrip_user(in) const char *in PREINIT: char *rv = NULL; CODE: { rv = owl_zephyr_smartstripped_user(in); RETVAL = rv; } OUTPUT: RETVAL CLEANUP: g_free(rv); const utf8 * zephyr_getsubs() PREINIT: char *rv = NULL; CODE: rv = owl_zephyr_getsubs(); RETVAL = rv; OUTPUT: RETVAL CLEANUP: g_free(rv); SV * queue_message(msg) SV *msg PREINIT: owl_message *m; CODE: { if(!SvROK(msg) || SvTYPE(SvRV(msg)) != SVt_PVHV) { croak("Usage: BarnOwl::queue_message($message)"); } m = owl_perlconfig_hashref2message(msg); owl_global_messagequeue_addmsg(&g, m); RETVAL = owl_perlconfig_message2hashref(m); } OUTPUT: RETVAL void admin_message(header, body) const char *header const char *body CODE: { owl_function_adminmsg(header, body); } const char * get_data_dir () CODE: RETVAL = owl_get_datadir(); OUTPUT: RETVAL const char * get_config_dir () CODE: RETVAL = owl_global_get_confdir(&g); OUTPUT: RETVAL void popless_text(text) const char *text CODE: { owl_function_popless_text(text); } void popless_ztext(text) const char *text CODE: { owl_fmtext fm; owl_fmtext_init_null(&fm); owl_fmtext_append_ztext(&fm, text); owl_function_popless_fmtext(&fm); owl_fmtext_cleanup(&fm); } void error(text) const char *text CODE: { owl_function_error("%s", text); } void debug(text) const char *text CODE: { owl_function_debugmsg("%s", text); } void message(text) const char *text CODE: { owl_function_makemsg("%s", text); } void create_style(name, object) const char *name SV *object PREINIT: owl_style *s; CODE: { s = g_slice_new(owl_style); owl_style_create_perl(s, name, newSVsv(object)); owl_global_add_style(&g, s); } int getnumcolors() CODE: RETVAL = owl_function_get_color_count(); OUTPUT: RETVAL void _remove_filter(filterName) const char *filterName CODE: { /* Don't delete the current view, or the 'all' filter */ if (strcmp(filterName, owl_view_get_filtname(owl_global_get_current_view(&g))) && strcmp(filterName, "all")) { owl_global_remove_filter(&g,filterName); } } bool message_matches_filter(message, filter_name, quiet = false) SV *message const char *filter_name bool quiet PREINIT: owl_message *m; const owl_filter *f; CODE: { if (!SvROK(message) || SvTYPE(SvRV(message)) != SVt_PVHV) { croak("Usage: BarnOwl::message_matches_filter($message, $filter_name[, $quiet])"); } m = owl_perlconfig_hashref2message(message); f = owl_global_get_filter(&g, filter_name); if (!f && !quiet) { owl_function_error("%s filter is not defined", filter_name); } RETVAL = f && owl_filter_message_match(f, m); } OUTPUT: RETVAL CLEANUP: owl_message_delete(m); const utf8 * wordwrap(in, cols) const char *in int cols PREINIT: char *rv = NULL; CODE: rv = owl_text_wordwrap(in, cols); RETVAL = rv; OUTPUT: RETVAL CLEANUP: g_free(rv); AV* all_filters() PREINIT: GPtrArray *fl; CODE: { fl = owl_dict_get_keys(&g.filters); RETVAL = owl_new_av(fl, (SV*(*)(const void*))owl_new_sv); sv_2mortal((SV*)RETVAL); owl_ptr_array_free(fl, g_free); } OUTPUT: RETVAL AV* all_styles() PREINIT: GPtrArray *l; CODE: { l = owl_global_get_style_names(&g); RETVAL = owl_new_av(l, (SV*(*)(const void*))owl_new_sv); sv_2mortal((SV*)RETVAL); } OUTPUT: RETVAL CLEANUP: owl_ptr_array_free(l, g_free); AV* all_variables() PREINIT: GPtrArray *l; CODE: { l = owl_dict_get_keys(owl_global_get_vardict(&g)); RETVAL = owl_new_av(l, (SV*(*)(const void*))owl_new_sv); sv_2mortal((SV*)RETVAL); } OUTPUT: RETVAL CLEANUP: owl_ptr_array_free(l, g_free); AV* all_keymaps() PREINIT: GPtrArray *l; const owl_keyhandler *kh; CODE: { kh = owl_global_get_keyhandler(&g); l = owl_keyhandler_get_keymap_names(kh); RETVAL = owl_new_av(l, (SV*(*)(const void*))owl_new_sv); sv_2mortal((SV*)RETVAL); } OUTPUT: RETVAL CLEANUP: owl_ptr_array_free(l, g_free); void redisplay() CODE: { owl_messagelist_invalidate_formats(owl_global_get_msglist(&g)); owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS); owl_mainwin_redisplay(owl_global_get_mainwin(&g)); } const char * get_zephyr_variable(name) const char *name; CODE: RETVAL = owl_zephyr_get_variable(name); OUTPUT: RETVAL const utf8 * skiptokens(str, n) const char *str; int n; CODE: RETVAL = skiptokens(str, n); OUTPUT: RETVAL MODULE = BarnOwl PACKAGE = BarnOwl::Zephyr int have_zephyr() CODE: RETVAL = owl_global_is_havezephyr(&g); OUTPUT: RETVAL MODULE = BarnOwl PACKAGE = BarnOwl::Internal int file_deleteline(filename, line, backup) const char *filename const char *line int backup CODE: RETVAL = owl_util_file_deleteline(filename, line, backup); OUTPUT: RETVAL void new_command(name, func, summary, usage, description) char *name SV *func char *summary char *usage char *description PREINIT: owl_cmd cmd; CODE: { if(!SV_IS_CODEREF(func)) { croak("Command function must be a coderef!"); } cmd.name = name; cmd.cmd_perl = newSVsv(func); cmd.summary = summary; cmd.usage = usage; cmd.description = description; cmd.validctx = OWL_CTX_ANY; cmd.cmd_aliased_to = NULL; cmd.cmd_args_fn = NULL; cmd.cmd_v_fn = NULL; cmd.cmd_i_fn = NULL; cmd.cmd_ctxargs_fn = NULL; cmd.cmd_ctxv_fn = NULL; cmd.cmd_ctxi_fn = NULL; owl_cmddict_add_cmd(owl_global_get_cmddict(&g), &cmd); } MODULE = BarnOwl PACKAGE = BarnOwl::Internal void new_variable(name, summary, description, validsettings, takes_on_off, get_tostring_fn, set_fromstring_fn, data) const char *name const char *summary const char *description const char *validsettings int takes_on_off SV *get_tostring_fn SV *set_fromstring_fn SV *data CODE: { /* data is somewhat redundant given we can create closures, but oh * well. Might be convenient sometimes. */ if(!SV_IS_CODEREF(get_tostring_fn)) { croak("To-string function must be a coderef!"); } if(!SV_IS_CODEREF(set_fromstring_fn)) { croak("From-string function must be a coderef!"); } owl_variable_dict_newvar_other(owl_global_get_vardict(&g), name, summary, description, validsettings, takes_on_off, perl_closure_new(get_tostring_fn, data, false), perl_closure_new(set_fromstring_fn, data, false)); } void start_edit(edit_type, line, callback) const char *edit_type const char *line SV *callback PREINIT: owl_editwin *e; CODE: { if (!SV_IS_CODEREF(callback)) croak("Callback must be a subref"); if (!strcmp(edit_type, "question")) e = owl_function_start_question(line); else if (!strcmp(edit_type, "password")) e = owl_function_start_password(line); else if (!strcmp(edit_type, "edit_win")) e = owl_function_start_edit_win(line); else croak("edit_type must be one of 'password', 'question', 'edit_win', not '%s'", edit_type); owl_editwin_set_cbdata(e, newSVsv(callback), owl_perlconfig_dec_refcnt); owl_editwin_set_callback(e, owl_perlconfig_edit_callback); } int zephyr_zwrite(cmd,msg) const char *cmd const char *msg CODE: RETVAL = owl_zwrite_create_and_send_from_line(cmd, msg); OUTPUT: RETVAL MODULE = BarnOwl PACKAGE = BarnOwl::Editwin int replace(count, string) int count; const char *string; PREINIT: owl_editwin *e; CODE: e = owl_global_current_typwin(&g); if (e) { RETVAL = owl_editwin_replace(e, count, string); } else { RETVAL = 0; } OUTPUT: RETVAL int point_move(delta) int delta; PREINIT: owl_editwin *e; CODE: e = owl_global_current_typwin(&g); if (e) { RETVAL = owl_editwin_point_move(e, delta); } else { RETVAL = 0; } OUTPUT: RETVAL int replace_region(string) const char *string; PREINIT: owl_editwin *e; CODE: e = owl_global_current_typwin(&g); if (e) { RETVAL = owl_editwin_replace_region(e, string); } else { RETVAL = 0; } OUTPUT: RETVAL const utf8 * get_region() PREINIT: char *region; owl_editwin *e; CODE: e = owl_global_current_typwin(&g); if (e) { region = owl_editwin_get_region(owl_global_current_typwin(&g)); } else { region = NULL; } RETVAL = region; OUTPUT: RETVAL CLEANUP: g_free(region); SV * save_excursion(sub) SV *sub; PROTOTYPE: & PREINIT: int count; owl_editwin *e; owl_editwin_excursion *x; CODE: { e = owl_global_current_typwin(&g); if(!e) croak("The edit window is not currently active!"); x = owl_editwin_begin_excursion(owl_global_current_typwin(&g)); PUSHMARK(SP); count = call_sv(sub, G_SCALAR|G_EVAL|G_NOARGS); SPAGAIN; owl_editwin_end_excursion(owl_global_current_typwin(&g), x); if(SvTRUE(ERRSV)) { croak(NULL); } if(count == 1) RETVAL = SvREFCNT_inc(POPs); else XSRETURN_UNDEF; } OUTPUT: RETVAL int current_column() PREINIT: owl_editwin *e; CODE: e = owl_global_current_typwin(&g); if (e) { RETVAL = owl_editwin_current_column(e); } else { RETVAL = 0; } OUTPUT: RETVAL int point() PREINIT: owl_editwin *e; CODE: e = owl_global_current_typwin(&g); if (e) { RETVAL = owl_editwin_get_point(e); } else { RETVAL = 0; } OUTPUT: RETVAL int mark() PREINIT: owl_editwin *e; CODE: e = owl_global_current_typwin(&g); if (e) { RETVAL = owl_editwin_get_mark(e); } else { RETVAL = 0; } OUTPUT: RETVAL barnowl-1.10/buddy.c0000644000175000017500000000227413020626370011277 00000000000000#include "owl.h" void owl_buddy_create(owl_buddy *b, int proto, const char *name) { b->proto=proto; b->name=g_strdup(name); b->idlesince=0; } const char *owl_buddy_get_name(const owl_buddy *b) { if (b->name) return(b->name); return(""); } int owl_buddy_is_idle(const owl_buddy *b) { if (b->isidle) return(1); return(0); } void owl_buddy_set_idle(owl_buddy *b) { b->isidle=1; } void owl_buddy_set_unidle(owl_buddy *b) { b->isidle=0; } int owl_buddy_get_proto(const owl_buddy *b) { return(b->proto); } int owl_buddy_is_proto_aim(const owl_buddy *b) { if (b->proto==OWL_PROTOCOL_AIM) return(1); return(0); } /* Set the buddy to have been idle since 'diff' minutes ago */ void owl_buddy_set_idle_since(owl_buddy *b, int diff) { time_t now; now=time(NULL); b->idlesince=now-(diff*60); } /* return the number of minutes the buddy has been idle */ int owl_buddy_get_idle_time(const owl_buddy *b) { time_t now; if (b->isidle) { now=time(NULL); return((now - b->idlesince)/60); } return(0); } void owl_buddy_cleanup(owl_buddy *b) { if (b->name) g_free(b->name); } void owl_buddy_delete(owl_buddy *b) { owl_buddy_cleanup(b); g_slice_free(owl_buddy, b); } barnowl-1.10/window.h0000644000175000017500000000505113020626370011500 00000000000000#ifndef INC_BARNOWL_WINDOW_H #define INC_BARNOWL_WINDOW_H #include #include #include G_BEGIN_DECLS #define OWL_TYPE_WINDOW (owl_window_get_type ()) #define OWL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OWL_TYPE_WINDOW, OwlWindow)) #define OWL_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OWL_TYPE_WINDOW)) #define OWL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OWL_TYPE_WINDOW, OwlWindowClass)) #define OWL_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OWL_TYPE_WINDOW)) #define OWL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OWL_TYPE_WINDOW, OwlWindowClass)) typedef struct _owl_window OwlWindow; typedef struct _OwlWindowClass OwlWindowClass; typedef OwlWindow owl_window; /* meh */ struct _OwlWindowClass { GObjectClass parent_class; /* default implementations for signals */ void (*redraw)(owl_window *, WINDOW *); void (*resized)(owl_window *); }; GType owl_window_get_type(void); owl_window *owl_window_get_screen(void); owl_window *owl_window_new(owl_window *parent); void owl_window_unlink(owl_window *w); void owl_window_children_foreach(owl_window *parent, GFunc func, gpointer user_data); owl_window *owl_window_parent(owl_window *parent); owl_window *owl_window_first_child(owl_window *parent); owl_window *owl_window_next_sibling(owl_window *w); owl_window *owl_window_previous_sibling(owl_window *w); void owl_window_show(owl_window *w); void owl_window_show_all(owl_window *w); void owl_window_hide(owl_window *w); bool owl_window_is_shown(owl_window *w); bool owl_window_is_realized(owl_window *w); bool owl_window_is_toplevel(owl_window *w); bool owl_window_is_subwin(owl_window *w); void owl_window_set_cursor(owl_window *w); void owl_window_set_default_cursor(owl_window *w); void owl_window_dirty(owl_window *w); void owl_window_dirty_children(owl_window *w); void owl_window_redraw_scheduled(void); void owl_window_get_position(owl_window *w, int *nlines, int *ncols, int *begin_y, int *begin_x); void owl_window_set_position(owl_window *w, int nlines, int ncols, int begin_y, int begin_x); void owl_window_move(owl_window *w, int begin_y, int begin_x); void owl_window_resize(owl_window *w, int nlines, int ncols); GSource *owl_window_redraw_source_new(void); /* Standard callback functions in windowcb.c */ void owl_window_erase_cb(owl_window *w, WINDOW *win, void *user_data); void owl_window_fill_parent_cb(owl_window *parent, void *user_data); G_END_DECLS #endif /* INC_BARNOWL_WINDOW_H */ barnowl-1.10/keypress.c0000644000175000017500000001210313020626370012025 00000000000000#include "owl.h" static const struct _owl_keypress_specialmap { int kj; const char *ks; } specialmap[] = { #ifdef KEY_CODE_YES { KEY_CODE_YES, "CODE_YES" }, #endif { KEY_MIN, "MIN" }, { KEY_BREAK, "BREAK" }, { KEY_DOWN, "DOWN" }, { KEY_UP, "UP" }, { KEY_LEFT, "LEFT" }, { KEY_RIGHT, "RIGHT" }, { KEY_HOME, "HOME" }, { KEY_BACKSPACE, "BACKSPACE" }, { KEY_F0, "F0" }, { KEY_F(1), "F1" }, { KEY_F(2), "F2" }, { KEY_F(3), "F3" }, { KEY_F(4), "F4" }, { KEY_F(5), "F5" }, { KEY_F(6), "F6" }, { KEY_F(7), "F7" }, { KEY_F(8), "F8" }, { KEY_F(9), "F9" }, { KEY_F(10), "F10" }, { KEY_F(11), "F11" }, { KEY_F(12), "F12" }, { KEY_DL, "DL" }, { KEY_IL, "IL" }, { KEY_DC, "DC" }, { KEY_IC, "IC" }, { KEY_EIC, "EIC" }, { KEY_CLEAR, "CLEAR" }, { KEY_EOS, "EOS" }, { KEY_EOL, "EOL" }, { KEY_SF, "SF" }, { KEY_SR, "SR" }, { KEY_NPAGE, "NPAGE" }, { KEY_PPAGE, "PPAGE" }, { KEY_STAB, "STAB" }, { KEY_CTAB, "CTAB" }, { KEY_CATAB, "CATAB" }, { KEY_ENTER, "ENTER" }, { KEY_SRESET, "SRESET" }, { KEY_RESET, "RESET" }, { KEY_PRINT, "PRINT" }, { KEY_LL, "LL" }, { KEY_A1, "A1" }, { KEY_A3, "A3" }, { KEY_B2, "B2" }, { KEY_C1, "C1" }, { KEY_C3, "C3" }, { KEY_BTAB, "BTAB" }, { KEY_BEG, "BEG" }, { KEY_CANCEL, "CANCEL" }, { KEY_CLOSE, "CLOSE" }, { KEY_COMMAND, "COMMAND" }, { KEY_COPY, "COPY" }, { KEY_CREATE, "CREATE" }, { KEY_END, "END" }, { KEY_EXIT, "EXIT" }, { KEY_FIND, "FIND" }, { KEY_HELP, "HELP" }, { KEY_MARK, "MARK" }, { KEY_MESSAGE, "MESSAGE" }, { KEY_MOVE, "MOVE" }, { KEY_NEXT, "NEXT" }, { KEY_OPEN, "OPEN" }, { KEY_OPTIONS, "OPTIONS" }, { KEY_PREVIOUS, "PREVIOUS" }, { KEY_REDO, "REDO" }, { KEY_REFERENCE, "REFERENCE" }, { KEY_REFRESH, "REFRESH" }, { KEY_REPLACE, "REPLACE" }, { KEY_RESTART, "RESTART" }, { KEY_RESUME, "RESUME" }, { KEY_SAVE, "SAVE" }, { KEY_SBEG, "SBEG" }, { KEY_SCANCEL, "SCANCEL" }, { KEY_SCOMMAND, "SCOMMAND" }, { KEY_SCOPY, "SCOPY" }, { KEY_SCREATE, "SCREATE" }, { KEY_SDC, "SDC" }, { KEY_SDL, "SDL" }, { KEY_SELECT, "SELECT" }, { KEY_SEND, "SEND" }, { KEY_SEOL, "SEOL" }, { KEY_SEXIT, "SEXIT" }, { KEY_SFIND, "SFIND" }, { KEY_SHELP, "SHELP" }, { KEY_SHOME, "SHOME" }, { KEY_SIC, "SIC" }, { KEY_SLEFT, "SLEFT" }, { KEY_SMESSAGE, "SMESSAGE" }, { KEY_SMOVE, "SMOVE" }, { KEY_SNEXT, "SNEXT" }, { KEY_SOPTIONS, "SOPTIONS" }, { KEY_SPREVIOUS, "SPREVIOUS" }, { KEY_SPRINT, "SPRINT" }, { KEY_SREDO, "SREDO" }, { KEY_SREPLACE, "SREPLACE" }, { KEY_SRIGHT, "SRIGHT" }, { KEY_SRSUME, "SRSUME" }, { KEY_SSAVE, "SSAVE" }, { KEY_SSUSPEND, "SSUSPEND" }, { KEY_SUNDO, "SUNDO" }, { KEY_SUSPEND, "SUSPEND" }, { KEY_UNDO, "UNDO" }, { KEY_MOUSE, "MOUSE" }, #ifdef KEY_RESIZE { KEY_RESIZE, "RESIZE" }, #endif { KEY_MAX, "MAX" }, { ' ', "SPACE" }, { 27, "ESCAPE" }, { 127, "DELETE" }, { '\r', "CR" }, { '\n', "LF" }, { '\t', "TAB" }, { 0, NULL } }; #define OWL_CTRL(key) ((key)&037) /* OWL_META is definied in owl.h */ CALLER_OWN char *owl_keypress_tostring(int j, int esc) { GString *kb; const struct _owl_keypress_specialmap *sm; kb = g_string_new(""); for (sm = specialmap; sm->kj!=0; sm++) { if (j == OWL_META(sm->kj) || (esc && j == sm->kj)) { g_string_append(kb, "M-"); g_string_append(kb, sm->ks); break; } else if (j == sm->kj) { g_string_append(kb, sm->ks); break; } } if (!kb->str[0]) { if (j & OWL_META(0)) { g_string_append(kb, "M-"); j &= ~OWL_META(0); } if ((OWL_CTRL(j) == j)) { g_string_append(kb, "C-"); j |= 0x40; if (isupper(j)) j = tolower(j); } if (isascii(j)) { g_string_append_c(kb, j); } } if (!kb->str[0]) { /* not a valid key */ g_string_free(kb, true); return NULL; } return g_string_free(kb, false); } /* returns ERR on failure, else a keycode */ int owl_keypress_fromstring(const char *kb) { const struct _owl_keypress_specialmap *sm; int ismeta=0, isctrl=0; int j = ERR; while (*kb && kb[1] == '-' && (kb[0] == 'C' || kb[0] == 'M')) { if ((kb[0] == 'C') && (kb[1] == '-')) { isctrl = 1; kb+=2; } if ((kb[0] == 'M') && (kb[1] == '-')) { ismeta = 1; kb+=2; } } if (isascii(kb[0]) && !kb[1]) { j = kb[0]; } else { for (sm = specialmap; sm->kj!=0; sm++) { if (!strcmp(sm->ks, kb)) { j = sm->kj; } } } if (j==ERR) return(ERR); if (isctrl) { j = OWL_CTRL(j); } if (ismeta) { j = OWL_META(j); } return(j); } barnowl-1.10/typemap0000644000175000017500000000021513020626370011417 00000000000000TYPEMAP utf8 * T_PV_UTF8 const utf8 * T_PV_UTF8 OUTPUT T_PV_UTF8 sv_setpv((SV*)$arg, $var); SvUTF8_on((SV*)$arg); barnowl-1.10/zbuddylist.c0000644000175000017500000000204413020626370012360 00000000000000#include "owl.h" void owl_zbuddylist_create(owl_zbuddylist *zb) { zb->zusers = g_ptr_array_new(); } int owl_zbuddylist_adduser(owl_zbuddylist *zb, const char *name) { int i; char *user; user=long_zuser(name); for (i = 0; i < zb->zusers->len; i++) { if (!strcasecmp(user, zb->zusers->pdata[i])) { g_free(user); return(-1); } } g_ptr_array_add(zb->zusers, user); return(0); } int owl_zbuddylist_deluser(owl_zbuddylist *zb, const char *name) { int i; char *user; user=long_zuser(name); for (i = 0; i < zb->zusers->len; i++) { if (!strcasecmp(user, zb->zusers->pdata[i])) { g_free(g_ptr_array_remove_index(zb->zusers, i)); g_free(user); return(0); } } g_free(user); return(-1); } int owl_zbuddylist_contains_user(const owl_zbuddylist *zb, const char *name) { int i; char *user; user=long_zuser(name); for (i = 0; i < zb->zusers->len; i++) { if (!strcasecmp(user, zb->zusers->pdata[i])) { g_free(user); return(1); } } g_free(user); return(0); } barnowl-1.10/variable.c0000644000175000017500000013370513020626370011761 00000000000000#include "owl.h" #include #include "gmarshal_funcs.h" /* TODO(davidben): When we can require 2.30 and up, remove this. */ #ifndef G_VALUE_INIT #define G_VALUE_INIT { 0, { { 0 } } } #endif typedef const char *(*get_string_t)(const owl_variable *); typedef int (*get_int_t)(const owl_variable *); typedef bool (*get_bool_t)(const owl_variable *); typedef int (*set_string_t)(owl_variable *, const char *); typedef int (*set_int_t)(owl_variable *, int); typedef int (*set_bool_t)(owl_variable *, bool); typedef int (*validate_string_t)(const owl_variable *, const char *); typedef int (*validate_int_t)(const owl_variable *, int); typedef int (*validate_bool_t)(const owl_variable *, bool); static void owl_variable_dict_newvar_bool_full(owl_vardict *vd, const char *name, bool default_val, const char *summary, const char *description, validate_bool_t validate_fn, set_bool_t set_fn, get_bool_t get_fn); static void owl_variable_dict_newvar_string_full(owl_vardict *vd, const char *name, const char *default_val, const char *summary, const char *description, const char *validsettings, validate_string_t validate_fn, set_string_t set_fn, get_string_t get_fn); static void owl_variable_dict_newvar_int_full(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validsettings, validate_int_t validate_fn, set_int_t set_fn, get_int_t get_fn); static void owl_variable_dict_newvar_enum_full(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validsettings, validate_int_t validate_fn, set_int_t set_fn, get_int_t get_fn); #define OWLVAR_BOOL(name, default, summary, description) \ owl_variable_dict_newvar_bool(vd, name, default, summary, description) #define OWLVAR_BOOL_FULL(name, default, summary, description, validate, set, get) \ owl_variable_dict_newvar_bool_full(vd, name, default, summary, description, \ validate, set, get) #define OWLVAR_INT(name, default, summary, description) \ owl_variable_dict_newvar_int(vd, name, default, summary, description) #define OWLVAR_INT_FULL(name,default,summary,description,validset,validate,set,get) \ owl_variable_dict_newvar_int_full(vd, name, default, summary, description, \ validset, validate, set, get) #define OWLVAR_PATH(name, default, summary, description) \ owl_variable_dict_newvar_path(vd, name, default, summary, description) #define OWLVAR_STRING(name, default, summary, description) \ owl_variable_dict_newvar_string(vd, name, default, summary, description) #define OWLVAR_STRING_FULL(name, default, validset, summary, description, validate, set, get) \ owl_variable_dict_newvar_string_full(vd, name, default, summary, description, \ validset, validate, set, get) /* enums are really integers, but where validset is a comma-separated * list of strings which can be specified. The tokens, starting at 0, * correspond to the values that may be specified. */ #define OWLVAR_ENUM(name, default, summary, description, validset) \ owl_variable_dict_newvar_enum(vd, name, default, summary, description, validset) #define OWLVAR_ENUM_FULL(name,default,summary,description,validset,validate, set, get) \ owl_variable_dict_newvar_enum_full(vd, name, default, summary, description, \ validset, validate, set, get) void owl_variable_add_defaults(owl_vardict *vd) { OWLVAR_STRING( "personalbell" /* %OwlVarStub */, "off", "ring the terminal bell when personal messages are received", "Can be set to 'on', 'off', or the name of a filter which\n" "messages need to match in order to ring the bell"); OWLVAR_BOOL( "bell" /* %OwlVarStub */, 1, "enable / disable the terminal bell", "" ); OWLVAR_BOOL_FULL( "debug" /* %OwlVarStub */, OWL_DEBUG, "whether debugging is enabled", "If set to 'on', debugging messages are logged to the\n" "file specified by the debugfile variable.\n", NULL, owl_variable_debug_set, NULL); OWLVAR_BOOL( "startuplogin" /* %OwlVarStub */, 1, "send a login message when BarnOwl starts", "" ); OWLVAR_BOOL( "shutdownlogout" /* %OwlVarStub */, 1, "send a logout message when BarnOwl exits", "" ); OWLVAR_BOOL( "rxping" /* %OwlVarStub */, 0, "display received pings", "" ); OWLVAR_BOOL( "txping" /* %OwlVarStub */, 1, "send pings", "" ); OWLVAR_BOOL( "sepbar_disable" /* %OwlVarStub */, 0, "disable printing information in the separator bar", "" ); OWLVAR_BOOL( "smartstrip" /* %OwlVarStub */, 1, "strip kerberos instance for reply", ""); OWLVAR_BOOL( "newlinestrip" /* %OwlVarStub */, 1, "strip leading and trailing newlines", ""); OWLVAR_BOOL( "displayoutgoing" /* %OwlVarStub */, 1, "display outgoing messages", "" ); OWLVAR_BOOL( "loginsubs" /* %OwlVarStub */, 1, "load logins from .anyone on startup", "" ); OWLVAR_BOOL( "logging" /* %OwlVarStub */, 0, "turn personal logging on or off", "If this is set to on, personal messages are\n" "logged in the directory specified\n" "by the 'logpath' variable. The filename in that\n" "directory is derived from the sender of the message.\n" ); OWLVAR_BOOL( "classlogging" /* %OwlVarStub */, 0, "turn class logging on or off", "If this is set to on, class messages are\n" "logged in the directory specified\n" "by the 'classlogpath' variable.\n" "The filename in that directory is derived from\n" "the name of the class to which the message was sent.\n" ); OWLVAR_ENUM( "loggingdirection" /* %OwlVarStub */, OWL_LOGGING_DIRECTION_BOTH, "specifies which kind of messages should be logged", "Can be one of 'both', 'in', or 'out'. If 'in' is\n" "selected, only incoming messages are logged, if 'out'\n" "is selected only outgoing messages are logged. If 'both'\n" "is selected both incoming and outgoing messages are\n" "logged.", "both,in,out"); OWLVAR_BOOL_FULL( "colorztext" /* %OwlVarStub */, 1, "allow @color() in zephyrs to change color", NULL, NULL, owl_variable_colorztext_set, NULL); OWLVAR_BOOL( "fancylines" /* %OwlVarStub */, 1, "Use 'nice' line drawing on the terminal.", "If turned off, dashes, pipes and pluses will be used\n" "to draw lines on the screen. Useful when the terminal\n" "is causing problems" ); OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1, "Do automatic zcrypt processing", "" ); OWLVAR_BOOL_FULL( "pseudologins" /* %OwlVarStub */, 0, "Enable zephyr pseudo logins", "When this is enabled, BarnOwl will periodically check the zephyr\n" "location of users in your .anyone file. If a user is present\n" "but sent no login message, or a user is not present that sent no\n" "logout message, a pseudo login or logout message will be created\n", NULL, owl_variable_pseudologins_set, NULL); OWLVAR_BOOL( "ignorelogins" /* %OwlVarStub */, 0, "Enable printing of login notifications", "When this is enabled, BarnOwl will print login and logout notifications\n" "for AIM, zephyr, or other protocols. If disabled BarnOwl will not print\n" "login or logout notifications.\n"); OWLVAR_STRING( "logfilter" /* %OwlVarStub */, "", "name of a filter controlling which messages to log", "If non empty, any messages matching the given filter will be logged.\n" "This is a completely separate mechanism from the other logging\n" "variables like logging, classlogging, loglogins, loggingdirection,\n" "etc. If you want this variable to control all logging, make sure\n" "all other logging variables are in their default state.\n"); OWLVAR_BOOL( "loglogins" /* %OwlVarStub */, 0, "Enable logging of login notifications", "When this is enabled, BarnOwl will log login and logout notifications\n" "for AIM, zephyr, or other protocols. If disabled BarnOwl will not print\n" "login or logout notifications.\n"); OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1, "don't send zephyrs on C-d", "If set to 'on', C-d won't send a zephyr from the edit\n" "window. If set to 'off', C-d will always send a zephyr\n" "being composed in the edit window. If set to 'middle',\n" "C-d will only ever send a zephyr if the cursor is at\n" "the end of the message being composed.\n\n" "Note that this works by changing the C-d keybinding\n" "in the editmulti keymap.\n", "off,middle,on", NULL, owl_variable_disable_ctrl_d_set, NULL); OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people", "path for logging personal zephyrs", "Specifies a directory which must exist.\n" "Files will be created in the directory for each sender.\n"); OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class", "path for logging class zephyrs", "Specifies a directory which must exist.\n" "Files will be created in the directory for each class.\n"); OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE, "path for logging debug messages when debugging is enabled", "This file will be logged to if 'debug' is set to 'on'.\n" "BarnOwl will append a dot and the current process's pid to the filename."); OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL, "name of a program to run that will generate zsigs", "This program should produce a zsig on stdout when run.\n" "Note that it is important that this program not block.\n\n" "See the documentation for 'zsig' for more information about\n" "how the outgoing zsig is chosen." ); OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL, "name of a program to run when new messages are present", "The named program will be run when BarnOwl receives new\n" "messages. It will not be run again until the first\n" "instance exits"); OWLVAR_STRING( "zsender" /* %OwlVarStub */, "", "zephyr sender name", "Allows you to customize the outgoing username in\n" "zephyrs. If this is unset, it will use your Kerberos\n" "principal. Note that customizing the sender name will\n" "cause your zephyrs to be sent unauthenticated."); OWLVAR_STRING( "zsigfunc" /* %OwlVarStub */, "BarnOwl::default_zephyr_signature()", "zsig perl function", "Called every time you start a zephyrgram without an\n" "explicit zsig. The default setting implements the policy\n" "described in the documentation for the 'zsig' variable.\n" "See also BarnOwl::random_zephyr_signature().\n"); OWLVAR_STRING( "zsig" /* %OwlVarStub */, "", "zephyr signature", "The zsig to get on outgoing messages. If this variable is\n" "unset, 'zsigproc' will be run to generate a zsig. If that is\n" "also unset, the 'zwrite-signature' zephyr variable will be\n" "used instead.\n"); OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "", "string to append to the end of the sepbar", "The sepbar is the bar separating the top and bottom\n" "of the BarnOwl screen. Any string specified here will\n" "be displayed on the right of the sepbar\n"); OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0, "turn zaway on or off", "" ); OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, OWL_DEFAULT_ZAWAYMSG, "zaway msg for responding to zephyrs when away", "" ); OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, OWL_DEFAULT_ZAWAYMSG, "default zaway message", "" ); OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0, "Set AIM away status", "", NULL, owl_variable_aaway_set, NULL); OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */, OWL_DEFAULT_AAWAYMSG, "AIM away msg for responding when away", "" ); OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */, OWL_DEFAULT_AAWAYMSG, "default AIM away message", "" ); OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all", "home view to switch to after 'X' and 'V'", "SEE ALSO: view, filter\n" ); OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none", "filter on which to trigger alert actions", "" ); OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop", "BarnOwl command to execute for alert actions", "" ); OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "", "tty name for zephyr location", "", NULL, owl_variable_tty_set, NULL); OWLVAR_STRING( "default_style" /* %OwlVarStub */, "default", "name of the default formatting style", "This sets the default message formatting style.\n" "Styles may be created with the 'style' command.\n" "Some built-in styles include:\n" " default - the default BarnOwl formatting\n" " oneline - one line per-message\n" " perl - legacy perl interface\n" "\nSEE ALSO: style, show styles, view -s