source: logging.c @ ca52fe9

Last change on this file since ca52fe9 was 8a06468, checked in by Jason Gross <jasongross9@gmail.com>, 7 years ago
Clarify a comment about deferred logging mode As per https://github.com/barnowl/barnowl/pull/109#discussion_r131532293
  • Property mode set to 100644
File size: 19.8 KB
RevLine 
[7d4fbcd]1#include "owl.h"
[f271129]2#include <stdio.h>
[7d4fbcd]3
[cc305b5]4typedef struct _owl_log_entry { /* noproto */
5  char *filename;
6  char *message;
7} owl_log_entry;
8
[4511ac3]9typedef struct _owl_log_options { /* noproto */
10  bool drop_failed_logs;
11  bool display_initial_log_count;
12} owl_log_options;
[cc305b5]13
14static GMainContext *log_context;
15static GMainLoop *log_loop;
16static GThread *logging_thread;
[89e4294]17static bool defer_logs; /* to be accessed only on the disk-writing thread */
[ec36247]18static GQueue *deferred_entry_queue;
[cc305b5]19
[15b34fd]20/* This is now the one function that should be called to log a
21 * message.  It will do all the work necessary by calling the other
22 * functions in this file as necessary.
23 */
[c08c70a]24void owl_log_message(const owl_message *m) {
[15b34fd]25  owl_function_debugmsg("owl_log_message: entering");
26
[3c7d086a]27  if (m == NULL) {
28    owl_function_debugmsg("owl_log_message: passed null message");
29    return;
30  }
31
[15b34fd]32  /* should we be logging this message? */
33  if (!owl_log_shouldlog_message(m)) {
34    owl_function_debugmsg("owl_log_message: not logging message");
35    return;
36  }
37
38  /* handle incmoing messages */
39  if (owl_message_is_direction_in(m)) {
40    owl_log_incoming(m);
41    owl_function_debugmsg("owl_log_message: leaving");
42    return;
43  }
44
45  /* handle outgoing messages */
[42947f1]46  owl_log_outgoing(m);
47
[15b34fd]48  owl_function_debugmsg("owl_log_message: leaving");
49}
[7d4fbcd]50
[15b34fd]51/* Return 1 if we should log the given message, otherwise return 0 */
[c08c70a]52int owl_log_shouldlog_message(const owl_message *m) {
[4542047]53  const owl_filter *f;
[12c35df]54
[15b34fd]55  /* If there's a logfilter and this message matches it, log */
56  f=owl_global_get_filter(&g, owl_global_get_logfilter(&g));
57  if (f && owl_filter_message_match(f, m)) return(1);
[7d4fbcd]58
[15b34fd]59  /* otherwise we do things based on the logging variables */
60
61  /* skip login/logout messages if appropriate */
62  if (!owl_global_is_loglogins(&g) && owl_message_is_loginout(m)) return(0);
63     
64  /* check direction */
65  if ((owl_global_get_loggingdirection(&g)==OWL_LOGGING_DIRECTION_IN) && owl_message_is_direction_out(m)) {
66    return(0);
67  }
68  if ((owl_global_get_loggingdirection(&g)==OWL_LOGGING_DIRECTION_OUT) && owl_message_is_direction_in(m)) {
69    return(0);
70  }
71
72  if (owl_message_is_type_zephyr(m)) {
73    if (owl_message_is_personal(m) && !owl_global_is_logging(&g)) return(0);
74    if (!owl_message_is_personal(m) && !owl_global_is_classlogging(&g)) return(0);
75  } else {
76    if (owl_message_is_private(m) || owl_message_is_loginout(m)) {
77      if (!owl_global_is_logging(&g)) return(0);
78    } else {
79      if (!owl_global_is_classlogging(&g)) return(0);
80    }
[7d4fbcd]81  }
[15b34fd]82  return(1);
83}
84
[6829afc]85CALLER_OWN char *owl_log_zephyr(const owl_message *m)
[d427f08]86{
[cc305b5]87    char *tmp = NULL;
88    GString *buffer = NULL;
89    buffer = g_string_new("");
90    tmp = short_zuser(owl_message_get_sender(m));
91    g_string_append_printf(buffer, "Class: %s Instance: %s", 
92                           owl_message_get_class(m), 
93                           owl_message_get_instance(m));
94    if (strcmp(owl_message_get_opcode(m), "")) {
95      g_string_append_printf(buffer, " Opcode: %s", 
96                             owl_message_get_opcode(m));
97    }
98    g_string_append_printf(buffer, "\n");
99    g_string_append_printf(buffer, "Time: %s Host: %s\n", 
100                           owl_message_get_timestr(m), 
101                           owl_message_get_hostname(m));
102    g_string_append_printf(buffer, "From: %s <%s>\n\n", 
103                           owl_message_get_zsig(m), tmp);
104    g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
[ddbbcffa]105    g_free(tmp);
[cc305b5]106    return g_string_free(buffer, FALSE);
107}
108
[6829afc]109CALLER_OWN char *owl_log_aim(const owl_message *m)
[d427f08]110{
[cc305b5]111    GString *buffer = NULL;
112    buffer = g_string_new("");
113    g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 
114                           owl_message_get_sender(m), owl_message_get_recipient(m));
115    g_string_append_printf(buffer, "Time: %s\n\n", 
116                           owl_message_get_timestr(m));
117    if (owl_message_is_login(m)) {
118        g_string_append_printf(buffer, "LOGIN\n\n");
119    } else if (owl_message_is_logout(m)) {
120        g_string_append_printf(buffer, "LOGOUT\n\n");
121    } else {
122        g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
123    }
124    return g_string_free(buffer, FALSE);
125}
126
[6829afc]127CALLER_OWN char *owl_log_jabber(const owl_message *m)
[d427f08]128{
[cc305b5]129    GString *buffer = NULL;
130    buffer = g_string_new("");
131    g_string_append_printf(buffer, "From: <%s> To: <%s>\n",
132                           owl_message_get_sender(m), 
133                           owl_message_get_recipient(m));
134    g_string_append_printf(buffer, "Time: %s\n\n", 
135                           owl_message_get_timestr(m));
136    g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
137    return g_string_free(buffer, FALSE);
138}
139
[6829afc]140CALLER_OWN char *owl_log_generic(const owl_message *m)
[d427f08]141{
[cc305b5]142    GString *buffer;
143    buffer = g_string_new("");
144    g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 
145                           owl_message_get_sender(m), 
146                           owl_message_get_recipient(m));
147    g_string_append_printf(buffer, "Time: %s\n\n", 
148                           owl_message_get_timestr(m));
149    g_string_append_printf(buffer, "%s\n\n", 
150                           owl_message_get_body(m));
151    return g_string_free(buffer, FALSE);
152}
153
154static void owl_log_error_main_thread(gpointer data)
155{
156  owl_function_error("%s", (const char*)data);
[42947f1]157}
158
[edb14cc]159static void owl_log_adminmsg_main_thread(gpointer data)
160{
161  owl_function_adminmsg("Logging", (const char*)data);
162}
163
[565a43c]164static void owl_log_makemsg_main_thread(gpointer data)
165{
166  owl_function_makemsg((const char*)data);
167}
168
[e47e1b0]169static void G_GNUC_PRINTF(1, 2) owl_log_error(const char *fmt, ...)
[cc305b5]170{
[e47e1b0]171  va_list ap;
172  char *data;
173
174  va_start(ap, fmt);
175  data = g_strdup_vprintf(fmt, ap);
176  va_end(ap);
177
[cc305b5]178  owl_select_post_task(owl_log_error_main_thread,
[e47e1b0]179                       data, g_free, g_main_context_default());
[42947f1]180}
181
[edb14cc]182static void G_GNUC_PRINTF(1, 2) owl_log_adminmsg(const char *fmt, ...)
183{
184  va_list ap;
185  char *data;
186
187  va_start(ap, fmt);
188  data = g_strdup_vprintf(fmt, ap);
189  va_end(ap);
190
191  owl_select_post_task(owl_log_adminmsg_main_thread,
192                       data, g_free, g_main_context_default());
193}
194
[565a43c]195static void G_GNUC_PRINTF(1, 2) owl_log_makemsg(const char *fmt, ...)
196{
197  va_list ap;
198  char *data;
199
200  va_start(ap, fmt);
201  data = g_strdup_vprintf(fmt, ap);
202  va_end(ap);
203
204  owl_select_post_task(owl_log_makemsg_main_thread,
205                       data, g_free, g_main_context_default());
206}
207
[ec36247]208static CALLER_OWN owl_log_entry *owl_log_new_entry(const char *buffer, const char *filename)
209{
210  owl_log_entry *log_msg = g_slice_new(owl_log_entry);
211  log_msg->message = g_strdup(buffer);
212  log_msg->filename = g_strdup(filename);
213  return log_msg;
214}
215
216static void owl_log_deferred_enqueue_message(const char *buffer, const char *filename)
217{
218  g_queue_push_tail(deferred_entry_queue, owl_log_new_entry(buffer, filename));
219}
220
[874fd19]221static void owl_log_deferred_enqueue_first_message(const char *buffer, const char *filename)
222{
223  g_queue_push_head(deferred_entry_queue, owl_log_new_entry(buffer, filename));
224}
225
[ec36247]226/* write out the entry if possible
227 * return 0 on success, errno on failure to open
228 */
229static int owl_log_try_write_entry(owl_log_entry *msg)
[cc305b5]230{
231  FILE *file = NULL;
232  file = fopen(msg->filename, "a");
233  if (!file) {
[ec36247]234    return errno;
[cc305b5]235  }
236  fprintf(file, "%s", msg->message);
237  fclose(file);
[ec36247]238  return 0;
[42947f1]239}
240
[cc305b5]241static void owl_log_entry_free(void *data)
242{
243  owl_log_entry *msg = (owl_log_entry*)data;
244  if (msg) {
245    g_free(msg->message);
246    g_free(msg->filename);
[7dcef03]247    g_slice_free(owl_log_entry, msg);
[cc305b5]248  }
249}
250
[ec36247]251#if GLIB_CHECK_VERSION(2, 32, 0)
252#else
253static void owl_log_entry_free_gfunc(gpointer data, gpointer user_data)
254{
255  owl_log_entry_free(data);
256}
257#endif
258
[253f37f]259static void owl_log_file_error(owl_log_entry *msg, int errnum)
[77beb3c]260{
261  owl_log_error("Unable to open file for logging: %s (file %s)",
[253f37f]262                g_strerror(errnum),
[77beb3c]263                msg->filename);
264}
265
[ec36247]266/* If we are deferring log messages, enqueue this entry for writing.
267 * Otherwise, try to write this log message, and, if it fails with
[e6f21ea]268 * EPERM, EACCES, or ETIMEDOUT, go into deferred logging mode and
269 * queue an admin message.  If it fails with anything else, display an
[8a06468]270 * error message, drop the log message, and do not go into deferred
271 * logging mode.
[89e4294]272 *
273 * N.B. This function is called only on the disk-writing thread. */
[ec36247]274static void owl_log_eventually_write_entry(gpointer data)
275{
276  int ret;
277  owl_log_entry *msg = (owl_log_entry*)data;
278  if (defer_logs) {
279    owl_log_deferred_enqueue_message(msg->message, msg->filename);
280  } else {
281    ret = owl_log_try_write_entry(msg);
[e6f21ea]282    if (ret == EPERM || ret == EACCES || ret == ETIMEDOUT) {
[ec36247]283      defer_logs = true;
284      owl_log_error("Unable to open file for logging (%s): \n"
285                    "%s.  \n"
286                    "Consider renewing your tickets.  Logging has been \n"
287                    "suspended, and your messages will be saved.  To \n"
288                    "resume logging, use the command :flush-logs.\n\n",
289                    msg->filename,
290                    g_strerror(ret));
[874fd19]291      /* If we were not in deferred logging mode, either the queue should be
292       * empty, or we are attempting to log a message that we just popped off
293       * the head of the queue.  Either way, we should enqueue this message as
294       * the first message in the queue, rather than the last, so that we
295       * preserve message ordering. */
296      owl_log_deferred_enqueue_first_message(msg->message, msg->filename);
[ec36247]297    } else if (ret != 0) {
[77beb3c]298      owl_log_file_error(msg, ret);
[ec36247]299    }
300  }
301}
302
[89e4294]303/* tries to write the deferred log entries
304 *
305 * N.B. This function is called only on the disk-writing thread. */
[ec36247]306static void owl_log_write_deferred_entries(gpointer data)
307{
308  owl_log_entry *entry;
[4511ac3]309  owl_log_options *opts = (owl_log_options *)data;
[77beb3c]310  int ret;
[604303c]311  int logged_message_count = 0;
[edb14cc]312  bool all_succeeded = true;
[ec36247]313
[4511ac3]314  if (opts->display_initial_log_count) {
315    if (g_queue_is_empty(deferred_entry_queue)) {
316      owl_log_makemsg("There are no logs to flush.");
317    } else {
318      owl_log_makemsg("Attempting to flush %u logs...",
319                      g_queue_get_length(deferred_entry_queue));
320    }
[565a43c]321  }
322
[ec36247]323  defer_logs = false;
324  while (!g_queue_is_empty(deferred_entry_queue) && !defer_logs) {
[604303c]325    logged_message_count++;
[ec36247]326    entry = (owl_log_entry*)g_queue_pop_head(deferred_entry_queue);
[4511ac3]327    if (!opts->drop_failed_logs) {
[874fd19]328      /* Attempt to write the log entry.  If it fails, re-queue the entry at
329       * the head of the queue. */
[77beb3c]330      owl_log_eventually_write_entry(entry);
331    } else {
[874fd19]332      /* Attempt to write the log entry. If it fails, print an error message,
333       * drop the log, and keep going through the queue. */
[77beb3c]334      ret = owl_log_try_write_entry(entry);
335      if (ret != 0) {
[edb14cc]336        all_succeeded = false;
[77beb3c]337        owl_log_file_error(entry, ret);
338      }
339    }
[ec36247]340    owl_log_entry_free(entry);
341  }
[565a43c]342  if (logged_message_count > 0) {
[4511ac3]343    if (opts->display_initial_log_count) {
344      /* first clear the "attempting to flush" message from the status bar */
345      owl_log_makemsg("");
346    }
[565a43c]347    if (!defer_logs) {
348      if (all_succeeded) {
349        owl_log_adminmsg("Flushed %d logs and resumed logging.",
350                         logged_message_count);
351      } else {
352        owl_log_adminmsg("Flushed or dropped %d logs and resumed logging.",
353                         logged_message_count);
354      }
355    } else {
356      owl_log_error("Attempted to flush %d logs; %u deferred logs remain.",
357                    logged_message_count, g_queue_get_length(deferred_entry_queue));
358    }
[edb14cc]359  }
[ec36247]360}
361
[4511ac3]362void owl_log_flush_logs(bool drop_failed_logs, bool quiet)
[ec36247]363{
[4511ac3]364  owl_log_options *data = g_new(owl_log_options, 1);
365  data->drop_failed_logs = drop_failed_logs;
366  data->display_initial_log_count = !quiet;
[77beb3c]367
368  owl_select_post_task(owl_log_write_deferred_entries,
369                       data,
370                       g_free,
371                       log_context);
[ec36247]372}
373
[cc305b5]374void owl_log_enqueue_message(const char *buffer, const char *filename)
375{
[ec36247]376  owl_log_entry *log_msg = owl_log_new_entry(buffer, filename);
377  owl_select_post_task(owl_log_eventually_write_entry, log_msg,
[cc305b5]378                       owl_log_entry_free, log_context);
[42947f1]379}
380
[c08c70a]381void owl_log_append(const owl_message *m, const char *filename) {
[cc305b5]382  char *buffer = NULL;
383  if (owl_message_is_type_zephyr(m)) {
384    buffer = owl_log_zephyr(m);
385  } else if (owl_message_is_type_jabber(m)) {
386    buffer = owl_log_jabber(m);
387  } else if (owl_message_is_type_aim(m)) {
388    buffer = owl_log_aim(m);
389  } else {
390    buffer = owl_log_generic(m);
391  }
392  owl_log_enqueue_message(buffer, filename);
393  g_free(buffer);
[42947f1]394}
395
[c08c70a]396void owl_log_outgoing(const owl_message *m)
[15b34fd]397{
[e3a75ed]398  char *filename, *logpath;
[9c590d4]399  char *to, *temp;
[839697d]400  GList *cc;
[9c590d4]401
402  /* expand ~ in path names */
[60d7935]403  logpath = owl_util_makepath(owl_global_get_logpath(&g));
[15b34fd]404
[42947f1]405  /* Figure out what path to log to */
406  if (owl_message_is_type_zephyr(m)) {
[af1920fd]407    /* If this has CC's, do all but the "recipient" which we'll do below */
[839697d]408    cc = owl_message_get_cc_without_recipient(m);
409    while (cc != NULL) {
410      temp = short_zuser(cc->data);
[dde1b4d]411      filename = g_build_filename(logpath, temp, NULL);
[839697d]412      owl_log_append(m, filename);
413
[e3a75ed]414      g_free(filename);
[ddbbcffa]415      g_free(temp);
416      g_free(cc->data);
[839697d]417      cc = g_list_delete_link(cc, cc);
[9c590d4]418    }
[839697d]419
[9c590d4]420    to = short_zuser(owl_message_get_recipient(m));
[42947f1]421  } else if (owl_message_is_type_jabber(m)) {
[3472845]422    to = g_strdup_printf("jabber:%s", owl_message_get_recipient(m));
[7865479]423    g_strdelimit(to, "/", '_');
[42947f1]424  } else if (owl_message_is_type_aim(m)) {
[28ee32b]425    char *temp2;
[9c590d4]426    temp = owl_aim_normalize_screenname(owl_message_get_recipient(m));
[28ee32b]427    temp2 = g_utf8_strdown(temp,-1);
[3472845]428    to = g_strdup_printf("aim:%s", temp2);
[ddbbcffa]429    g_free(temp2);
430    g_free(temp);
[42947f1]431  } else {
[d4927a7]432    to = g_strdup("loopback");
[42947f1]433  }
[7d4fbcd]434
[dde1b4d]435  filename = g_build_filename(logpath, to, NULL);
[42947f1]436  owl_log_append(m, filename);
[ddbbcffa]437  g_free(to);
[e3a75ed]438  g_free(filename);
[7d4fbcd]439
[dde1b4d]440  filename = g_build_filename(logpath, "all", NULL);
[42947f1]441  owl_log_append(m, filename);
[ddbbcffa]442  g_free(logpath);
[e3a75ed]443  g_free(filename);
[7d4fbcd]444}
445
[42947f1]446
[24ccc01]447void owl_log_outgoing_zephyr_error(const owl_zwrite *zw, const char *text)
[2b86d14]448{
[e3a75ed]449  char *filename, *logpath;
[fe3b017]450  char *tobuff, *recip;
[180cd15]451  owl_message *m;
[cc305b5]452  GString *msgbuf;
[180cd15]453  /* create a present message so we can pass it to
[c79a047]454   * owl_log_shouldlog_message(void)
[180cd15]455   */
[7dcef03]456  m = g_slice_new(owl_message);
[e5da3fe]457  /* recip_index = 0 because there can only be one recipient anyway */
458  owl_message_create_from_zwrite(m, zw, text, 0);
[180cd15]459  if (!owl_log_shouldlog_message(m)) {
[91634ec]460    owl_message_delete(m);
[180cd15]461    return;
462  }
[91634ec]463  owl_message_delete(m);
[2b86d14]464
[180cd15]465  /* chop off a local realm */
[fe3b017]466  recip = owl_zwrite_get_recip_n_with_realm(zw, 0);
467  tobuff = short_zuser(recip);
468  g_free(recip);
[2b86d14]469
470  /* expand ~ in path names */
[60d7935]471  logpath = owl_util_makepath(owl_global_get_logpath(&g));
[dde1b4d]472  filename = g_build_filename(logpath, tobuff, NULL);
[cc305b5]473  msgbuf = g_string_new("");
474  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
475  if (text[strlen(text)-1] != '\n') {
476    g_string_append_printf(msgbuf, "\n");
[2b86d14]477  }
[cc305b5]478  owl_log_enqueue_message(msgbuf->str, filename);
479  g_string_free(msgbuf, TRUE);
[2b86d14]480
[dde1b4d]481  filename = g_build_filename(logpath, "all", NULL);
[ddbbcffa]482  g_free(logpath);
[cc305b5]483  msgbuf = g_string_new("");
484  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
485  if (text[strlen(text)-1] != '\n') {
486    g_string_append_printf(msgbuf, "\n");
[2b86d14]487  }
[cc305b5]488  owl_log_enqueue_message(msgbuf->str, filename);
489  g_string_free(msgbuf, TRUE);
[2b86d14]490
[ddbbcffa]491  g_free(tobuff);
[2b86d14]492}
493
[c08c70a]494void owl_log_incoming(const owl_message *m)
[15283bb]495{
[e3a75ed]496  char *filename, *allfilename, *logpath;
[e19eb97]497  const char *from=NULL;
[65b2173]498  char *frombuff=NULL;
[7d4fbcd]499  int len, ch, i, personal;
[12c35df]500
[15b34fd]501  /* figure out if it's a "personal" message or not */
[aac889a]502  if (owl_message_is_type_zephyr(m)) {
503    if (owl_message_is_personal(m)) {
[42947f1]504      personal = 1;
[aac889a]505    } else {
[42947f1]506      personal = 0;
[aac889a]507    }
[2182be3]508  } else if (owl_message_is_type_jabber(m)) {
[42947f1]509    /* This needs to be fixed to handle groupchat */
[e19eb97]510    const char* msgtype = owl_message_get_attribute_value(m,"jtype");
[42947f1]511    if (msgtype && !strcmp(msgtype,"groupchat")) {
512      personal = 0;
513    } else {
514      personal = 1;
515    }
[7d4fbcd]516  } else {
[79a0e82]517    if (owl_message_is_private(m) || owl_message_is_loginout(m)) {
[42947f1]518      personal = 1;
[aac889a]519    } else {
[42947f1]520      personal = 0;
[aac889a]521    }
[7d4fbcd]522  }
523
[2182be3]524
[aac889a]525  if (owl_message_is_type_zephyr(m)) {
526    if (personal) {
[3066d23]527      from=frombuff=short_zuser(owl_message_get_sender(m));
[aac889a]528    } else {
[d4927a7]529      from=frombuff=g_strdup(owl_message_get_class(m));
[7d4fbcd]530    }
[aac889a]531  } else if (owl_message_is_type_aim(m)) {
532    /* we do not yet handle chat rooms */
[28ee32b]533    char *normalto, *temp;
534    temp = owl_aim_normalize_screenname(owl_message_get_sender(m));
535    normalto = g_utf8_strdown(temp, -1);
[3472845]536    from=frombuff=g_strdup_printf("aim:%s", normalto);
[ddbbcffa]537    g_free(normalto);
538    g_free(temp);
[37eab7f]539  } else if (owl_message_is_type_loopback(m)) {
[d4927a7]540    from=frombuff=g_strdup("loopback");
[2182be3]541  } else if (owl_message_is_type_jabber(m)) {
[5c30091]542    if (personal) {
[cc305b5]543      from=frombuff=g_strdup_printf("jabber:%s", 
544                                    owl_message_get_sender(m));
[5c30091]545    } else {
[cc305b5]546      from=frombuff=g_strdup_printf("jabber:%s", 
547                                    owl_message_get_recipient(m));
[5c30091]548    }
[e6449bc]549  } else {
[d4927a7]550    from=frombuff=g_strdup("unknown");
[7d4fbcd]551  }
552 
553  /* check for malicious sender formats */
554  len=strlen(frombuff);
555  if (len<1 || len>35) from="weird";
556  if (strchr(frombuff, '/')) from="weird";
557
558  ch=frombuff[0];
[28ee32b]559  if (!g_ascii_isalnum(ch)) from="weird";
[7d4fbcd]560
561  for (i=0; i<len; i++) {
[e1c4636]562    if (frombuff[i]<'!' || frombuff[i]>='~') from="weird";
[7d4fbcd]563  }
564
565  if (!strcmp(frombuff, ".") || !strcasecmp(frombuff, "..")) from="weird";
566
567  if (!personal) {
[28ee32b]568    if (strcmp(from, "weird")) {
569      char* temp = g_utf8_strdown(frombuff, -1);
570      if (temp) {
[ddbbcffa]571        g_free(frombuff);
[28ee32b]572        from = frombuff = temp;
573      }
574    }
[7d4fbcd]575  }
576
[e1c4636]577  /* create the filename (expanding ~ in path names) */
[7d4fbcd]578  if (personal) {
[60d7935]579    logpath = owl_util_makepath(owl_global_get_logpath(&g));
[dde1b4d]580    filename = g_build_filename(logpath, from, NULL);
581    allfilename = g_build_filename(logpath, "all", NULL);
[d0961fe]582    owl_log_append(m, allfilename);
[e3a75ed]583    g_free(allfilename);
[7d4fbcd]584  } else {
[60d7935]585    logpath = owl_util_makepath(owl_global_get_classlogpath(&g));
[dde1b4d]586    filename = g_build_filename(logpath, from, NULL);
[7d4fbcd]587  }
[37eab7f]588
[42947f1]589  owl_log_append(m, filename);
[e3a75ed]590  g_free(filename);
[7d4fbcd]591
[d0961fe]592  if (personal && owl_message_is_type_zephyr(m)) {
[af1920fd]593    /* We want to log to all of the CC'd people who were not us, or
594     * the sender, as well.
595     */
[839697d]596    char *temp;
597    GList *cc;
[d0961fe]598    cc = owl_message_get_cc_without_recipient(m);
[839697d]599    while (cc != NULL) {
600      temp = short_zuser(cc->data);
601      if (strcasecmp(temp, frombuff) != 0) {
[dde1b4d]602        filename = g_build_filename(logpath, temp, NULL);
[839697d]603        owl_log_append(m, filename);
[e3a75ed]604        g_free(filename);
[d0961fe]605      }
[839697d]606
[ddbbcffa]607      g_free(temp);
608      g_free(cc->data);
[839697d]609      cc = g_list_delete_link(cc, cc);
[d0961fe]610    }
611  }
[7d4fbcd]612
[ddbbcffa]613  g_free(frombuff);
614  g_free(logpath);
[7d4fbcd]615}
[cc305b5]616
617static gpointer owl_log_thread_func(gpointer data)
618{
[ec36247]619  log_context = g_main_context_new();
[cc305b5]620  log_loop = g_main_loop_new(log_context, FALSE);
621  g_main_loop_run(log_loop);
622  return NULL;
623}
624
[ec36247]625void owl_log_init(void)
[cc305b5]626{
[0a9ffc5]627  log_context = g_main_context_new();
[0792d99]628#if GLIB_CHECK_VERSION(2, 31, 0)
629  logging_thread = g_thread_new("logging",
630                                owl_log_thread_func,
631                                NULL);
632#else
633  GError *error = NULL;
[cc305b5]634  logging_thread = g_thread_create(owl_log_thread_func,
635                                   NULL,
636                                   TRUE,
637                                   &error);
638  if (error) {
639    endwin();
640    fprintf(stderr, "Error spawning logging thread: %s\n", error->message);
641    fflush(stderr);
642    exit(1);
643  }
[0792d99]644#endif
[ec36247]645
646  deferred_entry_queue = g_queue_new();
[cc305b5]647}
648
649static void owl_log_quit_func(gpointer data)
650{
[ec36247]651  /* flush the deferred logs queue, trying to write the
[77beb3c]652   * entries to the disk one last time.  Drop any failed
[4511ac3]653   * entries, and be quiet about it. */
654  owl_log_options opts;
655  opts.drop_failed_logs = true;
656  opts.display_initial_log_count = false;
657  owl_log_write_deferred_entries(&opts);
[ec36247]658#if GLIB_CHECK_VERSION(2, 32, 0)
659  g_queue_free_full(deferred_entry_queue, owl_log_entry_free);
660#else
661  g_queue_foreach(deferred_entry_queue, owl_log_entry_free_gfunc, NULL);
662  g_queue_free(deferred_entry_queue);
663#endif
664
[cc305b5]665  g_main_loop_quit(log_loop);
666}
667
668void owl_log_shutdown(void)
669{
670  owl_select_post_task(owl_log_quit_func, NULL,
671                       NULL, log_context);
672  g_thread_join(logging_thread);
673}
Note: See TracBrowser for help on using the repository browser.