source: logging.c @ 253f37f

Last change on this file since 253f37f was 253f37f, checked in by Jason Gross <jasongross9@gmail.com>, 7 years ago
Change int ret to int errnum as per PR review As per https://github.com/barnowl/barnowl/pull/109#discussion_r131532257
  • 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
[89e4294]270 * error message, but do not go into deferred logging mode.
271 *
272 * N.B. This function is called only on the disk-writing thread. */
[ec36247]273static void owl_log_eventually_write_entry(gpointer data)
274{
275  int ret;
276  owl_log_entry *msg = (owl_log_entry*)data;
277  if (defer_logs) {
278    owl_log_deferred_enqueue_message(msg->message, msg->filename);
279  } else {
280    ret = owl_log_try_write_entry(msg);
[e6f21ea]281    if (ret == EPERM || ret == EACCES || ret == ETIMEDOUT) {
[ec36247]282      defer_logs = true;
283      owl_log_error("Unable to open file for logging (%s): \n"
284                    "%s.  \n"
285                    "Consider renewing your tickets.  Logging has been \n"
286                    "suspended, and your messages will be saved.  To \n"
287                    "resume logging, use the command :flush-logs.\n\n",
288                    msg->filename,
289                    g_strerror(ret));
[874fd19]290      /* If we were not in deferred logging mode, either the queue should be
291       * empty, or we are attempting to log a message that we just popped off
292       * the head of the queue.  Either way, we should enqueue this message as
293       * the first message in the queue, rather than the last, so that we
294       * preserve message ordering. */
295      owl_log_deferred_enqueue_first_message(msg->message, msg->filename);
[ec36247]296    } else if (ret != 0) {
[77beb3c]297      owl_log_file_error(msg, ret);
[ec36247]298    }
299  }
300}
301
[89e4294]302/* tries to write the deferred log entries
303 *
304 * N.B. This function is called only on the disk-writing thread. */
[ec36247]305static void owl_log_write_deferred_entries(gpointer data)
306{
307  owl_log_entry *entry;
[4511ac3]308  owl_log_options *opts = (owl_log_options *)data;
[77beb3c]309  int ret;
[604303c]310  int logged_message_count = 0;
[edb14cc]311  bool all_succeeded = true;
[ec36247]312
[4511ac3]313  if (opts->display_initial_log_count) {
314    if (g_queue_is_empty(deferred_entry_queue)) {
315      owl_log_makemsg("There are no logs to flush.");
316    } else {
317      owl_log_makemsg("Attempting to flush %u logs...",
318                      g_queue_get_length(deferred_entry_queue));
319    }
[565a43c]320  }
321
[ec36247]322  defer_logs = false;
323  while (!g_queue_is_empty(deferred_entry_queue) && !defer_logs) {
[604303c]324    logged_message_count++;
[ec36247]325    entry = (owl_log_entry*)g_queue_pop_head(deferred_entry_queue);
[4511ac3]326    if (!opts->drop_failed_logs) {
[874fd19]327      /* Attempt to write the log entry.  If it fails, re-queue the entry at
328       * the head of the queue. */
[77beb3c]329      owl_log_eventually_write_entry(entry);
330    } else {
[874fd19]331      /* Attempt to write the log entry. If it fails, print an error message,
332       * drop the log, and keep going through the queue. */
[77beb3c]333      ret = owl_log_try_write_entry(entry);
334      if (ret != 0) {
[edb14cc]335        all_succeeded = false;
[77beb3c]336        owl_log_file_error(entry, ret);
337      }
338    }
[ec36247]339    owl_log_entry_free(entry);
340  }
[565a43c]341  if (logged_message_count > 0) {
[4511ac3]342    if (opts->display_initial_log_count) {
343      /* first clear the "attempting to flush" message from the status bar */
344      owl_log_makemsg("");
345    }
[565a43c]346    if (!defer_logs) {
347      if (all_succeeded) {
348        owl_log_adminmsg("Flushed %d logs and resumed logging.",
349                         logged_message_count);
350      } else {
351        owl_log_adminmsg("Flushed or dropped %d logs and resumed logging.",
352                         logged_message_count);
353      }
354    } else {
355      owl_log_error("Attempted to flush %d logs; %u deferred logs remain.",
356                    logged_message_count, g_queue_get_length(deferred_entry_queue));
357    }
[edb14cc]358  }
[ec36247]359}
360
[4511ac3]361void owl_log_flush_logs(bool drop_failed_logs, bool quiet)
[ec36247]362{
[4511ac3]363  owl_log_options *data = g_new(owl_log_options, 1);
364  data->drop_failed_logs = drop_failed_logs;
365  data->display_initial_log_count = !quiet;
[77beb3c]366
367  owl_select_post_task(owl_log_write_deferred_entries,
368                       data,
369                       g_free,
370                       log_context);
[ec36247]371}
372
[cc305b5]373void owl_log_enqueue_message(const char *buffer, const char *filename)
374{
[ec36247]375  owl_log_entry *log_msg = owl_log_new_entry(buffer, filename);
376  owl_select_post_task(owl_log_eventually_write_entry, log_msg,
[cc305b5]377                       owl_log_entry_free, log_context);
[42947f1]378}
379
[c08c70a]380void owl_log_append(const owl_message *m, const char *filename) {
[cc305b5]381  char *buffer = NULL;
382  if (owl_message_is_type_zephyr(m)) {
383    buffer = owl_log_zephyr(m);
384  } else if (owl_message_is_type_jabber(m)) {
385    buffer = owl_log_jabber(m);
386  } else if (owl_message_is_type_aim(m)) {
387    buffer = owl_log_aim(m);
388  } else {
389    buffer = owl_log_generic(m);
390  }
391  owl_log_enqueue_message(buffer, filename);
392  g_free(buffer);
[42947f1]393}
394
[c08c70a]395void owl_log_outgoing(const owl_message *m)
[15b34fd]396{
[e3a75ed]397  char *filename, *logpath;
[9c590d4]398  char *to, *temp;
[839697d]399  GList *cc;
[9c590d4]400
401  /* expand ~ in path names */
[60d7935]402  logpath = owl_util_makepath(owl_global_get_logpath(&g));
[15b34fd]403
[42947f1]404  /* Figure out what path to log to */
405  if (owl_message_is_type_zephyr(m)) {
[af1920fd]406    /* If this has CC's, do all but the "recipient" which we'll do below */
[839697d]407    cc = owl_message_get_cc_without_recipient(m);
408    while (cc != NULL) {
409      temp = short_zuser(cc->data);
[dde1b4d]410      filename = g_build_filename(logpath, temp, NULL);
[839697d]411      owl_log_append(m, filename);
412
[e3a75ed]413      g_free(filename);
[ddbbcffa]414      g_free(temp);
415      g_free(cc->data);
[839697d]416      cc = g_list_delete_link(cc, cc);
[9c590d4]417    }
[839697d]418
[9c590d4]419    to = short_zuser(owl_message_get_recipient(m));
[42947f1]420  } else if (owl_message_is_type_jabber(m)) {
[3472845]421    to = g_strdup_printf("jabber:%s", owl_message_get_recipient(m));
[7865479]422    g_strdelimit(to, "/", '_');
[42947f1]423  } else if (owl_message_is_type_aim(m)) {
[28ee32b]424    char *temp2;
[9c590d4]425    temp = owl_aim_normalize_screenname(owl_message_get_recipient(m));
[28ee32b]426    temp2 = g_utf8_strdown(temp,-1);
[3472845]427    to = g_strdup_printf("aim:%s", temp2);
[ddbbcffa]428    g_free(temp2);
429    g_free(temp);
[42947f1]430  } else {
[d4927a7]431    to = g_strdup("loopback");
[42947f1]432  }
[7d4fbcd]433
[dde1b4d]434  filename = g_build_filename(logpath, to, NULL);
[42947f1]435  owl_log_append(m, filename);
[ddbbcffa]436  g_free(to);
[e3a75ed]437  g_free(filename);
[7d4fbcd]438
[dde1b4d]439  filename = g_build_filename(logpath, "all", NULL);
[42947f1]440  owl_log_append(m, filename);
[ddbbcffa]441  g_free(logpath);
[e3a75ed]442  g_free(filename);
[7d4fbcd]443}
444
[42947f1]445
[24ccc01]446void owl_log_outgoing_zephyr_error(const owl_zwrite *zw, const char *text)
[2b86d14]447{
[e3a75ed]448  char *filename, *logpath;
[fe3b017]449  char *tobuff, *recip;
[180cd15]450  owl_message *m;
[cc305b5]451  GString *msgbuf;
[180cd15]452  /* create a present message so we can pass it to
[c79a047]453   * owl_log_shouldlog_message(void)
[180cd15]454   */
[7dcef03]455  m = g_slice_new(owl_message);
[e5da3fe]456  /* recip_index = 0 because there can only be one recipient anyway */
457  owl_message_create_from_zwrite(m, zw, text, 0);
[180cd15]458  if (!owl_log_shouldlog_message(m)) {
[91634ec]459    owl_message_delete(m);
[180cd15]460    return;
461  }
[91634ec]462  owl_message_delete(m);
[2b86d14]463
[180cd15]464  /* chop off a local realm */
[fe3b017]465  recip = owl_zwrite_get_recip_n_with_realm(zw, 0);
466  tobuff = short_zuser(recip);
467  g_free(recip);
[2b86d14]468
469  /* expand ~ in path names */
[60d7935]470  logpath = owl_util_makepath(owl_global_get_logpath(&g));
[dde1b4d]471  filename = g_build_filename(logpath, tobuff, NULL);
[cc305b5]472  msgbuf = g_string_new("");
473  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
474  if (text[strlen(text)-1] != '\n') {
475    g_string_append_printf(msgbuf, "\n");
[2b86d14]476  }
[cc305b5]477  owl_log_enqueue_message(msgbuf->str, filename);
478  g_string_free(msgbuf, TRUE);
[2b86d14]479
[dde1b4d]480  filename = g_build_filename(logpath, "all", NULL);
[ddbbcffa]481  g_free(logpath);
[cc305b5]482  msgbuf = g_string_new("");
483  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
484  if (text[strlen(text)-1] != '\n') {
485    g_string_append_printf(msgbuf, "\n");
[2b86d14]486  }
[cc305b5]487  owl_log_enqueue_message(msgbuf->str, filename);
488  g_string_free(msgbuf, TRUE);
[2b86d14]489
[ddbbcffa]490  g_free(tobuff);
[2b86d14]491}
492
[c08c70a]493void owl_log_incoming(const owl_message *m)
[15283bb]494{
[e3a75ed]495  char *filename, *allfilename, *logpath;
[e19eb97]496  const char *from=NULL;
[65b2173]497  char *frombuff=NULL;
[7d4fbcd]498  int len, ch, i, personal;
[12c35df]499
[15b34fd]500  /* figure out if it's a "personal" message or not */
[aac889a]501  if (owl_message_is_type_zephyr(m)) {
502    if (owl_message_is_personal(m)) {
[42947f1]503      personal = 1;
[aac889a]504    } else {
[42947f1]505      personal = 0;
[aac889a]506    }
[2182be3]507  } else if (owl_message_is_type_jabber(m)) {
[42947f1]508    /* This needs to be fixed to handle groupchat */
[e19eb97]509    const char* msgtype = owl_message_get_attribute_value(m,"jtype");
[42947f1]510    if (msgtype && !strcmp(msgtype,"groupchat")) {
511      personal = 0;
512    } else {
513      personal = 1;
514    }
[7d4fbcd]515  } else {
[79a0e82]516    if (owl_message_is_private(m) || owl_message_is_loginout(m)) {
[42947f1]517      personal = 1;
[aac889a]518    } else {
[42947f1]519      personal = 0;
[aac889a]520    }
[7d4fbcd]521  }
522
[2182be3]523
[aac889a]524  if (owl_message_is_type_zephyr(m)) {
525    if (personal) {
[3066d23]526      from=frombuff=short_zuser(owl_message_get_sender(m));
[aac889a]527    } else {
[d4927a7]528      from=frombuff=g_strdup(owl_message_get_class(m));
[7d4fbcd]529    }
[aac889a]530  } else if (owl_message_is_type_aim(m)) {
531    /* we do not yet handle chat rooms */
[28ee32b]532    char *normalto, *temp;
533    temp = owl_aim_normalize_screenname(owl_message_get_sender(m));
534    normalto = g_utf8_strdown(temp, -1);
[3472845]535    from=frombuff=g_strdup_printf("aim:%s", normalto);
[ddbbcffa]536    g_free(normalto);
537    g_free(temp);
[37eab7f]538  } else if (owl_message_is_type_loopback(m)) {
[d4927a7]539    from=frombuff=g_strdup("loopback");
[2182be3]540  } else if (owl_message_is_type_jabber(m)) {
[5c30091]541    if (personal) {
[cc305b5]542      from=frombuff=g_strdup_printf("jabber:%s", 
543                                    owl_message_get_sender(m));
[5c30091]544    } else {
[cc305b5]545      from=frombuff=g_strdup_printf("jabber:%s", 
546                                    owl_message_get_recipient(m));
[5c30091]547    }
[e6449bc]548  } else {
[d4927a7]549    from=frombuff=g_strdup("unknown");
[7d4fbcd]550  }
551 
552  /* check for malicious sender formats */
553  len=strlen(frombuff);
554  if (len<1 || len>35) from="weird";
555  if (strchr(frombuff, '/')) from="weird";
556
557  ch=frombuff[0];
[28ee32b]558  if (!g_ascii_isalnum(ch)) from="weird";
[7d4fbcd]559
560  for (i=0; i<len; i++) {
[e1c4636]561    if (frombuff[i]<'!' || frombuff[i]>='~') from="weird";
[7d4fbcd]562  }
563
564  if (!strcmp(frombuff, ".") || !strcasecmp(frombuff, "..")) from="weird";
565
566  if (!personal) {
[28ee32b]567    if (strcmp(from, "weird")) {
568      char* temp = g_utf8_strdown(frombuff, -1);
569      if (temp) {
[ddbbcffa]570        g_free(frombuff);
[28ee32b]571        from = frombuff = temp;
572      }
573    }
[7d4fbcd]574  }
575
[e1c4636]576  /* create the filename (expanding ~ in path names) */
[7d4fbcd]577  if (personal) {
[60d7935]578    logpath = owl_util_makepath(owl_global_get_logpath(&g));
[dde1b4d]579    filename = g_build_filename(logpath, from, NULL);
580    allfilename = g_build_filename(logpath, "all", NULL);
[d0961fe]581    owl_log_append(m, allfilename);
[e3a75ed]582    g_free(allfilename);
[7d4fbcd]583  } else {
[60d7935]584    logpath = owl_util_makepath(owl_global_get_classlogpath(&g));
[dde1b4d]585    filename = g_build_filename(logpath, from, NULL);
[7d4fbcd]586  }
[37eab7f]587
[42947f1]588  owl_log_append(m, filename);
[e3a75ed]589  g_free(filename);
[7d4fbcd]590
[d0961fe]591  if (personal && owl_message_is_type_zephyr(m)) {
[af1920fd]592    /* We want to log to all of the CC'd people who were not us, or
593     * the sender, as well.
594     */
[839697d]595    char *temp;
596    GList *cc;
[d0961fe]597    cc = owl_message_get_cc_without_recipient(m);
[839697d]598    while (cc != NULL) {
599      temp = short_zuser(cc->data);
600      if (strcasecmp(temp, frombuff) != 0) {
[dde1b4d]601        filename = g_build_filename(logpath, temp, NULL);
[839697d]602        owl_log_append(m, filename);
[e3a75ed]603        g_free(filename);
[d0961fe]604      }
[839697d]605
[ddbbcffa]606      g_free(temp);
607      g_free(cc->data);
[839697d]608      cc = g_list_delete_link(cc, cc);
[d0961fe]609    }
610  }
[7d4fbcd]611
[ddbbcffa]612  g_free(frombuff);
613  g_free(logpath);
[7d4fbcd]614}
[cc305b5]615
616static gpointer owl_log_thread_func(gpointer data)
617{
[ec36247]618  log_context = g_main_context_new();
[cc305b5]619  log_loop = g_main_loop_new(log_context, FALSE);
620  g_main_loop_run(log_loop);
621  return NULL;
622}
623
[ec36247]624void owl_log_init(void)
[cc305b5]625{
[0a9ffc5]626  log_context = g_main_context_new();
[0792d99]627#if GLIB_CHECK_VERSION(2, 31, 0)
628  logging_thread = g_thread_new("logging",
629                                owl_log_thread_func,
630                                NULL);
631#else
632  GError *error = NULL;
[cc305b5]633  logging_thread = g_thread_create(owl_log_thread_func,
634                                   NULL,
635                                   TRUE,
636                                   &error);
637  if (error) {
638    endwin();
639    fprintf(stderr, "Error spawning logging thread: %s\n", error->message);
640    fflush(stderr);
641    exit(1);
642  }
[0792d99]643#endif
[ec36247]644
645  deferred_entry_queue = g_queue_new();
[cc305b5]646}
647
648static void owl_log_quit_func(gpointer data)
649{
[ec36247]650  /* flush the deferred logs queue, trying to write the
[77beb3c]651   * entries to the disk one last time.  Drop any failed
[4511ac3]652   * entries, and be quiet about it. */
653  owl_log_options opts;
654  opts.drop_failed_logs = true;
655  opts.display_initial_log_count = false;
656  owl_log_write_deferred_entries(&opts);
[ec36247]657#if GLIB_CHECK_VERSION(2, 32, 0)
658  g_queue_free_full(deferred_entry_queue, owl_log_entry_free);
659#else
660  g_queue_foreach(deferred_entry_queue, owl_log_entry_free_gfunc, NULL);
661  g_queue_free(deferred_entry_queue);
662#endif
663
[cc305b5]664  g_main_loop_quit(log_loop);
665}
666
667void owl_log_shutdown(void)
668{
669  owl_select_post_task(owl_log_quit_func, NULL,
670                       NULL, log_context);
671  g_thread_join(logging_thread);
672}
Note: See TracBrowser for help on using the repository browser.