Initial Import
[profile/ivi/glib2.git] / packaging / glib-2.24.0-syslog-message-handler.patch
1 From adee01a89537bf8bb2e81508f1a7a6c43202bb48 Mon Sep 17 00:00:00 2001
2 From: Damien Lespiau <damien.lespiau@intel.com>
3 Date: Mon, 10 May 2010 20:31:55 +0100
4 Subject: [PATCH] Add a custom log handling for MeeGo
5
6 * The log system should not output to stdout/stderr when not in an
7   interactive shell as uxlaunch logs those to ~/.xsession-errors.
8 * When being launched from a interactive shell, display the messages as
9   usual
10 * Log messages to syslog to be able to detect/investigate issues. The
11   verbosity of messages logged this way is tweakable though the
12   glib.syslog linux command line parameter:
13     -  glib.syslog=0 disables syslog logging
14     -  glib.syslog=1 logs error messages
15     -  ...
16     -  glib.syslog=6 logs debug messages
17   It defaults to logging WARNING, CRITICAL and ERROR messages
18 ---
19  glib/gmessages.c |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
20  1 files changed, 143 insertions(+), 1 deletions(-)
21
22 diff --git a/glib/gmessages.c b/glib/gmessages.c
23 index 9a3eec3..ad05954 100644
24 --- a/glib/gmessages.c
25 +++ b/glib/gmessages.c
26 @@ -40,6 +40,7 @@
27  #include <signal.h>
28  #include <locale.h>
29  #include <errno.h>
30 +#include <syslog.h>
31  
32  #include "glib.h"
33  #include "gdebug.h"
34 @@ -925,6 +926,142 @@ escape_string (GString *string)
35      }
36  }
37  
38 +/* That is a syslog version of default log handler. */
39 +
40 +#define IS_EMPTY_STRING(s)     (NULL == (s) || 0 == *(s))
41 +
42 +#define GLIB_PREFIX    "GLIB"
43 +#define DEFAULT_DOMAIN "default"
44 +#define DEFAULT_MESSAGE        "(NULL) message"
45 +
46 +/*
47 + * Returns the shift of maximum log level we should log.
48 + * This level can be tuned with a linux command line parameter:
49 + *  glib.syslog=0 disables syslog logging
50 + *  glib.syslog=1 logs error messages
51 + *  ...
52 + *  glib.syslog=6 logs debug messages
53 + *
54 + * We default to logging G_LOG_LEVEL_WARNING messages and down (ie. ERROR,
55 + * CRITICAL, WARNING)
56 + */
57 +
58 +#define GLIB_SYSLOG_CMDLINE_PARAM   "glib.syslog="
59 +
60 +static guint
61 +g_log_syslog_max_level_shift (void)
62 +{
63 +  static guint max_level = 0;
64 +  gchar *cmdline;
65 +  guint i;
66 +  gchar **tokens;
67 +
68 +  if (G_LIKELY (max_level) != 0)
69 +    return max_level;
70 +
71 +  max_level = 4; /* defaults WARNING */
72 +  if (!g_file_get_contents ("/proc/cmdline", &cmdline, NULL, NULL))
73 +    return max_level;
74 +
75 +  tokens = g_strsplit (cmdline, " ", 0);
76 +  for (i = 0; tokens[i]; i++)
77 +    {
78 +      gchar *level, *token = tokens[i];
79 +
80 +      if (!g_str_has_prefix (token, GLIB_SYSLOG_CMDLINE_PARAM))
81 +        continue;
82 +
83 +      level = token + sizeof (GLIB_SYSLOG_CMDLINE_PARAM) - 1;
84 +      max_level = atoi (level);
85 +      max_level = CLAMP (max_level + 1, 1, 7);
86 +    }
87 +
88 +  g_strfreev (tokens);
89 +  g_free (cmdline);
90 +
91 +  return max_level;
92 +}
93 +
94 +static void
95 +g_log_syslog_handler (const gchar    *log_domain,
96 +                     GLogLevelFlags  log_level,
97 +                     const gchar    *message,
98 +                     gpointer        unused_data)
99 +{
100 +  static gboolean initialized = FALSE;
101 +
102 +  /* This call only variables */
103 +  const gchar* alert    = (log_level & ALERT_LEVELS ? " ** " : " ");
104 +  const gchar* aborting = (log_level & G_LOG_FLAG_FATAL ? "\naborting..." : "");
105 +
106 +  const gchar* prefix;
107 +  int   priority;
108 +
109 +  /* Check first that logging facility is initialized */
110 +  if (G_UNLIKELY (initialized == FALSE))
111 +    {
112 +      openlog (NULL, LOG_PID, LOG_USER);
113 +      initialized = !initialized;
114 +    }
115 +
116 +  /* do we actually log that level? */
117 +  if ((1 << g_log_syslog_max_level_shift ()) < (log_level & G_LOG_LEVEL_MASK))
118 +    return;
119 +
120 +  /* Validate log domain */
121 +  if (IS_EMPTY_STRING (log_domain))
122 +    log_domain = DEFAULT_DOMAIN;
123 +
124 +  /* Check log message for validity */
125 +  if (IS_EMPTY_STRING (message))
126 +    message = DEFAULT_MESSAGE;
127 +
128 +  /* Process the message prefix and priority */
129 +  switch (log_level & G_LOG_LEVEL_MASK)
130 +    {
131 +    case G_LOG_LEVEL_ERROR:
132 +      prefix   = "ERROR";
133 +      priority = LOG_ERR;
134 +      break;
135 +    case G_LOG_LEVEL_CRITICAL:
136 +      prefix   = "CRITICAL";
137 +      priority = LOG_CRIT;
138 +      break;
139 +    case G_LOG_LEVEL_WARNING:
140 +      prefix   = "WARNING";
141 +      priority = LOG_WARNING;
142 +      break;
143 +    case G_LOG_LEVEL_MESSAGE:
144 +      prefix   = "MESSAGE";
145 +      priority = LOG_NOTICE;
146 +      break;
147 +    case G_LOG_LEVEL_INFO:
148 +      prefix   = "INFO";
149 +      priority = LOG_INFO;
150 +      break;
151 +    default:
152 +      prefix   = "DEBUG";
153 +      priority = LOG_DEBUG;
154 +      break;
155 +    }
156 +
157 +  /* Now printing the message to syslog */
158 +  syslog (priority, "%s %s%s%s - %s%s", GLIB_PREFIX, prefix, alert, log_domain,
159 +          message, aborting);
160 +}
161 +
162 +static gboolean
163 +is_interactive (void)
164 +{
165 +  gint interactive = -1;
166 +
167 +  if (G_LIKELY (interactive != -1))
168 +    return interactive;
169 +
170 +  interactive = g_getenv ("PWD") != NULL;
171 +  return interactive;
172 +}
173 +
174  void
175  g_log_default_handler (const gchar   *log_domain,
176                        GLogLevelFlags log_level,
177 @@ -999,7 +1136,12 @@ g_log_default_handler (const gchar   *log_domain,
178  
179    string = g_string_free (gstring, FALSE);
180  
181 -  write_string (fd, string);
182 +  /* only output a string to stdout/stderr if we are in an interactive shell */
183 +  if (is_interactive ())
184 +    write_string (fd, string);
185 +
186 +  /* */
187 +  g_log_syslog_handler (log_domain, log_level, message, unused_data);
188    g_free (string);
189  }
190  
191 -- 
192 1.7.0.1
193