Index: Makefile.in
===================================================================
--- Makefile.in	(revision 702aee775414706d919e559a89ebda7e4837b6a4)
+++ Makefile.in	(revision 2bdfed9634a0f1ee28b359eca2d69367877f17fb)
@@ -45,5 +45,5 @@
 #AUTOGEN=$(GEN_C)
 
-HEADERS=$(GEN_H) owl.h config.h
+HEADERS=$(GEN_H) owl.h config.h test.h
 
 %.o: %.c $(HEADERS)
@@ -127,5 +127,5 @@
 	${INSTALL} -d ${DESTDIR}${datadir}/lib
 	${INSTALL} -d ${DESTDIR}${datadir}/modules
-	tar -C perl/lib --exclude .svn -c . | tar -C ${DESTDIR}${datadir}/lib -x
+	tar -C perl/lib --exclude .svn -cf - . | tar -C ${DESTDIR}${datadir}/lib -xf -
 	for i in $(PERL_MODULES); do \
 		${INSTALL_DATA} perl/modules/$$i/$$i.par ${DESTDIR}${datadir}/modules/$$i.par; \
Index: commands.c
===================================================================
--- commands.c	(revision 987ff51b9bf0519cc9627175070a8cbaa52b3775)
+++ commands.c	(revision fa4f9c3df1fc8c504f4a53b37a7d2a5da7370e6d)
@@ -132,6 +132,8 @@
   OWLCMD_ARGS("aimwrite", owl_command_aimwrite, OWL_CTX_INTERACTIVE,
 	      "send an AIM message",
-	      "aimzwrite <user>",
-	      "Send an aim message to a user.\n"),
+	      "aimwrite <user> [-m <message...>]",
+	      "Send an aim message to a user.\n\n" 
+              "The following options are available:\n\n"
+              "-m    Specifies a message to send without prompting.\n"),
 
   OWLCMD_ARGS("loopwrite", owl_command_loopwrite, OWL_CTX_INTERACTIVE,
@@ -280,4 +282,23 @@
 	      "suppressed to be received again.\n\n"
 	      "SEE ALSO:  zpunt, show zpunts\n"),
+
+  OWLCMD_ARGS("punt", owl_command_punt, OWL_CTX_ANY,
+	      "suppress an arbitrary filter",
+	      "punt <filter-name>",
+	      "punt <filter-text (multiple words)>\n"
+	      "The punt command will supress message to the specified\n"
+	      "filter\n\n"
+	      "SEE ALSO:  unpunt, zpunt, show zpunts\n"),
+
+  OWLCMD_ARGS("unpunt", owl_command_unpunt, OWL_CTX_ANY,
+	      "remove an entry from the punt list",
+	      "zpunt <filter-name>\n"
+	      "zpunt <filter-text>\n"
+	      "zpunt <number>\n",
+	      "The unpunt command will remove an entry from the puntlist.\n"
+	      "The first two forms correspond to the first two forms of the :punt\n"
+	      "command. The latter allows you to remove a specific entry from the\n"
+	      "the list (see :show zpunts)\n\n"
+	      "SEE ALSO:  punt, zpunt, zunpunt, show zpunts\n"),
 
   OWLCMD_VOID("info", owl_command_info, OWL_CTX_INTERACTIVE,
@@ -1867,6 +1888,7 @@
 char *owl_command_aimwrite(int argc, char **argv, char *buff)
 {
-  char *newbuff;
-  int i, j;
+  char *newbuff, *recip, **myargv;
+  int i, j, myargc;
+  owl_message *m;
   
   if (!owl_global_is_aimloggedin(&g)) {
@@ -1878,4 +1900,54 @@
     owl_function_makemsg("Not enough arguments to the aimwrite command.");
     return(NULL);
+  }
+
+  myargv=argv;
+  if (argc<0) {
+    owl_function_error("Unbalanced quotes in aimwrite");
+    return(NULL);
+  }
+  myargc=argc;
+  if (myargc && *(myargv[0])!='-') {
+    myargc--;
+    myargv++;
+  }
+  while (myargc) {
+    if (!strcmp(myargv[0], "-m")) {
+      if (myargc<2) {
+	break;
+      }
+
+      /* Once we have -m, gobble up everything else on the line */
+      myargv++;
+      myargc--;
+      newbuff=owl_malloc(1);
+      newbuff=owl_strdup("");
+      while (myargc) {
+	newbuff=realloc(newbuff, strlen(newbuff)+strlen(myargv[0])+5);
+	strcat(newbuff, myargv[0]);
+	strcat(newbuff, " ");
+	myargc--;
+	myargv++;
+      }
+      newbuff[strlen(newbuff)-1]='\0'; /* remove last space */
+
+      recip=owl_malloc(strlen(argv[0])+5);
+      sprintf(recip, "%s ", argv[1]);
+      owl_aim_send_im(recip, newbuff);
+      m=owl_function_make_outgoing_aim(newbuff, recip);
+      if (m) { 
+          owl_global_messagequeue_addmsg(&g, m);
+      } else {
+          owl_function_error("Could not create outgoing AIM message");
+      }
+
+      owl_free(recip);
+      owl_free(newbuff);
+      return(NULL);
+    } else {
+      /* we don't care */
+      myargv++;
+      myargc--;
+    }
   }
 
@@ -2142,7 +2214,6 @@
     char *filename;
     
-    filename=owl_sprintf("%s/%s", owl_global_get_homedir(&g), OWL_STARTUP_FILE);
+    filename=owl_global_get_startupfile(&g);
     owl_function_popless_file(filename);
-    owl_free(filename);
   } else if (!strcmp(argv[1], "errors")) {
     owl_function_showerrs();
@@ -2294,5 +2365,4 @@
   return NULL;
 }
-
 
 void owl_command_zpunt_and_zunpunt(int argc, char **argv, int type)
@@ -2345,4 +2415,50 @@
 }
 
+char *owl_command_punt(int argc, char **argv, char *buff)
+{
+  owl_command_punt_unpunt(argc, argv, buff, 0);
+  return NULL;
+}
+
+char *owl_command_unpunt(int argc, char **argv, char *buff)
+{
+  owl_command_punt_unpunt(argc, argv, buff, 1);
+  return NULL;
+}
+
+void owl_command_punt_unpunt(int argc, char ** argv, char *buff, int unpunt)
+{
+  owl_list * fl;
+  owl_filter * f;
+  char * text;
+  int i;
+
+  fl = owl_global_get_puntlist(&g);
+  if(argc == 1) {
+    owl_function_show_zpunts();
+  }
+
+  if(argc == 2) {
+    /* Handle :unpunt <number> */
+    if(unpunt && (i=atoi(argv[1])) !=0) {
+      i--;      /* Accept 1-based indexing */
+      if(i < owl_list_get_size(fl)) {
+        f = (owl_filter*)owl_list_get_element(fl, i);
+        owl_list_remove_element(fl, i);
+        owl_filter_free(f);
+        return;
+      } else {
+        owl_function_error("No such filter number: %d", i+1);
+      }
+    }
+    text = owl_sprintf("filter %s", argv[1]);
+  } else {
+    text = skiptokens(buff, 1);
+  }
+
+  owl_function_punt(text, unpunt);
+}
+
+
 char *owl_command_getview(int argc, char **argv, char *buff)
 {
@@ -2469,4 +2585,5 @@
   owl_message *m;
   owl_view *v;
+  char *cmd;
 
   v = owl_global_get_current_view(&g);
@@ -2487,5 +2604,5 @@
     return;
   }
-  char * cmd = owl_message_get_attribute_value(m, "yescommand");
+  cmd = owl_message_get_attribute_value(m, "yescommand");
   if(!cmd) {
     owl_function_error("No yes command!");
@@ -2502,4 +2619,5 @@
   owl_message *m;
   owl_view *v;
+  char *cmd;
 
   v = owl_global_get_current_view(&g);
@@ -2520,5 +2638,5 @@
     return;
   }
-  char * cmd = owl_message_get_attribute_value(m, "nocommand");
+  cmd = owl_message_get_attribute_value(m, "nocommand");
   if(!cmd) {
     owl_function_error("No no command!");
Index: configure.in
===================================================================
--- configure.in	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ configure.in	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -33,8 +33,12 @@
 
 dnl Check for kerberosIV include
-AC_MSG_CHECKING(for /usr/include/kerberosIV)
+AC_MSG_CHECKING(for kerberosIV)
 if test -d /usr/include/kerberosIV; then
         CFLAGS=${CFLAGS}\ -I/usr/include/kerberosIV
         CPPFLAGS=${CPPFLAGS}\ -I/usr/include/kerberosIV
+        AC_MSG_RESULT(yes)
+elif test -d /usr/local/include/kerberosIV; then
+        CFLAGS=${CFLAGS}\ -I/usr/local/include/kerberosIV
+        CPPFLAGS=${CPPFLAGS}\ -I/usr/local/include/kerberosIV
         AC_MSG_RESULT(yes)
 else
@@ -102,5 +106,5 @@
 fi
 
-dnl Add LDFLAGS for embeded perl
+dnl Add LDFLAGS for embedded perl
 FOO=`perl -MExtUtils::Embed -e ldopts`
 echo Adding perl LDFLAGS ${FOO}
@@ -117,7 +121,4 @@
 
 dnl Checks for typedefs, structures, and compiler characteristics.
-AC_CHECK_FILE(/usr/share/terminfo, AC_DEFINE(TERMINFO, "/usr/share/terminfo", [Have terminfo]),
-  AC_CHECK_FILE(/usr/share/lib/terminfo, AC_DEFINE(TERMINFO, "/usr/share/lib/terminfo", [Have terminfo]),
-  AC_MSG_ERROR(No terminfo found for this system)))
 
 AC_SUBST(XSUBPPDIR)
Index: debian/control
===================================================================
--- debian/control	(revision 8d1a33ff37eff9eb1930d8fe2a8abcd062668b0d)
+++ debian/control	(revision c7172b3ff8b6b7574dc69e953f84627d3a5f1011)
@@ -3,5 +3,5 @@
 Priority: optional
 Maintainer: Sam Hartman <hartmans@debian.org>
-Build-Depends: debhelper (>> 4.0.0), libzephyr-dev (>= 2.1.20010518.SNAPSHOT-7), libncurses5-dev, libkrb5-dev, libperl-dev
+Build-Depends: debhelper (>> 4.0.0), libzephyr-dev (>= 2.1.20010518.SNAPSHOT-7), libncurses5-dev, libkrb5-dev, libperl-dev, zip
 Standards-Version: 3.5.2
 
@@ -12,7 +12,7 @@
 Description: A curses-based tty Jabber and Zephyr client.
  An alternative standalone (doesn't use zwgc) Zephyr (instant
- messaging) client.  Also supports Jabber.
+ messaging) client.  Also supports AIM and Jabber.
  Much of the functionality is written in Perl, which is supported as 
  an extension language.
  .
- ktools software -- The 'k' is for Quality!
+ This is a fork of ktools software's owl Zephyr/AIM client
Index: dict.c
===================================================================
--- dict.c	(revision 0138478b33d7650c789c4c6e40eec517dc455795)
+++ dict.c	(revision 1cf3f8d3cf08ed3fb38d1c83459a1db140cb0d17)
@@ -152,5 +152,5 @@
   char *av="aval", *bv="bval", *cv="cval", *dv="dval";
 
-  printf("BEGIN testing owl_dict\n");
+  printf("# BEGIN testing owl_dict\n");
   FAIL_UNLESS("create", 0==owl_dict_create(&d));
   FAIL_UNLESS("insert b", 0==owl_dict_insert_element(&d, "b", (void*)bv, owl_dict_noop_free));
@@ -179,6 +179,6 @@
   owl_dict_free_all(&d, NULL);
 
-  if (numfailed) printf("*** WARNING: failures encountered with owl_dict\n");
-  printf("END testing owl_dict (%d failures)\n", numfailed);
+  //  if (numfailed) printf("*** WARNING: failures encountered with owl_dict\n");
+  printf("# END testing owl_dict (%d failures)\n", numfailed);
   return(numfailed);
 }
Index: filter.c
===================================================================
--- filter.c	(revision d791cdbe7393155e834e40ea2719136a81d0695c)
+++ filter.c	(revision ad15610ead2550219224b67ce4c2d7da2819e4df)
@@ -63,11 +63,11 @@
 static owl_filterelement * owl_filter_parse_primitive_expression(int argc, char **argv, int *next)
 {
+  owl_filterelement *fe, *op;
+  int i = 0, skip;
+
   if(!argc) return NULL;
 
-  owl_filterelement * fe = owl_malloc(sizeof(owl_filterelement));
-  owl_filterelement *op;
-
+  fe = owl_malloc(sizeof(owl_filterelement));
   owl_filterelement_create(fe);
-  int i = 0, skip;
 
   if(!strcasecmp(argv[i], "(")) {
@@ -118,5 +118,5 @@
 {
   int i = 0, skip;
-  owl_filterelement * op1 = NULL, * op2 = NULL;
+  owl_filterelement * op1 = NULL, * op2 = NULL, *tmp;
 
   op1 = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
@@ -129,5 +129,5 @@
     op2 = owl_filter_parse_primitive_expression(argc-i-1, argv+i+1, &skip);
     if(!op2) goto err;
-    owl_filterelement * tmp = owl_malloc(sizeof(owl_filterelement));
+    tmp = owl_malloc(sizeof(owl_filterelement));
     if(!strcasecmp(argv[i], "and")) {
       owl_filterelement_create_and(tmp, op1, op2);
@@ -204,6 +204,7 @@
 int owl_filter_message_match(owl_filter *f, owl_message *m)
 {
+  int ret;
   if(!f->root) return 0;
-  int ret = owl_filterelement_match(f->root, m);
+  ret = owl_filterelement_match(f->root, m);
   if(f->polarity) ret = !ret;
   return ret;
@@ -283,5 +284,5 @@
   int failed = 0;
   if(owl_filter_init_fromstring(&f, "test-filter", filt)) {
-    printf("\tFAIL: parse %s\n", filt);
+    printf("not ok can't parse %s\n", filt);
     failed = 1;
     goto out;
@@ -289,5 +290,5 @@
   ok = owl_filter_message_match(&f, m);
   if((shouldmatch && !ok) || (!shouldmatch && ok)) {
-    printf("\tFAIL: match %s (got %d, expected %d)\n", filt, ok, shouldmatch);
+    printf("not ok match %s (got %d, expected %d)\n", filt, ok, shouldmatch);
     failed = 1;
   }
@@ -295,5 +296,5 @@
   owl_filter_free(&f);
   if(!failed) {
-    printf("\tok  : %s %s\n", shouldmatch ? "matches" : "doesn't match", filt);
+    printf("ok %s %s\n", shouldmatch ? "matches" : "doesn't match", filt);
   }
   return failed;
@@ -305,7 +306,9 @@
 
 int owl_filter_regtest(void) {
-  owl_list_create(&(g.filterlist));
   int numfailed=0;
   owl_message m;
+  owl_filter f1, f2, f3, f4;
+
+  owl_list_create(&(g.filterlist));
   owl_message_init(&m);
   owl_message_set_type_zephyr(&m);
@@ -345,6 +348,4 @@
   TEST_FILTER("true and false or false", 0);
 
-  owl_filter f1, f2, f3, f4;
-
   owl_filter_init_fromstring(&f1, "f1", "class owl");
   owl_global_add_filter(&g, &f1);
Index: functions.c
===================================================================
--- functions.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ functions.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -580,4 +580,5 @@
 
   if (i>owl_view_get_size(v)-1) i=owl_view_get_size(v)-1;
+  if (i<0) i=0;
 
   if (!found) {
@@ -848,10 +849,12 @@
 {
   int ret, ret2;
-  char *foo;
+  char *foo, *path;
 
   if (file==NULL) {
     ret=owl_zephyr_loadsubs(NULL, 0);
   } else {
-    ret=owl_zephyr_loadsubs(file, 1);
+    path = owl_util_makepath(file);
+    ret=owl_zephyr_loadsubs(path, 1);
+    free(path);
   }
 
@@ -2057,78 +2060,77 @@
       /* if it's a zephyr we sent, send it out the same way again */
       if (owl_message_is_direction_out(m)) {
-	owl_function_zwrite_setup(owl_message_get_zwriteline(m));
-	owl_global_set_buffercommand(&g, owl_message_get_zwriteline(m));
-	return;
+          buff = owl_strdup(owl_message_get_zwriteline(m));
+      } else {
+
+        /* Special case a personal reply to a webzephyr user on a class */
+        if ((type==1) && !strcasecmp(owl_message_get_opcode(m), OWL_WEBZEPHYR_OPCODE)) {
+          class=OWL_WEBZEPHYR_CLASS;
+          inst=owl_message_get_sender(m);
+          to=OWL_WEBZEPHYR_PRINCIPAL;
+        } else if (!strcasecmp(owl_message_get_class(m), OWL_WEBZEPHYR_CLASS) && owl_message_is_loginout(m)) {
+          /* Special case LOGIN/LOGOUT notifications on class "webzephyr" */
+          class=OWL_WEBZEPHYR_CLASS;
+          inst=owl_message_get_instance(m);
+          to=OWL_WEBZEPHYR_PRINCIPAL;
+        } else if (owl_message_is_loginout(m)) {
+          /* Normal LOGIN/LOGOUT messages */
+          class="MESSAGE";
+          inst="PERSONAL";
+          to=owl_message_get_sender(m);
+        } else if (type==1) {
+          /* Personal reply */
+          class="MESSAGE";
+          inst="PERSONAL";
+          to=owl_message_get_sender(m);
+        } else {
+          /* General reply */
+          class=owl_message_get_class(m);
+          inst=owl_message_get_instance(m);
+          to=owl_message_get_recipient(m);
+          cc=owl_message_get_cc_without_recipient(m);
+          if (!strcmp(to, "") || !strcmp(to, "*")) {
+            to="";
+          } else if (to[0]=='@') {
+            /* leave it, to get the realm */
+          } else {
+            to=owl_message_get_sender(m);
+          }
+        }
+
+        /* create the command line */
+        if (!strcasecmp(owl_message_get_opcode(m), "CRYPT")) {
+          buff=owl_strdup("zcrypt");
+        } else {
+          buff = owl_strdup("zwrite");
+        }
+        if (strcasecmp(class, "message")) {
+          buff = owl_sprintf("%s -c %s%s%s", oldbuff=buff, owl_getquoting(class), class, owl_getquoting(class));
+          owl_free(oldbuff);
+        }
+        if (strcasecmp(inst, "personal")) {
+          buff = owl_sprintf("%s -i %s%s%s", oldbuff=buff, owl_getquoting(inst), inst, owl_getquoting(inst));
+          owl_free(oldbuff);
+        }
+        if (*to != '\0') {
+          char *tmp, *oldtmp, *tmp2;
+          tmp=short_zuser(to);
+          if (cc) {
+            tmp = owl_util_uniq(oldtmp=tmp, cc, "-");
+            owl_free(oldtmp);
+            buff = owl_sprintf("%s -C %s", oldbuff=buff, tmp);
+            owl_free(oldbuff);
+          } else {
+            if (owl_global_is_smartstrip(&g)) {
+              tmp2=tmp;
+              tmp=owl_zephyr_smartstripped_user(tmp2);
+              owl_free(tmp2);
+            }
+            buff = owl_sprintf("%s %s", oldbuff=buff, tmp);
+            owl_free(oldbuff);
+          }
+          owl_free(tmp);
+        }
+        if (cc) owl_free(cc);
       }
-
-      /* Special case a personal reply to a webzephyr user on a class */
-      if ((type==1) && !strcasecmp(owl_message_get_opcode(m), OWL_WEBZEPHYR_OPCODE)) {
-	class=OWL_WEBZEPHYR_CLASS;
-	inst=owl_message_get_sender(m);
-	to=OWL_WEBZEPHYR_PRINCIPAL;
-      } else if (!strcasecmp(owl_message_get_class(m), OWL_WEBZEPHYR_CLASS) && owl_message_is_loginout(m)) {
-	/* Special case LOGIN/LOGOUT notifications on class "webzephyr" */
-	class=OWL_WEBZEPHYR_CLASS;
-	inst=owl_message_get_instance(m);
-	to=OWL_WEBZEPHYR_PRINCIPAL;
-      } else if (owl_message_is_loginout(m)) {
-	/* Normal LOGIN/LOGOUT messages */
-	class="MESSAGE";
-	inst="PERSONAL";
-	to=owl_message_get_sender(m);
-      } else if (type==1) {
-	/* Personal reply */
-	class="MESSAGE";
-	inst="PERSONAL";
-	to=owl_message_get_sender(m);
-      } else {
-	/* General reply */
-	class=owl_message_get_class(m);
-	inst=owl_message_get_instance(m);
-	to=owl_message_get_recipient(m);
-	cc=owl_message_get_cc_without_recipient(m);
-	if (!strcmp(to, "") || !strcmp(to, "*")) {
-	  to="";
-	} else if (to[0]=='@') {
-	  /* leave it, to get the realm */
-	} else {
-	  to=owl_message_get_sender(m);
-	}
-      }
-	
-      /* create the command line */
-      if (!strcasecmp(owl_message_get_opcode(m), "CRYPT")) {
-	buff=owl_strdup("zcrypt");
-      } else {
-	buff = owl_strdup("zwrite");
-      }
-      if (strcasecmp(class, "message")) {
-	buff = owl_sprintf("%s -c %s%s%s", oldbuff=buff, owl_getquoting(class), class, owl_getquoting(class));
-	owl_free(oldbuff);
-      }
-      if (strcasecmp(inst, "personal")) {
-	buff = owl_sprintf("%s -i %s%s%s", oldbuff=buff, owl_getquoting(inst), inst, owl_getquoting(inst));
-	owl_free(oldbuff);
-      }
-      if (*to != '\0') {
-	char *tmp, *oldtmp, *tmp2;
-	tmp=short_zuser(to);
-	if (cc) {
-	  tmp = owl_util_uniq(oldtmp=tmp, cc, "-");
-	  owl_free(oldtmp);
-	  buff = owl_sprintf("%s -C %s", oldbuff=buff, tmp);
-	  owl_free(oldbuff);
-	} else {
-	  if (owl_global_is_smartstrip(&g)) {
-	    tmp2=tmp;
-	    tmp=owl_zephyr_smartstripped_user(tmp2);
-	    owl_free(tmp2);
-	  }
-	  buff = owl_sprintf("%s %s", oldbuff=buff, tmp);
-	  owl_free(oldbuff);
-	}
-	owl_free(tmp);
-      }
-      if (cc) owl_free(cc);
     } else if (owl_message_is_type_aim(m)) {
       /* aim */
@@ -2557,4 +2559,6 @@
   for (i=0; i<j; i++) {
     f=owl_list_get_element(fl, i);
+    snprintf(buff, sizeof(buff), "[% 2d] ", i+1);
+    owl_fmtext_append_normal(&fm, buff);
     owl_filter_print(f, buff);
     owl_fmtext_append_normal(&fm, buff);
@@ -2622,5 +2626,5 @@
   sprintf(argbuff, "class ^(un)*%s(\\.d)*$", tmpclass);
   if (tmpinstance) {
-    sprintf(argbuff, "%s and ( instance ^%s(\\.d)*$ )", argbuff, tmpinstance);
+    sprintf(argbuff, "%s and ( instance ^(un)*%s(\\.d)*$ )", argbuff, tmpinstance);
   }
   owl_free(tmpclass);
@@ -2670,7 +2674,7 @@
 
   argbuff=owl_malloc(strlen(longuser)+1000);
-  sprintf(argbuff, "( type ^zephyr$ and ( class ^message$ and instance ^personal$ and ");
+  sprintf(argbuff, "( type ^zephyr$ and filter personal and ");
   sprintf(argbuff, "%s ( ( direction ^in$ and sender ^%s$ ) or ( direction ^out$ and recipient ^%s$ ) ) )", argbuff, longuser, longuser);
-  sprintf(argbuff, "%s or ( ( class ^login$ ) and ( sender ^%s$ ) ) )", argbuff, longuser);
+  sprintf(argbuff, "%s or ( ( class ^login$ ) and ( sender ^%s$ ) )", argbuff, longuser);
 
   owl_filter_init_fromstring(f, filtname, argbuff);
@@ -2800,4 +2804,5 @@
   owl_message *m;
   char *zperson, *filtname=NULL;
+  char *argv[1];
   
   v=owl_global_get_current_view(&g);
@@ -2831,5 +2836,5 @@
   /* narrow personal and login messages to the sender or recip as appropriate */
   if (owl_message_is_type_zephyr(m)) {
-    if (owl_message_is_private(m) || owl_message_is_loginout(m)) {
+    if (owl_message_is_personal(m) || owl_message_is_loginout(m)) {
       if (owl_message_is_direction_in(m)) {
         zperson=short_zuser(owl_message_get_sender(m));
@@ -2858,5 +2863,4 @@
 
   /* pass it off to perl */
-  char *argv[1];
   if(type) {
     argv[0] = "-i";
@@ -3016,14 +3020,7 @@
 void owl_function_zpunt(char *class, char *inst, char *recip, int direction)
 {
-  owl_filter *f;
-  owl_list *fl;
   char *buff;
   char *quoted;
-  int ret, i, j;
-
-  fl=owl_global_get_puntlist(&g);
-
-  /* first, create the filter */
-  f=owl_malloc(sizeof(owl_filter));
+
   buff=owl_malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
   strcpy(buff, "class");
@@ -3056,8 +3053,21 @@
     owl_free(quoted);
   }
-  
-  owl_function_debugmsg("About to filter %s", buff);
-  ret=owl_filter_init_fromstring(f, "punt-filter", buff);
+
+  owl_function_punt(buff, direction);
   owl_free(buff);
+}
+
+void owl_function_punt(char *filter, int direction)
+{
+  owl_filter *f;
+  owl_list *fl;
+  int ret, i, j;
+  fl=owl_global_get_puntlist(&g);
+
+  /* first, create the filter */
+  f=malloc(sizeof(owl_filter));
+
+  owl_function_debugmsg("About to filter %s", filter);
+  ret=owl_filter_init_fromstring(f, "punt-filter", filter);
   if (ret) {
     owl_function_error("Error creating filter for zpunt");
@@ -3070,4 +3080,5 @@
   for (i=0; i<j; i++) {
     if (owl_filter_equiv(f, owl_list_get_element(fl, i))) {
+      owl_function_debugmsg("found an equivalent punt filter");
       /* if we're punting, then just silently bow out on this duplicate */
       if (direction==0) {
@@ -3080,4 +3091,5 @@
 	owl_filter_free(owl_list_get_element(fl, i));
 	owl_list_remove_element(fl, i);
+        owl_filter_free(f);
 	return;
       }
@@ -3085,4 +3097,5 @@
   }
 
+  owl_function_debugmsg("punting");
   /* If we're punting, add the filter to the global punt list */
   if (direction==0) {
@@ -3461,9 +3474,8 @@
   char *filename;
 
-  filename=owl_sprintf("%s/%s", owl_global_get_homedir(&g), OWL_STARTUP_FILE);
+  filename=owl_global_get_startupfile(&g);
   file=fopen(filename, "a");
   if (!file) {
     owl_function_error("Error opening startupfile for new command");
-    owl_free(filename);
     return;
   }
@@ -3471,5 +3483,4 @@
   /* delete earlier copies */
   owl_util_file_deleteline(filename, buff, 1);
-  owl_free(filename);
 
   /* add this line */
@@ -3483,7 +3494,6 @@
 {
   char *filename;
-  filename=owl_sprintf("%s/%s", owl_global_get_homedir(&g), OWL_STARTUP_FILE);
+  filename=owl_global_get_startupfile(&g);
   owl_util_file_deleteline(filename, buff, 1);
-  owl_free(filename);
 }
 
@@ -3497,7 +3507,6 @@
 
   if (!filename) {
-    filename=owl_sprintf("%s/%s", owl_global_get_homedir(&g), OWL_STARTUP_FILE);
+    filename=owl_global_get_startupfile(&g);
     file=fopen(filename, "r");
-    owl_free(filename);
   } else {
     file=fopen(filename, "r");
Index: global.c
===================================================================
--- global.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ global.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -18,4 +18,5 @@
   struct hostent *hent;
   char hostname[MAXHOSTNAMELEN];
+  char *cd;
 
   g->malloced=0;
@@ -86,4 +87,10 @@
   g->homedir=owl_strdup(getenv("HOME"));
 
+  g->confdir = NULL;
+  g->startupfile = NULL;
+  cd = owl_sprintf("%s/%s", g->homedir, OWL_CONFIG_DIR);
+  owl_global_set_confdir(g, cd);
+  owl_free(cd);
+
   owl_messagelist_create(&(g->msglist));
   owl_mainwin_init(&(g->mw));
@@ -319,4 +326,24 @@
 }
 
+char *owl_global_get_confdir(owl_global *g) {
+  if (g->confdir) return(g->confdir);
+  return("/");
+}
+
+/*
+ * Setting this also sets startupfile to confdir/startup
+ */
+void owl_global_set_confdir(owl_global *g, char *cd) {
+  free(g->confdir);
+  g->confdir = owl_strdup(cd);
+  free(g->startupfile);
+  g->startupfile = owl_sprintf("%s/startup", cd);
+}
+
+char *owl_global_get_startupfile(owl_global *g) {
+  if(g->startupfile) return(g->startupfile);
+  return("/");
+}
+
 int owl_global_get_direction(owl_global *g) {
   return(g->direction);
Index: keys.c
===================================================================
--- keys.c	(revision 51c57f85d3389f7f5f0c240308b276881c5dda5f)
+++ keys.c	(revision 8938188651289a80e4f3129f765c9ac991d254a3)
@@ -180,4 +180,5 @@
   BIND_CMD("M-<",         "popless:scroll-to-top", "");
 
+  BIND_CMD("END",         "popless:scroll-to-bottom", "");
   BIND_CMD(">",           "popless:scroll-to-bottom", "");
   BIND_CMD("M->",         "popless:scroll-to-bottom", "");
Index: message.c
===================================================================
--- message.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ message.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -27,8 +27,8 @@
 owl_fmtext_cache * owl_message_next_fmtext() /*noproto*/
 {
+    owl_fmtext_cache * f = fmtext_cache_next;
     if(fmtext_cache_next->message != NULL) {
         owl_message_invalidate_format(fmtext_cache_next->message);
     }
-    owl_fmtext_cache * f = fmtext_cache_next;
     fmtext_cache_next++;
     if(fmtext_cache_next - fmtext_cache == OWL_FMTEXT_CACHE_SIZE)
@@ -121,4 +121,9 @@
     p=owl_list_get_element(&(m->attributes), i);
     buff=owl_sprintf("  %-15.15s: %-35.35s\n", owl_pair_get_key(p), owl_pair_get_value(p));
+    if(buff == NULL) {
+      buff=owl_sprintf("  %-15.15s: %-35.35s\n", owl_pair_get_key(p), "<error>");
+      if(buff == NULL)
+        buff=owl_strdup("   <error>\n");
+    }
     owl_fmtext_append_normal(fm, buff);
     owl_free(buff);
@@ -417,4 +422,5 @@
 char *owl_message_get_text(owl_message *m)
 {
+  owl_message_format(m);
   return(owl_fmtext_get_text(&(m->fmtext->fmtext)));
 }
@@ -566,6 +572,7 @@
 
 int owl_message_is_answered(owl_message *m) {
+  char *q;
   if(!owl_message_is_question(m)) return 0;
-  char * q = owl_message_get_attribute_value(m, "question");
+  q = owl_message_get_attribute_value(m, "question");
   if(!q) return 0;
   return !strcmp(q, "answered");
@@ -813,4 +820,5 @@
   struct hostent *hent;
   char *ptr, *tmp, *tmp2;
+  int len;
 
   owl_message_init(m);
@@ -841,5 +849,5 @@
     owl_message_set_opcode(m, "");
   }
-  owl_message_set_zsig(m, n->z_message);
+  owl_message_set_zsig(m, owl_zephyr_get_zsig(n, &len));
 
   if ((ptr=strchr(n->z_recipient, '@'))!=NULL) {
Index: obarray.c
===================================================================
--- obarray.c	(revision db90f031ba656e1e552c2fa0ef3a8b57be62e2ca)
+++ obarray.c	(revision 535d68bc01fbedad4a7e0bbdbf8a4758fe2ce03f)
@@ -80,5 +80,5 @@
   owl_obarray_init(&oa);
 
-  printf("BEGIN testing owl_obarray\n");
+  printf("# BEGIN testing owl_obarray\n");
 
   p = owl_obarray_insert(&oa, "test");
@@ -96,5 +96,5 @@
   FAIL_UNLESS("Didn't find a string that isn't there", p == NULL);
 
-  printf("END testing owl_obarray (%d failures)\n", numfailed);
+  printf("# END testing owl_obarray (%d failures)\n", numfailed);
 
   return numfailed;
Index: owl.c
===================================================================
--- owl.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ owl.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -65,4 +65,11 @@
 owl_global g;
 
+char * owl_get_datadir() {
+    char * datadir = getenv("BARNOWL_DATA_DIR");
+    if(datadir != NULL)
+        return strchr(datadir, '=') + 1;
+    return DATADIR;
+}
+
 int main(int argc, char **argv, char **env)
 {
@@ -74,4 +81,5 @@
   struct sigaction sigact;
   char *configfile, *tty, *perlout, *perlerr, **argvsave, buff[LINE], startupmsg[LINE];
+  char *confdir;
   owl_filter *f;
   owl_style *s;
@@ -88,4 +96,5 @@
   argvsave=argv;
   configfile=NULL;
+  confdir = NULL;
   tty=NULL;
   debug=0;
@@ -105,7 +114,7 @@
     } else if (!strcmp(argv[0], "-c")) {
       if (argc<2) {
-	fprintf(stderr, "Too few arguments to -c\n");
-	usage();
-	exit(1);
+        fprintf(stderr, "Too few arguments to -c\n");
+        usage();
+        exit(1);
       }
       configfile=argv[1];
@@ -114,9 +123,18 @@
     } else if (!strcmp(argv[0], "-t")) {
       if (argc<2) {
-	fprintf(stderr, "Too few arguments to -t\n");
-	usage();
-	exit(1);
+        fprintf(stderr, "Too few arguments to -t\n");
+        usage();
+        exit(1);
       }
       tty=argv[1];
+      argv+=2;
+      argc-=2;
+    } else if (!strcmp(argv[0], "-s")){
+      if (argc<2) {
+        fprintf(stderr, "Too few arguments to -s\n");
+        usage();
+        exit(1);
+      }
+      confdir = argv[1];
       argv+=2;
       argc-=2;
@@ -131,5 +149,5 @@
       argc--;
     } else if (!strcmp(argv[0], "-v")) {
-      printf("This is owl version %s\n", OWL_VERSION_STRING);
+      printf("This is barnowl version %s\n", OWL_VERSION_STRING);
       exit(0);
     } else {
@@ -163,7 +181,5 @@
   /* screen init */
   if (!getenv("TERMINFO")) {
-    sprintf(buff, "TERMINFO=%s", TERMINFO);
-    putenv(buff);
-    owl_function_debugmsg("startup: setting TERMINFO to %s", TERMINFO);
+    owl_function_debugmsg("startup: Not setting TERMINFO");
   } else {
     owl_function_debugmsg("startup: leaving TERMINFO as %s from envrionment", getenv("TERMINFO"));
@@ -195,5 +211,6 @@
   /* owl global init */
   owl_global_init(&g);
-    if (debug) owl_global_set_debug_on(&g);
+  if (debug) owl_global_set_debug_on(&g);
+  if (confdir) owl_global_set_confdir(&g, confdir);
   owl_function_debugmsg("startup: first available debugging message");
   owl_global_set_startupargs(&g, argcsave, argvsave);
@@ -217,7 +234,6 @@
   /* create the owl directory, in case it does not exist */
   owl_function_debugmsg("startup: creating owl directory, if not present");
-  dir=owl_sprintf("%s/%s", owl_global_get_homedir(&g), OWL_CONFIG_DIR);
+  dir=owl_global_get_confdir(&g);
   mkdir(dir, S_IRWXU);
-  owl_free(dir);
 
   /* set the tty, either from the command line, or by figuring it out */
@@ -263,5 +279,7 @@
   owl_function_debugmsg("startup: creating default filters");
   f=owl_malloc(sizeof(owl_filter));
-  owl_filter_init_fromstring(f, "personal", "isprivate ^true$");
+  owl_filter_init_fromstring(f, "personal", "isprivate ^true$ and ( not type ^zephyr$"
+                             " or ( class ^message and"
+                             " ( instance ^personal$ or instance ^urgent$ ) ) )");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
@@ -533,5 +551,5 @@
     j=wgetch(typwin);
     if (j==ERR) {
-      usleep(10);
+      usleep(10000);
     } else {
       owl_global_update_lastinputtime(&g);
@@ -700,12 +718,13 @@
 void usage()
 {
-  fprintf(stderr, "Owl version %s\n", OWL_VERSION_STRING);
-  fprintf(stderr, "Usage: owl [-n] [-d] [-D] [-v] [-h] [-c <configfile>] [-t <ttyname>]\n");
+  fprintf(stderr, "Barnowl version %s\n", OWL_VERSION_STRING);
+  fprintf(stderr, "Usage: barnowl [-n] [-d] [-D] [-v] [-h] [-c <configfile>] [-s <confdir>] [-t <ttyname>]\n");
   fprintf(stderr, "  -n      don't load zephyr subscriptions\n");
   fprintf(stderr, "  -d      enable debugging\n");
   fprintf(stderr, "  -D      enable debugging and delete previous debug file\n");
-  fprintf(stderr, "  -v      print the Owl version number and exit\n");
+  fprintf(stderr, "  -v      print the Barnowl version number and exit\n");
   fprintf(stderr, "  -h      print this help message\n");
   fprintf(stderr, "  -c      specify an alternate config file\n");
+  fprintf(stderr, "  -s      specify an alternate config dir (default ~/.owl)\n");
   fprintf(stderr, "  -t      set the tty name\n");
 }
Index: owl.h
===================================================================
--- owl.h	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ owl.h	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -64,5 +64,8 @@
 #ifdef OWL_PERL
 typedef void WINDOW;
+/* logout is defined in FreeBSD. */
+#define logout logout_
 #include <perl.h>
+#undef logout
 #include "XSUB.h"
 #else
@@ -560,4 +563,6 @@
   char *thishost;
   char *homedir;
+  char *confdir;
+  char *startupfile;
   int direction;
   int zaway;
Index: perl/lib/BarnOwl/ModuleLoader.pm
===================================================================
--- perl/lib/BarnOwl/ModuleLoader.pm	(revision 9de39410327b85335dda6876d4767fbc426ae041)
+++ perl/lib/BarnOwl/ModuleLoader.pm	(revision be98ba53c4d3756545118a8c0454a06f2ea3c0e1)
@@ -6,12 +6,15 @@
 use lib (BarnOwl::get_data_dir() . "/modules/");
 use PAR (BarnOwl::get_data_dir() . "/modules/*.par");
-use PAR ($ENV{HOME} . "/.owl/modules/*.par");
+use PAR (BarnOwl::get_config_dir() . "/modules/*.par");
 
 sub load_all {
     my %modules;
     my @modules;
+
+    my @moddirs = ();
+    push @moddirs, BarnOwl::get_data_dir() . "/modules";
+    push @moddirs, BarnOwl::get_config_dir() . "/modules";
     
-    for my $dir ( BarnOwl::get_data_dir() . "/modules",
-                  $ENV{HOME} . "/.owl/modules" ) {
+    for my $dir (@moddirs) {
         opendir(my $dh, $dir) or next;
         while(defined(my $f = readdir($dh))) {
Index: perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm
===================================================================
--- perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm	(revision f032974dd42063d8ccfd55bb796907b611f4ad97)
+++ perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm	(revision 892568bf6e3ceea8724cef719078e5f6c2455b16)
@@ -581,4 +581,6 @@
       or die("Usage: jmuc join MUC [-p password] [-a account]");
 
+    die("Error: Must specify a fully-qualified MUC name (e.g. barnowl\@conference.mit.edu)\n")
+        unless $muc =~ /@/;
     $muc = Net::Jabber::JID->new($muc);
     $jid = Net::Jabber::JID->new($jid);
@@ -586,8 +588,8 @@
 
     $conn->getConnectionFromJID($jid)->MUCJoin(JID      => $muc,
-                                                  Password => $password,
-                                                  History  => {
-                                                      MaxChars => 0
-                                                     });
+                                               Password => $password,
+                                               History  => {
+                                                   MaxChars => 0
+                                                  });
     return;
 }
@@ -599,6 +601,9 @@
     die("Usage: jmuc part MUC [-a account]") unless $muc;
 
-    $conn->getConnectionFromJID($jid)->MUCLeave(JID => $muc);
-    queue_admin_msg("$jid has left $muc.");
+    if($conn->getConnectionFromJID($jid)->MUCLeave(JID => $muc)) {
+        queue_admin_msg("$jid has left $muc.");
+    } else {
+        die("Error: Not joined to $muc");
+    }
 }
 
@@ -639,6 +644,23 @@
     my $m = shift;
     my @jids = $m->Presence();
-    return "JIDs present in " . $m->BaseJID . "\n\t"
-      . join("\n\t", map {$_->GetResource}@jids) . "\n";
+
+    my $presence = "JIDs present in " . $m->BaseJID;
+    if($m->Anonymous) {
+        $presence .= " [anonymous MUC]";
+    }
+    $presence .= "\n\t";
+    $presence .= join("\n\t", map {pp_jid($m, $_);} @jids) . "\n";
+    return $presence;
+}
+
+sub pp_jid {
+    my ($m, $jid) = @_;
+    my $nick = $jid->GetResource;
+    my $full = $m->GetFullJID($jid);
+    if($full && $full ne $nick) {
+        return "$nick ($full)";
+    } else {
+        return "$nick";
+    }
 }
 
@@ -904,4 +926,5 @@
                               sid => $sid } );
     $jhash{type} = 'admin';
+    
     BarnOwl::queue_message( BarnOwl::Message->new(%jhash) );
 }
@@ -1134,12 +1157,12 @@
     }
     elsif ( $jtype eq 'normal' ) {
-        $props{replycmd}  = undef;
+        $props{replycmd}  = "";
         $props{private} = 1;
     }
     elsif ( $jtype eq 'headline' ) {
-        $props{replycmd} = undef;
+        $props{replycmd} = "";
     }
     elsif ( $jtype eq 'error' ) {
-        $props{replycmd} = undef;
+        $props{replycmd} = "";
         $props{body}     = "Error "
           . $props{error_code}
Index: perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm
===================================================================
--- perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm	(revision 3c455b40331c014fd3d113629a3fd670bb6ffd4f)
+++ perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm	(revision 892568bf6e3ceea8724cef719078e5f6c2455b16)
@@ -52,4 +52,7 @@
 Leave a MUC. The MUC is specified in the same form as L</FindMUC>
 
+Returns true if successful, false if this connection was not in the
+named MUC.
+
 =cut
 
@@ -61,4 +64,5 @@
     $muc->Leave();
     $self->{_BARNOWL_MUCS} = [grep {$_->BaseJID ne $muc->BaseJID} $self->MUCs];
+    return 1;
 }
 
Index: perl/modules/Jabber/lib/Net/Jabber/MUC.pm
===================================================================
--- perl/modules/Jabber/lib/Net/Jabber/MUC.pm	(revision c2bed5539d456612d69de33e1dacc3afe5f70395)
+++ perl/modules/Jabber/lib/Net/Jabber/MUC.pm	(revision 892568bf6e3ceea8724cef719078e5f6c2455b16)
@@ -64,4 +64,5 @@
     $self->{JID} = $args{jid};
     $self->{PRESENCE} = { };
+    $self->{ANONYMOUS} = 1;
 
     bless($self, $class);
@@ -188,5 +189,13 @@
         delete $self->{PRESENCE}->{$from->GetJID('full')};
     } elsif($type eq 'available') {
-        $self->{PRESENCE}->{$from->GetJID('full')} = $from;
+        $self->{PRESENCE}->{$from->GetJID('full')} = {ROOMNICK => $from};
+        my $x = $presence->GetX('http://jabber.org/protocol/muc#user');
+        if($x && $x->DefinedItem()) {
+            my $item = $x->GetItem();
+            if($item->DefinedJID()) {
+                $self->{PRESENCE}->{$from->GetJID('full')}->{FULLJID} = $item->GetJID();
+                $self->{ANONYMOUS} = 0;
+            }
+        }
     }
 }
@@ -207,4 +216,22 @@
 }
 
+=head2 GetFullJID roomjid
+
+Given the roomnick of a user in the MUC, return their full NIC if the
+MUC makes it available. If the MUC is anonymous or the user does not
+exist in the MUC, return undef.
+
+=cut
+
+sub GetFullJID {
+    my $self = shift;
+    my $jid = shift;
+
+    $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::Jabber::JID');
+    my $pres = $self->{PRESENCE}->{$jid};
+    return unless $pres;
+    return $pres->{FULLJID};
+}
+
 =head2 Presence
 
@@ -215,5 +242,16 @@
 sub Presence {
     my $self = shift;
-    return values %{$self->{PRESENCE}};
+    return map {$_->{ROOMNICK}} values %{$self->{PRESENCE}};
+}
+
+=head2 Anonymous
+
+Returns true if the MUC is anonymous (hides participants real JIDs)
+
+=cut
+
+sub Anonymous {
+    my $self = shift;
+    return $self->{ANONYMOUS};
 }
 
Index: perl/modules/Jabber/lib/XML/Stream.pm
===================================================================
--- perl/modules/Jabber/lib/XML/Stream.pm	(revision c2bed5539d456612d69de33e1dacc3afe5f70395)
+++ perl/modules/Jabber/lib/XML/Stream.pm	(revision 5073972cb617a0a04e54650031f94c47059c66fb)
@@ -1161,5 +1161,6 @@
     }
 
-    delete($self->{SIDS}->{$currsid});
+    # 08.04.05(Fri) slipstream@yandex.ru for compapility with ejabberd since it reuses stream id
+    delete($self->{SIDS}->{$currsid}) unless ($currsid eq $sid);
 
     if (exists($self->GetRoot($sid)->{version}) &&
Index: perlconfig.c
===================================================================
--- perlconfig.c	(revision f6b319cca5234c8b6dbdb43812ec2bb9483a6f26)
+++ perlconfig.c	(revision ad15610ead2550219224b67ce4c2d7da2819e4df)
@@ -137,4 +137,5 @@
   char *key,*val;
   HV * hash;
+  struct tm tm;
 
   hash = (HV*)SvRV(msg);
@@ -162,5 +163,4 @@
     } else if (!strcmp(key, "time")) {
       m->timestr = owl_strdup(val);
-      struct tm tm;
       strptime(val, "%a %b %d %T %Y", &tm);
       m->time = mktime(&tm);
@@ -445,4 +445,5 @@
   int i, count;
   char * ret = NULL;
+  SV *rv;
   STRLEN n_a;
   dSP;
@@ -467,5 +468,5 @@
     if(count != 1)
       croak("Perl command %s returned more than one value!", cmd->name);
-    SV * rv = POPs;
+    rv = POPs;
     if(SvTRUE(rv)) {
       ret = owl_strdup(SvPV(rv, n_a));
@@ -488,9 +489,9 @@
   SV *cb = (SV*)(e->cbdata);
   unsigned int n_a;
+  dSP;
+
   if(cb == NULL) {
     owl_function_error("Perl callback is NULL!");
   }
-
-  dSP;
 
   ENTER;
@@ -516,7 +517,7 @@
 void owl_perlconfig_mainloop()
 {
+  dSP;
   if (!owl_perlconfig_is_function("BarnOwl::Hooks::_mainloop_hook"))
     return;
-  dSP ;
   PUSHMARK(SP) ;
   call_pv("BarnOwl::Hooks::_mainloop_hook", G_DISCARD|G_EVAL);
Index: perlglue.xs
===================================================================
--- perlglue.xs	(revision 13a3c1db689b9429147996774625ca630c1b93cd)
+++ perlglue.xs	(revision b363d83e853174043a0471ddd8a28a4ef226df02)
@@ -199,7 +199,14 @@
 get_data_dir ()
 	CODE:
-		RETVAL = (char *) DATADIR;
+		RETVAL = (char *) owl_get_datadir();
 	OUTPUT:
 	RETVAL
+
+char * 
+get_config_dir ()
+	CODE:
+		RETVAL = (char *) owl_global_get_confdir(&g);
+	OUTPUT:
+	RETVAL	
 
 void
Index: perlwrap.pm
===================================================================
--- perlwrap.pm	(revision 42947f16c4f03f417502aeec42eaba54efd3d584)
+++ perlwrap.pm	(revision 18fb3d4f9f671a8ee3e93d7782a301238c6df61d)
@@ -21,7 +21,9 @@
 };
 
-use lib(get_data_dir()."/lib");
-use lib($ENV{HOME}."/.owl/lib");
-
+use lib(get_data_dir() . "/lib");
+use lib(get_config_dir() . "/lib");
+
+# perlconfig.c will set this to the value of the -c command-line
+# switch, if present.
 our $configfile;
 
@@ -520,5 +522,5 @@
     if ( $m->is_loginout) {
         return format_login($m);
-    } elsif($m->is_ping) {
+    } elsif($m->is_ping && $m->is_personal) {
         return ( "\@b(PING) from \@b(" . $m->pretty_sender . ")\n" );
     } elsif($m->is_admin) {
@@ -568,4 +570,7 @@
     }
 
+    if($m->opcode) {
+        $header .= " [" . $m->opcode . "]";
+    }
     $header .= "  " . time_hhmm($m);
     my $sender = $m->long_sender;
Index: t/00-core-tests.t
===================================================================
--- t/00-core-tests.t	(revision 1cf3f8d3cf08ed3fb38d1c83459a1db140cb0d17)
+++ t/00-core-tests.t	(revision 1cf3f8d3cf08ed3fb38d1c83459a1db140cb0d17)
@@ -0,0 +1,3 @@
+#!/usr/bin/env perl
+use File::Basename;
+system(dirname($0) . "/../tester");
Index: test.h
===================================================================
--- test.h	(revision 0138478b33d7650c789c4c6e40eec517dc455795)
+++ test.h	(revision 1cf3f8d3cf08ed3fb38d1c83459a1db140cb0d17)
@@ -3,5 +3,5 @@
 
 #define FAIL_UNLESS(desc,pred) do { int __pred = (pred);                \
-    printf("\t%-4s: %s", (__pred)?"ok":(numfailed++,"FAIL"), desc);     \
+    printf("%s %s", (__pred)?"ok":(numfailed++,"not ok"), desc);     \
     if(!(__pred)) printf("\t(%s:%d)", __FILE__, __LINE__); printf("%c", '\n'); } while(0)
 
Index: tester.c
===================================================================
--- tester.c	(revision e7dc035f778ce42e3fecd0f0da74f30a22fa458c)
+++ tester.c	(revision 1cf3f8d3cf08ed3fb38d1c83459a1db140cb0d17)
@@ -143,4 +143,10 @@
 
 
+#define OWL_DICT_NTESTS  20
+#define OWL_UTIL_NTESTS  9
+#define OWL_OBARRAY_NTESTS  5
+#define OWL_VARIABLE_NTESTS  52
+#define OWL_FILTER_NTESTS  23
+
 int main(int argc, char **argv, char **env)
 {
@@ -149,5 +155,7 @@
 
   int numfailures=0;
-  if (argc==2 && 0==strcmp(argv[1],"reg")) {
+  if (argc==1 || (argc==2 && 0==strcmp(argv[1],"reg"))) {
+    printf("1..%d\n", OWL_UTIL_NTESTS+OWL_DICT_NTESTS+OWL_VARIABLE_NTESTS
+           +OWL_FILTER_NTESTS+OWL_OBARRAY_NTESTS);
     numfailures += owl_util_regtest();
     numfailures += owl_dict_regtest();
@@ -156,5 +164,5 @@
     numfailures += owl_obarray_regtest();
     if (numfailures) {
-      fprintf(stderr, "*** WARNING: %d failures total\n", numfailures);
+      fprintf(stderr, "# *** WARNING: %d failures total\n", numfailures);
     }
     return(numfailures);
Index: util.c
===================================================================
--- util.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ util.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -759,5 +759,4 @@
 char * owl_util_baseclass(char * class)
 {
-  char *ret;
   char *start, *end;
 
@@ -769,5 +768,5 @@
   start = owl_strdup(start);
   end = start + strlen(start) - 1;
-  while(*end == 'd' && *(end-1) == '.') {
+  while(end > start && *end == 'd' && *(end-1) == '.') {
     end -= 2;
   }
@@ -789,5 +788,5 @@
   int numfailed=0;
 
-  printf("BEGIN testing owl_util\n");
+  printf("# BEGIN testing owl_util\n");
 
   FAIL_UNLESS("owl_util_substitute 1",
@@ -812,6 +811,6 @@
 	      !strcmp("meep foo bar", owl_util_uniq("meep foo", "bar foo meep", "-")));
 
-  if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
-  printf("END testing owl_util (%d failures)\n", numfailed);
+  // if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
+  printf("# END testing owl_util (%d failures)\n", numfailed);
   return(numfailed);
 }
Index: variable.c
===================================================================
--- variable.c	(revision a695a687a2b27f1b4164d054121186f9bb1b0b6c)
+++ variable.c	(revision ad15610ead2550219224b67ce4c2d7da2819e4df)
@@ -974,8 +974,9 @@
   int numfailed=0;
   char buf[1024];
+  owl_variable * v;
 
   in_regtest = 1;
 
-  printf("BEGIN testing owl_variable\n");
+  printf("# BEGIN testing owl_variable\n");
   FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
 
@@ -1027,6 +1028,4 @@
   FAIL_UNLESS("get enum 10", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
 
-  owl_variable * v;
-  
   owl_variable_dict_newvar_string(&vd, "stringvar", "", "", "testval");
   FAIL_UNLESS("get new string var", NULL != (v = owl_variable_get(&vd, "stringvar", OWL_VARIABLE_STRING)));
@@ -1049,6 +1048,6 @@
   owl_variable_dict_free(&vd);
 
-  if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n");
-  printf("END testing owl_variable (%d failures)\n", numfailed);
+  // if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n");
+  printf("# END testing owl_variable (%d failures)\n", numfailed);
   return(numfailed);
 }
Index: zephyr.c
===================================================================
--- zephyr.c	(revision 13a3c1db689b9429147996774625ca630c1b93cd)
+++ zephyr.c	(revision 50e29e35c64d64e223d378d350a7bc4f038d78f5)
@@ -328,4 +328,8 @@
   char *out;
 
+  /* If there's no message here, just run along now */
+  if (n->z_message_len == 0)
+    return(owl_strdup(""));
+
   count=save=0;
   for (i=0; i<n->z_message_len; i++) {
@@ -362,4 +366,7 @@
 {
   int i, fields;
+
+  if(n->z_message_len == 0)
+    return 0;
 
   fields=1;
Index: zwrite.c
===================================================================
--- zwrite.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ zwrite.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
@@ -125,4 +125,11 @@
   }
 
+  if (z->class == NULL &&
+      z->inst == NULL &&
+      owl_list_get_size(&(z->recips))==0) {
+    owl_function_error("You must specify a recipient for zwrite");
+    return(-1);
+  }
+
   /* now deal with defaults */
   if (z->class==NULL) z->class=owl_strdup("message");
@@ -132,11 +139,4 @@
   /* z->message is allowed to stay NULL */
   
-  if (!strcasecmp(z->class, "message") &&
-      !strcasecmp(z->inst, "personal") &&
-      owl_list_get_size(&(z->recips))==0) {
-    owl_function_error("You must specify a recipient for zwrite");
-    return(-1);
-  }
-
   /* get a zsig, if not given */
   if (z->zsig==NULL) {
