Index: logging.c
===================================================================
--- logging.c	(revision 7865479440dd042766ecbbc1119b45e5eb7cd6a6)
+++ logging.c	(revision cc305b53e93deb26ad26d3eb1beaf34d53c0d6ac)
@@ -4,4 +4,14 @@
 #include <ctype.h>
 #include <sys/param.h>
+
+typedef struct _owl_log_entry { /* noproto */
+  char *filename;
+  char *message;
+} owl_log_entry;
+
+
+static GMainContext *log_context;
+static GMainLoop *log_loop;
+static GThread *logging_thread;
 
 /* This is now the one function that should be called to log a
@@ -70,56 +80,127 @@
 }
 
-void owl_log_zephyr(const owl_message *m, FILE *file) {
-    char *tmp;
-    tmp=short_zuser(owl_message_get_sender(m));
-    fprintf(file, "Class: %s Instance: %s", owl_message_get_class(m), owl_message_get_instance(m));
-    if (strcmp(owl_message_get_opcode(m), "")) fprintf(file, " Opcode: %s", owl_message_get_opcode(m));
-    fprintf(file, "\n");
-    fprintf(file, "Time: %s Host: %s\n", owl_message_get_timestr(m), owl_message_get_hostname(m));
-    fprintf(file, "From: %s <%s>\n\n", owl_message_get_zsig(m), tmp);
-    fprintf(file, "%s\n\n", owl_message_get_body(m));
+char *owl_log_zephyr(const owl_message *m) {
+    char *tmp = NULL;
+    GString *buffer = NULL;
+    buffer = g_string_new("");
+    tmp = short_zuser(owl_message_get_sender(m));
+    g_string_append_printf(buffer, "Class: %s Instance: %s", 
+                           owl_message_get_class(m), 
+                           owl_message_get_instance(m));
+    if (strcmp(owl_message_get_opcode(m), "")) {
+      g_string_append_printf(buffer, " Opcode: %s", 
+                             owl_message_get_opcode(m));
+    }
+    g_string_append_printf(buffer, "\n");
+    g_string_append_printf(buffer, "Time: %s Host: %s\n", 
+                           owl_message_get_timestr(m), 
+                           owl_message_get_hostname(m));
+    g_string_append_printf(buffer, "From: %s <%s>\n\n", 
+                           owl_message_get_zsig(m), tmp);
+    g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
     g_free(tmp);
-}
-
-void owl_log_aim(const owl_message *m, FILE *file) {
-    fprintf(file, "From: <%s> To: <%s>\n", owl_message_get_sender(m), owl_message_get_recipient(m));
-    fprintf(file, "Time: %s\n\n", owl_message_get_timestr(m));
-    if (owl_message_is_login(m))
-        fprintf(file, "LOGIN\n\n");
-    else if (owl_message_is_logout(m))
-        fprintf(file, "LOGOUT\n\n");
-    else
-        fprintf(file, "%s\n\n", owl_message_get_body(m));
-}
-
-void owl_log_jabber(const owl_message *m, FILE *file) {
-    fprintf(file, "From: <%s> To: <%s>\n",owl_message_get_sender(m), owl_message_get_recipient(m));
-    fprintf(file, "Time: %s\n\n", owl_message_get_timestr(m));
-    fprintf(file, "%s\n\n",owl_message_get_body(m));
-}
-
-void owl_log_generic(const owl_message *m, FILE *file) {
-    fprintf(file, "From: <%s> To: <%s>\n", owl_message_get_sender(m), owl_message_get_recipient(m));
-    fprintf(file, "Time: %s\n\n", owl_message_get_timestr(m));
-    fprintf(file, "%s\n\n", owl_message_get_body(m));
+    return g_string_free(buffer, FALSE);
+}
+
+char *owl_log_aim(const owl_message *m) {
+    GString *buffer = NULL;
+    buffer = g_string_new("");
+    g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 
+                           owl_message_get_sender(m), owl_message_get_recipient(m));
+    g_string_append_printf(buffer, "Time: %s\n\n", 
+                           owl_message_get_timestr(m));
+    if (owl_message_is_login(m)) {
+        g_string_append_printf(buffer, "LOGIN\n\n");
+    } else if (owl_message_is_logout(m)) {
+        g_string_append_printf(buffer, "LOGOUT\n\n");
+    } else {
+        g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
+    }
+    return g_string_free(buffer, FALSE);
+}
+
+char *owl_log_jabber(const owl_message *m) {
+    GString *buffer = NULL;
+    buffer = g_string_new("");
+    g_string_append_printf(buffer, "From: <%s> To: <%s>\n",
+                           owl_message_get_sender(m), 
+                           owl_message_get_recipient(m));
+    g_string_append_printf(buffer, "Time: %s\n\n", 
+                           owl_message_get_timestr(m));
+    g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
+    return g_string_free(buffer, FALSE);
+}
+
+char *owl_log_generic(const owl_message *m) {
+    GString *buffer;
+    buffer = g_string_new("");
+    g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 
+                           owl_message_get_sender(m), 
+                           owl_message_get_recipient(m));
+    g_string_append_printf(buffer, "Time: %s\n\n", 
+                           owl_message_get_timestr(m));
+    g_string_append_printf(buffer, "%s\n\n", 
+                           owl_message_get_body(m));
+    return g_string_free(buffer, FALSE);
+}
+
+static void owl_log_error_main_thread(gpointer data)
+{
+  owl_function_error("%s", (const char*)data);
+}
+
+static void owl_log_error(const char *message)
+{
+  char *data = g_strdup(message);
+  owl_select_post_task(owl_log_error_main_thread,
+		       data, g_free, g_main_context_default());
+}
+
+static void owl_log_write_entry(gpointer data)
+{
+  owl_log_entry *msg = (owl_log_entry*)data;
+  FILE *file = NULL;
+  file = fopen(msg->filename, "a");
+  if (!file) {
+    owl_log_error("Unable to open file for logging");
+    return;
+  }
+  fprintf(file, "%s", msg->message);
+  fclose(file);
+}
+
+static void owl_log_entry_free(void *data)
+{
+  owl_log_entry *msg = (owl_log_entry*)data;
+  if (msg) {
+    g_free(msg->message);
+    g_free(msg->filename);
+    g_free(msg);
+  }
+}
+
+void owl_log_enqueue_message(const char *buffer, const char *filename)
+{
+  owl_log_entry *log_msg = NULL; 
+  log_msg = g_new(owl_log_entry,1);
+  log_msg->message = g_strdup(buffer);
+  log_msg->filename = g_strdup(filename);
+  owl_select_post_task(owl_log_write_entry, log_msg, 
+		       owl_log_entry_free, log_context);
 }
 
 void owl_log_append(const owl_message *m, const char *filename) {
-    FILE *file;
-    file=fopen(filename, "a");
-    if (!file) {
-        owl_function_error("Unable to open file for logging");
-        return;
-    }
-    if (owl_message_is_type_zephyr(m)) {
-        owl_log_zephyr(m, file);
-    } else if (owl_message_is_type_jabber(m)) {
-        owl_log_jabber(m, file);
-    } else if (owl_message_is_type_aim(m)) {
-        owl_log_aim(m, file);
-    } else {
-        owl_log_generic(m, file);
-    }
-    fclose(file);
+  char *buffer = NULL;
+  if (owl_message_is_type_zephyr(m)) {
+    buffer = owl_log_zephyr(m);
+  } else if (owl_message_is_type_jabber(m)) {
+    buffer = owl_log_jabber(m);
+  } else if (owl_message_is_type_aim(m)) {
+    buffer = owl_log_aim(m);
+  } else {
+    buffer = owl_log_generic(m);
+  }
+  owl_log_enqueue_message(buffer, filename);
+  g_free(buffer);
 }
 
@@ -177,9 +258,8 @@
 void owl_log_outgoing_zephyr_error(const owl_zwrite *zw, const char *text)
 {
-  FILE *file;
   char *filename, *logpath;
   char *tobuff, *recip;
   owl_message *m;
-
+  GString *msgbuf;
   /* create a present message so we can pass it to
    * owl_log_shouldlog_message(void)
@@ -201,34 +281,22 @@
   /* expand ~ in path names */
   logpath = owl_util_makepath(owl_global_get_logpath(&g));
-
   filename = g_strdup_printf("%s/%s", logpath, tobuff);
-  file=fopen(filename, "a");
-  g_free(filename);
-  if (!file) {
-    owl_function_error("Unable to open file for outgoing logging");
-    g_free(logpath);
-    g_free(tobuff);
-    return;
-  }
-  fprintf(file, "ERROR (owl): %s\n%s\n", tobuff, text);
-  if (text[strlen(text)-1]!='\n') {
-    fprintf(file, "\n");
-  }
-  fclose(file);
+  msgbuf = g_string_new("");
+  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
+  if (text[strlen(text)-1] != '\n') {
+    g_string_append_printf(msgbuf, "\n");
+  }
+  owl_log_enqueue_message(msgbuf->str, filename);
+  g_string_free(msgbuf, TRUE);
 
   filename = g_strdup_printf("%s/all", logpath);
   g_free(logpath);
-  file=fopen(filename, "a");
-  g_free(filename);
-  if (!file) {
-    owl_function_error("Unable to open file for outgoing logging");
-    g_free(tobuff);
-    return;
-  }
-  fprintf(file, "ERROR (owl): %s\n%s\n", tobuff, text);
-  if (text[strlen(text)-1]!='\n') {
-    fprintf(file, "\n");
-  }
-  fclose(file);
+  msgbuf = g_string_new("");
+  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
+  if (text[strlen(text)-1] != '\n') {
+    g_string_append_printf(msgbuf, "\n");
+  }
+  owl_log_enqueue_message(msgbuf->str, filename);
+  g_string_free(msgbuf, TRUE);
 
   g_free(tobuff);
@@ -284,7 +352,9 @@
   } else if (owl_message_is_type_jabber(m)) {
     if (personal) {
-      from=frombuff=g_strdup_printf("jabber:%s",owl_message_get_sender(m));
-    } else {
-      from=frombuff=g_strdup_printf("jabber:%s",owl_message_get_recipient(m));
+      from=frombuff=g_strdup_printf("jabber:%s", 
+				    owl_message_get_sender(m));
+    } else {
+      from=frombuff=g_strdup_printf("jabber:%s", 
+				    owl_message_get_recipient(m));
     }
   } else {
@@ -355,2 +425,38 @@
   g_free(logpath);
 }
+
+static gpointer owl_log_thread_func(gpointer data)
+{
+  log_context = g_main_context_new();
+  log_loop = g_main_loop_new(log_context, FALSE);
+  g_main_loop_run(log_loop);
+  return NULL;
+}
+
+void owl_log_init(void) 
+{
+  GError *error = NULL;
+  logging_thread = g_thread_create(owl_log_thread_func,
+                                   NULL,
+                                   TRUE,
+                                   &error);
+  if (error) {
+    endwin();
+    fprintf(stderr, "Error spawning logging thread: %s\n", error->message);
+    fflush(stderr);
+    exit(1);
+  }
+  
+}
+
+static void owl_log_quit_func(gpointer data)
+{
+  g_main_loop_quit(log_loop);
+}
+
+void owl_log_shutdown(void)
+{
+  owl_select_post_task(owl_log_quit_func, NULL,
+		       NULL, log_context);
+  g_thread_join(logging_thread);
+}
Index: owl.c
===================================================================
--- owl.c	(revision 44976fe18ba06c48eaf310eff343ffa7d44379ad)
+++ owl.c	(revision cc305b53e93deb26ad26d3eb1beaf34d53c0d6ac)
@@ -611,4 +611,6 @@
   g_source_unref(source);
 
+  owl_log_init();
+
   owl_function_debugmsg("startup: entering main loop");
   owl_select_run_loop();
@@ -618,4 +620,5 @@
   owl_signal_shutdown();
   owl_shutdown_curses();
+  owl_log_shutdown();
   return 0;
 }
