Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : */
19 : :
20 : : /*
21 : : * Modified by the GLib Team and others 1997-2000. See the AUTHORS
22 : : * file for a list of people on the GLib Team. See the ChangeLog
23 : : * files for a list of changes. These files are distributed with
24 : : * GLib at ftp://ftp.gtk.org/pub/gtk/.
25 : : */
26 : :
27 : : /*
28 : : * MT safe
29 : : */
30 : :
31 : : #include "config.h"
32 : :
33 : : #include <stdlib.h>
34 : : #include <stdarg.h>
35 : : #include <stdio.h>
36 : : #include <string.h>
37 : : #include <signal.h>
38 : : #include <locale.h>
39 : : #include <errno.h>
40 : :
41 : : #if defined(__linux__) && !defined(__BIONIC__)
42 : : #include <sys/types.h>
43 : : #include <sys/socket.h>
44 : : #include <sys/un.h>
45 : : #include <fcntl.h>
46 : : #include <sys/uio.h>
47 : : #endif
48 : :
49 : : #include "galloca.h"
50 : : #include "gbacktrace.h"
51 : : #include "gcharset.h"
52 : : #include "gconvert.h"
53 : : #include "genviron.h"
54 : : #include "glib-init.h"
55 : : #include "glib-private.h"
56 : : #include "gmain.h"
57 : : #include "gmem.h"
58 : : #include "gpattern.h"
59 : : #include "gprintfint.h"
60 : : #include "gstrfuncs.h"
61 : : #include "gstring.h"
62 : : #include "gtestutils.h"
63 : : #include "gthread.h"
64 : : #include "gthreadprivate.h"
65 : : #include "gutilsprivate.h"
66 : :
67 : : #ifdef HAVE_SYSLOG_H
68 : : #include <syslog.h>
69 : : #endif
70 : :
71 : : #if defined(__linux__) && !defined(__BIONIC__)
72 : : #include "gjournal-private.h"
73 : : #endif
74 : :
75 : : #ifdef G_OS_UNIX
76 : : #include <unistd.h>
77 : : #endif
78 : :
79 : : #ifdef G_OS_WIN32
80 : : #include <process.h> /* For getpid() */
81 : : #include <io.h>
82 : : # include <windows.h>
83 : :
84 : : #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
85 : : #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
86 : : #endif
87 : :
88 : : #include "gwin32.h"
89 : : #endif
90 : :
91 : : /**
92 : : * G_LOG_DOMAIN:
93 : : *
94 : : * Defines the log domain. See [Log Domains](#log-domains).
95 : : *
96 : : * Libraries should define this so that any messages
97 : : * which they log can be differentiated from messages from other
98 : : * libraries and application code. But be careful not to define
99 : : * it in any public header files.
100 : : *
101 : : * Log domains must be unique, and it is recommended that they are the
102 : : * application or library name, optionally followed by a hyphen and a sub-domain
103 : : * name. For example, `bloatpad` or `bloatpad-io`.
104 : : *
105 : : * If undefined, it defaults to the default %NULL (or `""`) log domain; this is
106 : : * not advisable, as it cannot be filtered against using the `G_MESSAGES_DEBUG`
107 : : * environment variable.
108 : : *
109 : : * For example, GTK uses this in its `Makefile.am`:
110 : : * |[
111 : : * AM_CPPFLAGS = -DG_LOG_DOMAIN=\"Gtk\"
112 : : * ]|
113 : : *
114 : : * Applications can choose to leave it as the default %NULL (or `""`)
115 : : * domain. However, defining the domain offers the same advantages as
116 : : * above.
117 : : *
118 : :
119 : : */
120 : :
121 : : /**
122 : : * G_LOG_FATAL_MASK:
123 : : *
124 : : * GLib log levels that are considered fatal by default.
125 : : *
126 : : * This is not used if structured logging is enabled; see
127 : : * [Using Structured Logging](logging.html#using-structured-logging).
128 : : */
129 : :
130 : : /**
131 : : * GLogFunc:
132 : : * @log_domain: the log domain of the message
133 : : * @log_level: the log level of the message (including the
134 : : * fatal and recursion flags)
135 : : * @message: the message to process
136 : : * @user_data: user data, set in [func@GLib.log_set_handler]
137 : : *
138 : : * Specifies the prototype of log handler functions.
139 : : *
140 : : * The default log handler, [func@GLib.log_default_handler], automatically appends a
141 : : * new-line character to @message when printing it. It is advised that any
142 : : * custom log handler functions behave similarly, so that logging calls in user
143 : : * code do not need modifying to add a new-line character to the message if the
144 : : * log handler is changed.
145 : : *
146 : : * This is not used if structured logging is enabled; see
147 : : * [Using Structured Logging](logging.html#using-structured-logging).
148 : : */
149 : :
150 : : /**
151 : : * GLogLevelFlags:
152 : : * @G_LOG_FLAG_RECURSION: internal flag
153 : : * @G_LOG_FLAG_FATAL: internal flag
154 : : * @G_LOG_LEVEL_ERROR: log level for errors, see [func@GLib.error].
155 : : * This level is also used for messages produced by [func@GLib.assert].
156 : : * @G_LOG_LEVEL_CRITICAL: log level for critical warning messages, see
157 : : * [func@GLib.critical]. This level is also used for messages produced by
158 : : * [func@GLib.return_if_fail] and [func@GLib.return_val_if_fail].
159 : : * @G_LOG_LEVEL_WARNING: log level for warnings, see [func@GLib.warning]
160 : : * @G_LOG_LEVEL_MESSAGE: log level for messages, see [func@GLib.message]
161 : : * @G_LOG_LEVEL_INFO: log level for informational messages, see [func@GLib.info]
162 : : * @G_LOG_LEVEL_DEBUG: log level for debug messages, see [func@GLib.debug]
163 : : * @G_LOG_LEVEL_MASK: a mask including all log levels
164 : : *
165 : : * Flags specifying the level of log messages.
166 : : *
167 : : * It is possible to change how GLib treats messages of the various
168 : : * levels using [func@GLib.log_set_handler] and [func@GLib.log_set_fatal_mask].
169 : : */
170 : :
171 : : /**
172 : : * G_LOG_LEVEL_USER_SHIFT:
173 : : *
174 : : * Log levels below `1<<G_LOG_LEVEL_USER_SHIFT` are used by GLib.
175 : : * Higher bits can be used for user-defined log levels.
176 : : */
177 : :
178 : : /**
179 : : * g_message:
180 : : * @...: format string, followed by parameters to insert into the format string
181 : : * (as with `printf()`)
182 : : *
183 : : * A convenience function/macro to log a normal message.
184 : : *
185 : : * If [func@GLib.log_default_handler] is used as the log handler function, a new-line
186 : : * character will automatically be appended to @..., and need not be entered
187 : : * manually.
188 : : *
189 : : * If structured logging is enabled, this will use [func@GLib.log_structured];
190 : : * otherwise it will use [func@GLib.log]. See
191 : : * [Using Structured Logging](logging.html#using-structured-logging).
192 : : */
193 : :
194 : : /**
195 : : * g_warning:
196 : : * @...: format string, followed by parameters to insert into the format string
197 : : * (as with `printf()`)
198 : : *
199 : : * A convenience function/macro to log a warning message.
200 : : *
201 : : * The message should typically *not* be translated to the user’s language.
202 : : *
203 : : * This is not intended for end user error reporting. Use of [type@GLib.Error] is
204 : : * preferred for that instead, as it allows calling functions to perform actions
205 : : * conditional on the type of error.
206 : : *
207 : : * Warning messages are intended to be used in the event of unexpected
208 : : * external conditions (system misconfiguration, missing files,
209 : : * other trusted programs violating protocol, invalid contents in
210 : : * trusted files, etc.)
211 : : *
212 : : * If attempting to deal with programmer errors (for example, incorrect function
213 : : * parameters) then you should use [flags@GLib.LogLevelFlags.LEVEL_CRITICAL] instead.
214 : : *
215 : : * [func@GLib.warn_if_reached] and func@GLib.warn_if_fail] log at [flags@GLib.LogLevelFlags.LEVEL_WARNING].
216 : : *
217 : : * You can make warnings fatal at runtime by setting the `G_DEBUG`
218 : : * environment variable (see
219 : : * [Running GLib Applications](glib-running.html)):
220 : : *
221 : : * ```
222 : : * G_DEBUG=fatal-warnings gdb ./my-program
223 : : * ```
224 : : *
225 : : * Any unrelated failures can be skipped over in
226 : : * [gdb](https://www.gnu.org/software/gdb/) using the `continue` command.
227 : : *
228 : : * If [func@GLib.log_default_handler] is used as the log handler function,
229 : : * a newline character will automatically be appended to @..., and
230 : : * need not be entered manually.
231 : : *
232 : : * If structured logging is enabled, this will use [func@GLib.log_structured];
233 : : * otherwise it will use [func@GLib.log]. See
234 : : * [Using Structured Logging](logging.html#using-structured-logging).
235 : : */
236 : :
237 : : /**
238 : : * g_critical:
239 : : * @...: format string, followed by parameters to insert into the format string
240 : : * (as with `printf()`)
241 : : *
242 : : * Logs a ‘critical warning’ ([flags@GLib.LogLevelFlags.LEVEL_CRITICAL]).
243 : : *
244 : : * Critical warnings are intended to be used in the event of an error
245 : : * that originated in the current process (a programmer error).
246 : : * Logging of a critical error is by definition an indication of a bug
247 : : * somewhere in the current program (or its libraries).
248 : : *
249 : : * [func@GLib.return_if_fail], [func@GLib.return_val_if_fail], [func@GLib.return_if_reached] and
250 : : * [func@GLib.return_val_if_reached] log at [flags@GLib.LogLevelFlags.LEVEL_CRITICAL].
251 : : *
252 : : * You can make critical warnings fatal at runtime by
253 : : * setting the `G_DEBUG` environment variable (see
254 : : * [Running GLib Applications](glib-running.html)):
255 : : *
256 : : * ```
257 : : * G_DEBUG=fatal-warnings gdb ./my-program
258 : : * ```
259 : : *
260 : : * You can also use [func@GLib.log_set_always_fatal].
261 : : *
262 : : * Any unrelated failures can be skipped over in
263 : : * [gdb](https://www.gnu.org/software/gdb/) using the `continue` command.
264 : : *
265 : : * The message should typically *not* be translated to the
266 : : * user’s language.
267 : : *
268 : : * If [func@GLib.log_default_handler] is used as the log handler function, a new-line
269 : : * character will automatically be appended to @..., and need not be entered
270 : : * manually.
271 : : *
272 : : * If structured logging is enabled, this will use [func@GLib.log_structured];
273 : : * otherwise it will use [func@GLib.log]. See
274 : : * [Using Structured Logging](logging.html#using-structured-logging).
275 : : */
276 : :
277 : : /**
278 : : * g_error:
279 : : * @...: format string, followed by parameters to insert into the format string
280 : : * (as with `printf()`)
281 : : *
282 : : * A convenience function/macro to log an error message.
283 : : *
284 : : * The message should typically *not* be translated to the user’s language.
285 : : *
286 : : * This is not intended for end user error reporting. Use of [type@GLib.Error] is
287 : : * preferred for that instead, as it allows calling functions to perform actions
288 : : * conditional on the type of error.
289 : : *
290 : : * Error messages are always fatal, resulting in a call to [func@GLib.BREAKPOINT]
291 : : * to terminate the application. This function will
292 : : * result in a core dump; don’t use it for errors you expect.
293 : : * Using this function indicates a bug in your program, i.e.
294 : : * an assertion failure.
295 : : *
296 : : * If [func@GLib.log_default_handler] is used as the log handler function, a new-line
297 : : * character will automatically be appended to @..., and need not be entered
298 : : * manually.
299 : : *
300 : : * If structured logging is enabled, this will use [func@GLib.log_structured];
301 : : * otherwise it will use [func@GLib.log]. See
302 : : * [Using Structured Logging](logging.html#using-structured-logging).
303 : : */
304 : :
305 : : /**
306 : : * g_info:
307 : : * @...: format string, followed by parameters to insert into the format string
308 : : * (as with `printf()`)
309 : : *
310 : : * A convenience function/macro to log an informational message.
311 : : *
312 : : * Seldom used.
313 : : *
314 : : * If [func@GLib.log_default_handler] is used as the log handler function, a new-line
315 : : * character will automatically be appended to @..., and need not be entered
316 : : * manually.
317 : : *
318 : : * Such messages are suppressed by the [func@GLib.log_default_handler] and
319 : : * [func@GLib.log_writer_default] unless the `G_MESSAGES_DEBUG` environment variable is
320 : : * set appropriately. If you need to set the allowed domains at runtime, use
321 : : * [func@GLib.log_writer_default_set_debug_domains].
322 : : *
323 : : * If structured logging is enabled, this will use [func@GLib.log_structured];
324 : : * otherwise it will use [func@GLib.log]. See
325 : : * [Using Structured Logging](logging.html#using-structured-logging).
326 : : *
327 : : * Since: 2.40
328 : : */
329 : :
330 : : /**
331 : : * g_debug:
332 : : * @...: format string, followed by parameters to insert into the format string
333 : : * (as with `printf()`)
334 : : *
335 : : * A convenience function/macro to log a debug message.
336 : : *
337 : : * The message should typically *not* be translated to the user’s language.
338 : : *
339 : : * If [func@GLib.log_default_handler] is used as the log handler function, a new-line
340 : : * character will automatically be appended to @..., and need not be entered
341 : : * manually.
342 : : *
343 : : * Such messages are suppressed by the [func@GLib.log_default_handler] and
344 : : * [func@GLib.log_writer_default] unless the `G_MESSAGES_DEBUG` environment variable is
345 : : * set appropriately. If you need to set the allowed domains at runtime, use
346 : : * [func@GLib.log_writer_default_set_debug_domains].
347 : : *
348 : : * If structured logging is enabled, this will use [func@GLib.log_structured];
349 : : * otherwise it will use [func@GLib.log]. See
350 : : * [Using Structured Logging](logging.html#using-structured-logging).
351 : : *
352 : : * Since: 2.6
353 : : */
354 : :
355 : : /* --- structures --- */
356 : : typedef struct _GLogDomain GLogDomain;
357 : : typedef struct _GLogHandler GLogHandler;
358 : : struct _GLogDomain
359 : : {
360 : : gchar *log_domain;
361 : : GLogLevelFlags fatal_mask;
362 : : GLogHandler *handlers;
363 : : GLogDomain *next;
364 : : };
365 : : struct _GLogHandler
366 : : {
367 : : guint id;
368 : : GLogLevelFlags log_level;
369 : : GLogFunc log_func;
370 : : gpointer data;
371 : : GDestroyNotify destroy;
372 : : GLogHandler *next;
373 : : };
374 : :
375 : : static void g_default_print_func (const gchar *string);
376 : : static void g_default_printerr_func (const gchar *string);
377 : :
378 : : /* --- variables --- */
379 : : static GMutex g_messages_lock;
380 : : static GLogDomain *g_log_domains = NULL;
381 : : static GPrintFunc glib_print_func = g_default_print_func;
382 : : static GPrintFunc glib_printerr_func = g_default_printerr_func;
383 : : static GPrivate g_log_depth;
384 : : static GPrivate g_log_structured_depth;
385 : : static GLogFunc default_log_func = g_log_default_handler;
386 : : static gpointer default_log_data = NULL;
387 : : static GTestLogFatalFunc fatal_log_func = NULL;
388 : : static gpointer fatal_log_data;
389 : : static GLogWriterFunc log_writer_func = g_log_writer_default;
390 : : static gpointer log_writer_user_data = NULL;
391 : : static GDestroyNotify log_writer_user_data_free = NULL;
392 : : static gboolean g_log_debug_enabled = FALSE; /* (atomic) */
393 : :
394 : : /* --- functions --- */
395 : :
396 : : static void _g_log_abort (gboolean breakpoint);
397 : : static inline const char * format_string (const char *format,
398 : : va_list args,
399 : : char **out_allocated_string)
400 : : G_GNUC_PRINTF (1, 0);
401 : : static inline FILE * log_level_to_file (GLogLevelFlags log_level);
402 : :
403 : : static void
404 : 0 : _g_log_abort (gboolean breakpoint)
405 : : {
406 : : gboolean debugger_present;
407 : :
408 [ # # ]: 0 : if (g_test_subprocess ())
409 : : {
410 : : /* If this is a test case subprocess then it probably caused
411 : : * this error message on purpose, so just exit() rather than
412 : : * abort()ing, to avoid triggering any system crash-reporting
413 : : * daemon.
414 : : */
415 : 0 : _exit (1);
416 : : }
417 : :
418 : : #ifdef G_OS_WIN32
419 : : debugger_present = IsDebuggerPresent ();
420 : : #else
421 : : /* Assume GDB is attached. */
422 : 0 : debugger_present = TRUE;
423 : : #endif /* !G_OS_WIN32 */
424 : :
425 [ # # # # ]: 0 : if (debugger_present && breakpoint)
426 : 0 : G_BREAKPOINT ();
427 : : else
428 : 0 : g_abort ();
429 : 0 : }
430 : :
431 : : #ifdef G_OS_WIN32
432 : : static gboolean win32_keep_fatal_message = FALSE;
433 : :
434 : : /* This default message will usually be overwritten. */
435 : : /* Yes, a fixed size buffer is bad. So sue me. But g_error() is never
436 : : * called with huge strings, is it?
437 : : */
438 : : static gchar fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting.";
439 : :
440 : : #endif
441 : :
442 : : static void
443 : 0 : write_string (FILE *stream,
444 : : const gchar *string)
445 : : {
446 : 0 : if (fputs (string, stream) == EOF)
447 : : {
448 : : /* Something failed, but it's not an error we can handle at glib level
449 : : * so let's just continue without the compiler blaming us
450 : : */
451 : : }
452 : 0 : }
453 : :
454 : : static void
455 : 0 : write_string_sized (FILE *stream,
456 : : const gchar *string,
457 : : gssize length)
458 : : {
459 : : /* Is it nul-terminated? */
460 [ # # ]: 0 : if (length < 0)
461 : 0 : write_string (stream, string);
462 : 0 : else if (fwrite (string, 1, length, stream) < (size_t) length)
463 : : {
464 : : /* Something failed, but it's not an error we can handle at glib level
465 : : * so let's just continue without the compiler blaming us
466 : : */
467 : : }
468 : 0 : }
469 : :
470 : : static GLogDomain*
471 : 8328 : g_log_find_domain_L (const gchar *log_domain)
472 : : {
473 : : GLogDomain *domain;
474 : :
475 : 8328 : domain = g_log_domains;
476 [ + + ]: 8330 : while (domain)
477 : : {
478 [ + + ]: 5 : if (strcmp (domain->log_domain, log_domain) == 0)
479 : 3 : return domain;
480 : 2 : domain = domain->next;
481 : : }
482 : 8325 : return NULL;
483 : : }
484 : :
485 : : static GLogDomain*
486 : 6 : g_log_domain_new_L (const gchar *log_domain)
487 : : {
488 : : GLogDomain *domain;
489 : :
490 : 6 : domain = g_new (GLogDomain, 1);
491 : 6 : domain->log_domain = g_strdup (log_domain);
492 : 6 : domain->fatal_mask = G_LOG_FATAL_MASK;
493 : 6 : domain->handlers = NULL;
494 : :
495 : 6 : domain->next = g_log_domains;
496 : 6 : g_log_domains = domain;
497 : :
498 : 6 : return domain;
499 : : }
500 : :
501 : : static void
502 : 6 : g_log_domain_check_free_L (GLogDomain *domain)
503 : : {
504 [ + - ]: 6 : if (domain->fatal_mask == G_LOG_FATAL_MASK &&
505 [ + - ]: 6 : domain->handlers == NULL)
506 : : {
507 : : GLogDomain *last, *work;
508 : :
509 : 6 : last = NULL;
510 : :
511 : 6 : work = g_log_domains;
512 [ + - ]: 6 : while (work)
513 : : {
514 [ + - ]: 6 : if (work == domain)
515 : : {
516 [ - + ]: 6 : if (last)
517 : 0 : last->next = domain->next;
518 : : else
519 : 6 : g_log_domains = domain->next;
520 : 6 : g_free (domain->log_domain);
521 : 6 : g_free (domain);
522 : 6 : break;
523 : : }
524 : 0 : last = work;
525 : 0 : work = last->next;
526 : : }
527 : : }
528 : 6 : }
529 : :
530 : : static GLogFunc
531 : 8321 : g_log_domain_get_handler_L (GLogDomain *domain,
532 : : GLogLevelFlags log_level,
533 : : gpointer *data)
534 : : {
535 [ + + + - ]: 8321 : if (domain && log_level)
536 : : {
537 : : GLogHandler *handler;
538 : :
539 : 2 : handler = domain->handlers;
540 [ + + ]: 3 : while (handler)
541 : : {
542 [ + + ]: 2 : if ((handler->log_level & log_level) == log_level)
543 : : {
544 : 1 : *data = handler->data;
545 : 1 : return handler->log_func;
546 : : }
547 : 1 : handler = handler->next;
548 : : }
549 : : }
550 : :
551 : 8320 : *data = default_log_data;
552 : 8320 : return default_log_func;
553 : : }
554 : :
555 : : /**
556 : : * g_log_set_always_fatal:
557 : : * @fatal_mask: the mask containing bits set for each level of error which is
558 : : * to be fatal
559 : : *
560 : : * Sets the message levels which are always fatal, in any log domain.
561 : : *
562 : : * When a message with any of these levels is logged the program terminates.
563 : : * You can only set the levels defined by GLib to be fatal.
564 : : * [flags@GLib.LogLevelFlags.LEVEL_ERROR] is always fatal.
565 : : *
566 : : * You can also make some message levels fatal at runtime by setting
567 : : * the `G_DEBUG` environment variable (see
568 : : * [Running GLib Applications](glib-running.html)).
569 : : *
570 : : * Libraries should not call this function, as it affects all messages logged
571 : : * by a process, including those from other libraries.
572 : : *
573 : : * Structured log messages (using [func@GLib.log_structured] and
574 : : * [func@GLib.log_structured_array]) are fatal only if the default log writer is used;
575 : : * otherwise it is up to the writer function to determine which log messages
576 : : * are fatal. See [Using Structured Logging](logging.html#using-structured-logging).
577 : : *
578 : : * Returns: the old fatal mask
579 : : */
580 : : GLogLevelFlags
581 : 1319 : g_log_set_always_fatal (GLogLevelFlags fatal_mask)
582 : : {
583 : : GLogLevelFlags old_mask;
584 : :
585 : : /* restrict the global mask to levels that are known to glib
586 : : * since this setting applies to all domains
587 : : */
588 : 1319 : fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
589 : : /* force errors to be fatal */
590 : 1319 : fatal_mask |= G_LOG_LEVEL_ERROR;
591 : : /* remove bogus flag */
592 : 1319 : fatal_mask &= ~G_LOG_FLAG_FATAL;
593 : :
594 : 1319 : g_mutex_lock (&g_messages_lock);
595 : 1319 : old_mask = g_log_always_fatal;
596 : 1319 : g_log_always_fatal = fatal_mask;
597 : 1319 : g_mutex_unlock (&g_messages_lock);
598 : :
599 : 1319 : return old_mask;
600 : : }
601 : :
602 : : /**
603 : : * g_log_set_fatal_mask:
604 : : * @log_domain: the log domain
605 : : * @fatal_mask: the new fatal mask
606 : : *
607 : : * Sets the log levels which are fatal in the given domain.
608 : : *
609 : : * [flags@GLib.LogLevelFlags.LEVEL_ERROR] is always fatal.
610 : : *
611 : : * This has no effect on structured log messages (using [func@GLib.log_structured] or
612 : : * [func@GLib.log_structured_array]). To change the fatal behaviour for specific log
613 : : * messages, programs must install a custom log writer function using
614 : : * [func@GLib.log_set_writer_func]. See
615 : : * [Using Structured Logging](logging.html#using-structured-logging).
616 : : *
617 : : * This function is mostly intended to be used with
618 : : * [flags@GLib.LogLevelFlags.LEVEL_CRITICAL]. You should typically not set
619 : : * [flags@GLib.LogLevelFlags.LEVEL_WARNING], [flags@GLib.LogLevelFlags.LEVEL_MESSAGE], [flags@GLib.LogLevelFlags.LEVEL_INFO] or
620 : : * [flags@GLib.LogLevelFlags.LEVEL_DEBUG] as fatal except inside of test programs.
621 : : *
622 : : * Returns: the old fatal mask for the log domain
623 : : */
624 : : GLogLevelFlags
625 : 5 : g_log_set_fatal_mask (const gchar *log_domain,
626 : : GLogLevelFlags fatal_mask)
627 : : {
628 : : GLogLevelFlags old_flags;
629 : : GLogDomain *domain;
630 : :
631 [ - + ]: 5 : if (!log_domain)
632 : 0 : log_domain = "";
633 : :
634 : : /* force errors to be fatal */
635 : 5 : fatal_mask |= G_LOG_LEVEL_ERROR;
636 : : /* remove bogus flag */
637 : 5 : fatal_mask &= ~G_LOG_FLAG_FATAL;
638 : :
639 : 5 : g_mutex_lock (&g_messages_lock);
640 : :
641 : 5 : domain = g_log_find_domain_L (log_domain);
642 [ + - ]: 5 : if (!domain)
643 : 5 : domain = g_log_domain_new_L (log_domain);
644 : 5 : old_flags = domain->fatal_mask;
645 : :
646 : 5 : domain->fatal_mask = fatal_mask;
647 : 5 : g_log_domain_check_free_L (domain);
648 : :
649 : 5 : g_mutex_unlock (&g_messages_lock);
650 : :
651 : 5 : return old_flags;
652 : : }
653 : :
654 : : /**
655 : : * g_log_set_handler:
656 : : * @log_domain: (nullable): the log domain, or `NULL` for the default `""`
657 : : * application domain
658 : : * @log_levels: the log levels to apply the log handler for.
659 : : * To handle fatal and recursive messages as well, combine
660 : : * the log levels with the [flags@GLib.LogLevelFlags.FLAG_FATAL] and
661 : : * [flags@GLib.LogLevelFlags.FLAG_RECURSION] bit flags.
662 : : * @log_func: the log handler function
663 : : * @user_data: data passed to the log handler
664 : : *
665 : : * Sets the log handler for a domain and a set of log levels.
666 : : *
667 : : * To handle fatal and recursive messages the @log_levels parameter
668 : : * must be combined with the [flags@GLib.LogLevelFlags.FLAG_FATAL] and [flags@GLib.LogLevelFlags.FLAG_RECURSION]
669 : : * bit flags.
670 : : *
671 : : * Note that since the [flags@GLib.LogLevelFlags.LEVEL_ERROR] log level is always fatal, if
672 : : * you want to set a handler for this log level you must combine it with
673 : : * [flags@GLib.LogLevelFlags.FLAG_FATAL].
674 : : *
675 : : * This has no effect if structured logging is enabled; see
676 : : * [Using Structured Logging](logging.html#using-structured-logging).
677 : : *
678 : : * Here is an example for adding a log handler for all warning messages
679 : : * in the default domain:
680 : : *
681 : : * ```c
682 : : * g_log_set_handler (NULL, G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
683 : : * | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
684 : : * ```
685 : : *
686 : : * This example adds a log handler for all critical messages from GTK:
687 : : *
688 : : * ```c
689 : : * g_log_set_handler ("Gtk", G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL
690 : : * | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
691 : : * ```
692 : : *
693 : : * This example adds a log handler for all messages from GLib:
694 : : *
695 : : * ```c
696 : : * g_log_set_handler ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
697 : : * | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
698 : : * ```
699 : : *
700 : : * Returns: the id of the new handler
701 : : */
702 : : guint
703 : 1 : g_log_set_handler (const gchar *log_domain,
704 : : GLogLevelFlags log_levels,
705 : : GLogFunc log_func,
706 : : gpointer user_data)
707 : : {
708 : 1 : return g_log_set_handler_full (log_domain, log_levels, log_func, user_data, NULL);
709 : : }
710 : :
711 : : /**
712 : : * g_log_set_handler_full: (rename-to g_log_set_handler)
713 : : * @log_domain: (nullable): the log domain, or `NULL` for the default `""`
714 : : * application domain
715 : : * @log_levels: the log levels to apply the log handler for.
716 : : * To handle fatal and recursive messages as well, combine
717 : : * the log levels with the [flags@GLib.LogLevelFlags.FLAG_FATAL] and
718 : : * [flags@GLib.LogLevelFlags.FLAG_RECURSION] bit flags.
719 : : * @log_func: the log handler function
720 : : * @user_data: data passed to the log handler
721 : : * @destroy: destroy notify for @user_data, or `NULL`
722 : : *
723 : : * Like [func@GLib.log_set_handler], but takes a destroy notify for the @user_data.
724 : : *
725 : : * This has no effect if structured logging is enabled; see
726 : : * [Using Structured Logging](logging.html#using-structured-logging).
727 : : *
728 : : * Returns: the ID of the new handler
729 : : *
730 : : * Since: 2.46
731 : : */
732 : : guint
733 : 1 : g_log_set_handler_full (const gchar *log_domain,
734 : : GLogLevelFlags log_levels,
735 : : GLogFunc log_func,
736 : : gpointer user_data,
737 : : GDestroyNotify destroy)
738 : : {
739 : : static guint handler_id = 0;
740 : : GLogDomain *domain;
741 : : GLogHandler *handler;
742 : :
743 : 1 : g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
744 : 1 : g_return_val_if_fail (log_func != NULL, 0);
745 : :
746 [ - + ]: 1 : if (!log_domain)
747 : 0 : log_domain = "";
748 : :
749 : 1 : handler = g_new (GLogHandler, 1);
750 : :
751 : 1 : g_mutex_lock (&g_messages_lock);
752 : :
753 : 1 : domain = g_log_find_domain_L (log_domain);
754 [ + - ]: 1 : if (!domain)
755 : 1 : domain = g_log_domain_new_L (log_domain);
756 : :
757 : 1 : handler->id = ++handler_id;
758 : 1 : handler->log_level = log_levels;
759 : 1 : handler->log_func = log_func;
760 : 1 : handler->data = user_data;
761 : 1 : handler->destroy = destroy;
762 : 1 : handler->next = domain->handlers;
763 : 1 : domain->handlers = handler;
764 : :
765 : 1 : g_mutex_unlock (&g_messages_lock);
766 : :
767 : 1 : return handler_id;
768 : : }
769 : :
770 : : /**
771 : : * g_log_set_default_handler:
772 : : * @log_func: the log handler function
773 : : * @user_data: data passed to the log handler
774 : : *
775 : : * Installs a default log handler which is used if no
776 : : * log handler has been set for the particular log domain
777 : : * and log level combination.
778 : : *
779 : : * By default, GLib uses [func@GLib.log_default_handler] as default log handler.
780 : : *
781 : : * This has no effect if structured logging is enabled; see
782 : : * [Using Structured Logging](logging.html#using-structured-logging).
783 : : *
784 : : * Returns: the previous default log handler
785 : : *
786 : : * Since: 2.6
787 : : */
788 : : GLogFunc
789 : 644 : g_log_set_default_handler (GLogFunc log_func,
790 : : gpointer user_data)
791 : : {
792 : : GLogFunc old_log_func;
793 : :
794 : 644 : g_mutex_lock (&g_messages_lock);
795 : 644 : old_log_func = default_log_func;
796 : 644 : default_log_func = log_func;
797 : 644 : default_log_data = user_data;
798 : 644 : g_mutex_unlock (&g_messages_lock);
799 : :
800 : 644 : return old_log_func;
801 : : }
802 : :
803 : : /**
804 : : * g_test_log_set_fatal_handler:
805 : : * @log_func: the log handler function.
806 : : * @user_data: data passed to the log handler.
807 : : *
808 : : * Installs a non-error fatal log handler which can be
809 : : * used to decide whether log messages which are counted
810 : : * as fatal abort the program.
811 : : *
812 : : * The use case here is that you are running a test case
813 : : * that depends on particular libraries or circumstances
814 : : * and cannot prevent certain known critical or warning
815 : : * messages. So you install a handler that compares the
816 : : * domain and message to precisely not abort in such a case.
817 : : *
818 : : * Note that the handler is reset at the beginning of
819 : : * any test case, so you have to set it inside each test
820 : : * function which needs the special behavior.
821 : : *
822 : : * This handler has no effect on g_error messages.
823 : : *
824 : : * This handler also has no effect on structured log messages (using
825 : : * [func@GLib.log_structured] or [func@GLib.log_structured_array]). To change the fatal
826 : : * behaviour for specific log messages, programs must install a custom log
827 : : * writer function using [func@GLib.log_set_writer_func].See
828 : : * [Using Structured Logging](logging.html#using-structured-logging).
829 : : *
830 : : * Since: 2.22
831 : : **/
832 : : void
833 : 7022 : g_test_log_set_fatal_handler (GTestLogFatalFunc log_func,
834 : : gpointer user_data)
835 : : {
836 : 7022 : g_mutex_lock (&g_messages_lock);
837 : 7022 : fatal_log_func = log_func;
838 : 7022 : fatal_log_data = user_data;
839 : 7022 : g_mutex_unlock (&g_messages_lock);
840 : 7022 : }
841 : :
842 : : /**
843 : : * g_log_remove_handler:
844 : : * @log_domain: the log domain
845 : : * @handler_id: the ID of the handler, which was returned
846 : : * in [func@GLib.log_set_handler]
847 : : *
848 : : * Removes the log handler.
849 : : *
850 : : * This has no effect if structured logging is enabled; see
851 : : * [Using Structured Logging](logging.html#using-structured-logging).
852 : : */
853 : : void
854 : 1 : g_log_remove_handler (const gchar *log_domain,
855 : : guint handler_id)
856 : : {
857 : : GLogDomain *domain;
858 : :
859 : 1 : g_return_if_fail (handler_id > 0);
860 : :
861 [ - + ]: 1 : if (!log_domain)
862 : 0 : log_domain = "";
863 : :
864 : 1 : g_mutex_lock (&g_messages_lock);
865 : 1 : domain = g_log_find_domain_L (log_domain);
866 [ + - ]: 1 : if (domain)
867 : : {
868 : : GLogHandler *work, *last;
869 : :
870 : 1 : last = NULL;
871 : 1 : work = domain->handlers;
872 [ + - ]: 1 : while (work)
873 : : {
874 [ + - ]: 1 : if (work->id == handler_id)
875 : : {
876 [ - + ]: 1 : if (last)
877 : 0 : last->next = work->next;
878 : : else
879 : 1 : domain->handlers = work->next;
880 : 1 : g_log_domain_check_free_L (domain);
881 : 1 : g_mutex_unlock (&g_messages_lock);
882 [ - + ]: 1 : if (work->destroy)
883 : 0 : work->destroy (work->data);
884 : 1 : g_free (work);
885 : 1 : return;
886 : : }
887 : 0 : last = work;
888 : 0 : work = last->next;
889 : : }
890 : : }
891 : 0 : g_mutex_unlock (&g_messages_lock);
892 : 0 : g_warning ("%s: could not find handler with id '%d' for domain \"%s\"",
893 : : G_STRLOC, handler_id, log_domain);
894 : : }
895 : :
896 : : #define CHAR_IS_SAFE(wc) (!((wc < 0x20 && wc != '\t' && wc != '\n' && wc != '\r') || \
897 : : (wc == 0x7f) || \
898 : : (wc >= 0x80 && wc < 0xa0)))
899 : :
900 : : static gchar*
901 : 19600 : strdup_convert (const gchar *string,
902 : : const gchar *charset)
903 : : {
904 [ - + ]: 19600 : if (!g_utf8_validate (string, -1, NULL))
905 : : {
906 : 0 : GString *gstring = g_string_new ("[Invalid UTF-8] ");
907 : : guchar *p;
908 : :
909 [ # # ]: 0 : for (p = (guchar *)string; *p; p++)
910 : : {
911 [ # # # # : 0 : if (CHAR_IS_SAFE(*p) &&
# # # # #
# # # #
# ]
912 [ # # # # ]: 0 : !(*p == '\r' && *(p + 1) != '\n') &&
913 [ # # ]: 0 : *p < 0x80)
914 [ # # ]: 0 : g_string_append_c (gstring, *p);
915 : : else
916 : 0 : g_string_append_printf (gstring, "\\x%02x", (guint)(guchar)*p);
917 : : }
918 : :
919 : 0 : return g_string_free (gstring, FALSE);
920 : : }
921 : : else
922 : : {
923 : 19600 : GError *err = NULL;
924 : :
925 : 19600 : gchar *result = g_convert_with_fallback (string, -1, charset, "UTF-8", "?", NULL, NULL, &err);
926 [ + - ]: 19600 : if (result)
927 : 19600 : return result;
928 : : else
929 : : {
930 : : /* Not thread-safe, but doesn't matter if we print the warning twice
931 : : */
932 : : static gboolean warned = FALSE;
933 [ # # ]: 0 : if (!warned)
934 : : {
935 : 0 : warned = TRUE;
936 : 0 : _g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
937 : : }
938 : 0 : g_error_free (err);
939 : :
940 : 0 : return g_strdup (string);
941 : : }
942 : : }
943 : : }
944 : :
945 : : /* For a radix of 8 we need at most 3 output bytes for 1 input
946 : : * byte. Additionally we might need up to 2 output bytes for the
947 : : * readix prefix and 1 byte for the trailing NULL.
948 : : */
949 : : #define FORMAT_UNSIGNED_BUFSIZE ((GLIB_SIZEOF_LONG * 3) + 3)
950 : :
951 : : static void
952 : 1 : format_unsigned (gchar *buf,
953 : : gulong num,
954 : : guint radix)
955 : : {
956 : : gulong tmp;
957 : : gchar c;
958 : : gint i, n;
959 : :
960 : : /* we may not call _any_ GLib functions here (or macros like g_return_if_fail()) */
961 : :
962 [ + - + - : 1 : if (radix != 8 && radix != 10 && radix != 16)
- + ]
963 : : {
964 : 0 : *buf = '\000';
965 : 0 : return;
966 : : }
967 : :
968 [ - + ]: 1 : if (!num)
969 : : {
970 : 0 : *buf++ = '0';
971 : 0 : *buf = '\000';
972 : 0 : return;
973 : : }
974 : :
975 [ + - ]: 1 : if (radix == 16)
976 : : {
977 : 1 : *buf++ = '0';
978 : 1 : *buf++ = 'x';
979 : : }
980 [ # # ]: 0 : else if (radix == 8)
981 : : {
982 : 0 : *buf++ = '0';
983 : : }
984 : :
985 : 1 : n = 0;
986 : 1 : tmp = num;
987 [ + + ]: 4 : while (tmp)
988 : : {
989 : 3 : tmp /= radix;
990 : 3 : n++;
991 : : }
992 : :
993 : 1 : i = n;
994 : :
995 : : /* Again we can't use g_assert; actually this check should _never_ fail. */
996 [ - + ]: 1 : if (n > FORMAT_UNSIGNED_BUFSIZE - 3)
997 : : {
998 : 0 : *buf = '\000';
999 : 0 : return;
1000 : : }
1001 : :
1002 [ + + ]: 4 : while (num)
1003 : : {
1004 : 3 : i--;
1005 : 3 : c = (num % radix);
1006 [ + - ]: 3 : if (c < 10)
1007 : 3 : buf[i] = c + '0';
1008 : : else
1009 : 0 : buf[i] = c + 'a' - 10;
1010 : 3 : num /= radix;
1011 : : }
1012 : :
1013 : 1 : buf[n] = '\000';
1014 : : }
1015 : :
1016 : : /* string size big enough to hold level prefix */
1017 : : #define STRING_BUFFER_SIZE (FORMAT_UNSIGNED_BUFSIZE + 32)
1018 : :
1019 : : #define ALERT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)
1020 : :
1021 : : /* these are emitted by the default log handler */
1022 : : #define DEFAULT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE)
1023 : : /* these are filtered by G_MESSAGES_DEBUG by the default log handler */
1024 : : #define INFO_LEVELS (G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG)
1025 : :
1026 : : static const gchar *log_level_to_color (GLogLevelFlags log_level,
1027 : : gboolean use_color);
1028 : : static const gchar *color_reset (gboolean use_color);
1029 : :
1030 : : static gboolean gmessages_use_stderr = FALSE;
1031 : :
1032 : : /**
1033 : : * g_log_writer_default_set_use_stderr:
1034 : : * @use_stderr: If `TRUE`, use `stderr` for log messages that would
1035 : : * normally have appeared on `stdout`
1036 : : *
1037 : : * Configure whether the built-in log functions will output all log messages to
1038 : : * `stderr`.
1039 : : *
1040 : : * The built-in log functions are [func@GLib.log_default_handler] for the
1041 : : * old-style API, and both [func@GLib.log_writer_default] and
1042 : : * [func@GLib.log_writer_standard_streams] for the structured API.
1043 : : *
1044 : : * By default, log messages of levels [flags@GLib.LogLevelFlags.LEVEL_INFO] and
1045 : : * [flags@GLib.LogLevelFlags.LEVEL_DEBUG] are sent to `stdout`, and other log messages are
1046 : : * sent to `stderr`. This is problematic for applications that intend
1047 : : * to reserve `stdout` for structured output such as JSON or XML.
1048 : : *
1049 : : * This function sets global state. It is not thread-aware, and should be
1050 : : * called at the very start of a program, before creating any other threads
1051 : : * or creating objects that could create worker threads of their own.
1052 : : *
1053 : : * Since: 2.68
1054 : : */
1055 : : void
1056 : 105 : g_log_writer_default_set_use_stderr (gboolean use_stderr)
1057 : : {
1058 : 105 : g_return_if_fail (g_thread_n_created () == 0);
1059 : 105 : gmessages_use_stderr = use_stderr;
1060 : : }
1061 : :
1062 : : static FILE *
1063 : 198 : mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE],
1064 : : GLogLevelFlags log_level,
1065 : : gboolean use_color)
1066 : : {
1067 : : /* we may not call _any_ GLib functions here */
1068 : :
1069 : 198 : strcpy (level_prefix, log_level_to_color (log_level, use_color));
1070 : :
1071 [ - + + + : 198 : switch (log_level & G_LOG_LEVEL_MASK)
+ + + ]
1072 : : {
1073 : 0 : case G_LOG_LEVEL_ERROR:
1074 : 0 : strcat (level_prefix, "ERROR");
1075 : 0 : break;
1076 : 7 : case G_LOG_LEVEL_CRITICAL:
1077 : 7 : strcat (level_prefix, "CRITICAL");
1078 : 7 : break;
1079 : 4 : case G_LOG_LEVEL_WARNING:
1080 : 4 : strcat (level_prefix, "WARNING");
1081 : 4 : break;
1082 : 4 : case G_LOG_LEVEL_MESSAGE:
1083 : 4 : strcat (level_prefix, "Message");
1084 : 4 : break;
1085 : 1 : case G_LOG_LEVEL_INFO:
1086 : 1 : strcat (level_prefix, "INFO");
1087 : 1 : break;
1088 : 181 : case G_LOG_LEVEL_DEBUG:
1089 : 181 : strcat (level_prefix, "DEBUG");
1090 : 181 : break;
1091 : 1 : default:
1092 [ + - ]: 1 : if (log_level)
1093 : : {
1094 : 1 : strcat (level_prefix, "LOG-");
1095 : 1 : format_unsigned (level_prefix + 4, log_level & G_LOG_LEVEL_MASK, 16);
1096 : : }
1097 : : else
1098 : 0 : strcat (level_prefix, "LOG");
1099 : 1 : break;
1100 : : }
1101 : :
1102 : 198 : strcat (level_prefix, color_reset (use_color));
1103 : :
1104 [ - + ]: 198 : if (log_level & G_LOG_FLAG_RECURSION)
1105 : 0 : strcat (level_prefix, " (recursed)");
1106 [ + + ]: 198 : if (log_level & ALERT_LEVELS)
1107 : 11 : strcat (level_prefix, " **");
1108 : :
1109 : : #ifdef G_OS_WIN32
1110 : : if ((log_level & G_LOG_FLAG_FATAL) != 0 && !g_test_initialized ())
1111 : : win32_keep_fatal_message = TRUE;
1112 : : #endif
1113 : 198 : return log_level_to_file (log_level);
1114 : : }
1115 : :
1116 : : typedef struct {
1117 : : gchar *log_domain;
1118 : : GLogLevelFlags log_level;
1119 : : gchar *pattern;
1120 : : } GTestExpectedMessage;
1121 : :
1122 : : static GSList *expected_messages = NULL;
1123 : :
1124 : : /**
1125 : : * g_logv:
1126 : : * @log_domain: (nullable): the log domain, or `NULL` for the default `""`
1127 : : * application domain
1128 : : * @log_level: the log level
1129 : : * @format: the message format. See the `printf()` documentation
1130 : : * @args: the parameters to insert into the format string
1131 : : *
1132 : : * Logs an error or debugging message.
1133 : : *
1134 : : * If the log level has been set as fatal, [func@GLib.BREAKPOINT] is called
1135 : : * to terminate the program. See the documentation for [func@GLib.BREAKPOINT] for
1136 : : * details of the debugging options this provides.
1137 : : *
1138 : : * If [func@GLib.log_default_handler] is used as the log handler function, a new-line
1139 : : * character will automatically be appended to @..., and need not be entered
1140 : : * manually.
1141 : : *
1142 : : * If [structured logging is enabled](logging.html#using-structured-logging) this will
1143 : : * output via the structured log writer function (see [func@GLib.log_set_writer_func]).
1144 : : */
1145 : : void
1146 : 10846 : g_logv (const gchar *log_domain,
1147 : : GLogLevelFlags log_level,
1148 : : const gchar *format,
1149 : : va_list args)
1150 : : {
1151 : 10846 : gboolean was_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
1152 : 10846 : gboolean was_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
1153 : 10846 : char buffer[1025], *msg_alloc = NULL;
1154 : : const char *msg;
1155 : : gint i;
1156 : :
1157 : 10846 : log_level &= G_LOG_LEVEL_MASK;
1158 [ - + ]: 10846 : if (!log_level)
1159 : 2525 : return;
1160 : :
1161 [ - + ]: 10846 : if (log_level & G_LOG_FLAG_RECURSION)
1162 : : {
1163 : : /* we use a stack buffer of fixed size, since we're likely
1164 : : * in an out-of-memory situation
1165 : : */
1166 : : gsize size G_GNUC_UNUSED;
1167 : :
1168 : 0 : size = _g_vsnprintf (buffer, 1024, format, args);
1169 : 0 : msg = buffer;
1170 : : }
1171 : : else
1172 : : {
1173 : 10846 : msg = format_string (format, args, &msg_alloc);
1174 : : }
1175 : :
1176 [ + + ]: 10846 : if (expected_messages)
1177 : : {
1178 : 2526 : GTestExpectedMessage *expected = expected_messages->data;
1179 : :
1180 [ + - ]: 2526 : if (g_strcmp0 (expected->log_domain, log_domain) == 0 &&
1181 [ + + + - ]: 5051 : ((log_level & expected->log_level) == expected->log_level) &&
1182 : 2525 : g_pattern_match_simple (expected->pattern, msg))
1183 : : {
1184 : 2525 : expected_messages = g_slist_delete_link (expected_messages,
1185 : : expected_messages);
1186 : 2525 : g_free (expected->log_domain);
1187 : 2525 : g_free (expected->pattern);
1188 : 2525 : g_free (expected);
1189 : 2525 : g_free (msg_alloc);
1190 : 2525 : return;
1191 : : }
1192 [ - + ]: 1 : else if ((log_level & G_LOG_LEVEL_DEBUG) != G_LOG_LEVEL_DEBUG)
1193 : : {
1194 : : gchar level_prefix[STRING_BUFFER_SIZE];
1195 : : gchar *expected_message;
1196 : :
1197 : 0 : mklevel_prefix (level_prefix, expected->log_level, FALSE);
1198 : 0 : expected_message = g_strdup_printf ("Did not see expected message %s-%s: %s",
1199 [ # # ]: 0 : expected->log_domain ? expected->log_domain : "**",
1200 : : level_prefix, expected->pattern);
1201 : 0 : g_log_default_handler (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, expected_message, NULL);
1202 : 0 : g_free (expected_message);
1203 : :
1204 : 0 : log_level |= G_LOG_FLAG_FATAL;
1205 : : }
1206 : : }
1207 : :
1208 [ + + ]: 16642 : for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
1209 : : {
1210 : : GLogLevelFlags test_level;
1211 : :
1212 : 8321 : test_level = 1L << i;
1213 [ + - ]: 8321 : if (log_level & test_level)
1214 : : {
1215 : : GLogDomain *domain;
1216 : : GLogFunc log_func;
1217 : : GLogLevelFlags domain_fatal_mask;
1218 : 8321 : gpointer data = NULL;
1219 : 8321 : gboolean masquerade_fatal = FALSE;
1220 : : guint depth;
1221 : :
1222 [ - + ]: 8321 : if (was_fatal)
1223 : 0 : test_level |= G_LOG_FLAG_FATAL;
1224 [ - + ]: 8321 : if (was_recursion)
1225 : 0 : test_level |= G_LOG_FLAG_RECURSION;
1226 : :
1227 : : /* check recursion and lookup handler */
1228 : 8321 : g_mutex_lock (&g_messages_lock);
1229 : 8321 : depth = GPOINTER_TO_UINT (g_private_get (&g_log_depth));
1230 [ + + ]: 8321 : domain = g_log_find_domain_L (log_domain ? log_domain : "");
1231 [ - + ]: 8321 : if (depth)
1232 : 0 : test_level |= G_LOG_FLAG_RECURSION;
1233 : 8321 : depth++;
1234 [ + + ]: 8321 : domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK;
1235 [ + + ]: 8321 : if ((domain_fatal_mask | g_log_always_fatal) & test_level)
1236 : 3 : test_level |= G_LOG_FLAG_FATAL;
1237 [ - + ]: 8321 : if (test_level & G_LOG_FLAG_RECURSION)
1238 : 0 : log_func = _g_log_fallback_handler;
1239 : : else
1240 : 8321 : log_func = g_log_domain_get_handler_L (domain, test_level, &data);
1241 : 8321 : domain = NULL;
1242 : 8321 : g_mutex_unlock (&g_messages_lock);
1243 : :
1244 : 8321 : g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
1245 : :
1246 : 8321 : log_func (log_domain, test_level, msg, data);
1247 : :
1248 [ + + ]: 8321 : if ((test_level & G_LOG_FLAG_FATAL)
1249 [ + - ]: 3 : && !(test_level & G_LOG_LEVEL_ERROR))
1250 : : {
1251 : 3 : masquerade_fatal = fatal_log_func
1252 [ + - + - ]: 3 : && !fatal_log_func (log_domain, test_level, msg, fatal_log_data);
1253 : : }
1254 : :
1255 [ + + - + ]: 8321 : if ((test_level & G_LOG_FLAG_FATAL) && !masquerade_fatal)
1256 : : {
1257 : : /* MessageBox is allowed on UWP apps only when building against
1258 : : * the debug CRT, which will set -D_DEBUG */
1259 : : #if defined(G_OS_WIN32) && (defined(_DEBUG) || !defined(G_WINAPI_ONLY_APP))
1260 : : if (win32_keep_fatal_message)
1261 : : {
1262 : : WCHAR *wide_msg;
1263 : :
1264 : : wide_msg = g_utf8_to_utf16 (fatal_msg_buf, -1, NULL, NULL, NULL);
1265 : :
1266 : : MessageBoxW (NULL, wide_msg, NULL,
1267 : : MB_ICONERROR | MB_SETFOREGROUND);
1268 : :
1269 : : g_free (wide_msg);
1270 : : }
1271 : : #endif
1272 : :
1273 : 0 : _g_log_abort (!(test_level & G_LOG_FLAG_RECURSION));
1274 : : }
1275 : :
1276 : 8321 : depth--;
1277 : 8321 : g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
1278 : : }
1279 : : }
1280 : :
1281 : 8321 : g_free (msg_alloc);
1282 : : }
1283 : :
1284 : : /**
1285 : : * g_log:
1286 : : * @log_domain: (nullable): the log domain, usually `G_LOG_DOMAIN`, or `NULL`
1287 : : * for the default
1288 : : * @log_level: the log level, either from [type@GLib.LogLevelFlags]
1289 : : * or a user-defined level
1290 : : * @format: the message format. See the `printf()` documentation
1291 : : * @...: the parameters to insert into the format string
1292 : : *
1293 : : * Logs an error or debugging message.
1294 : : *
1295 : : * If the log level has been set as fatal, [func@GLib.BREAKPOINT] is called
1296 : : * to terminate the program. See the documentation for [func@GLib.BREAKPOINT] for
1297 : : * details of the debugging options this provides.
1298 : : *
1299 : : * If [func@GLib.log_default_handler] is used as the log handler function, a new-line
1300 : : * character will automatically be appended to @..., and need not be entered
1301 : : * manually.
1302 : : *
1303 : : * If [structured logging is enabled](logging.html#using-structured-logging) this will
1304 : : * output via the structured log writer function (see [func@GLib.log_set_writer_func]).
1305 : : */
1306 : : void
1307 : 10846 : g_log (const gchar *log_domain,
1308 : : GLogLevelFlags log_level,
1309 : : const gchar *format,
1310 : : ...)
1311 : : {
1312 : : va_list args;
1313 : :
1314 : 10846 : va_start (args, format);
1315 : 10846 : g_logv (log_domain, log_level, format, args);
1316 : 10846 : va_end (args);
1317 : 10846 : }
1318 : :
1319 : : /* Return value must be 1 byte long (plus nul byte).
1320 : : * Reference: http://man7.org/linux/man-pages/man3/syslog.3.html#DESCRIPTION
1321 : : */
1322 : : static const gchar *
1323 : 208 : log_level_to_priority (GLogLevelFlags log_level)
1324 : : {
1325 [ - + ]: 208 : if (log_level & G_LOG_LEVEL_ERROR)
1326 : 0 : return "3";
1327 [ + + ]: 208 : else if (log_level & G_LOG_LEVEL_CRITICAL)
1328 : 7 : return "4";
1329 [ + + ]: 201 : else if (log_level & G_LOG_LEVEL_WARNING)
1330 : 5 : return "4";
1331 [ + + ]: 196 : else if (log_level & G_LOG_LEVEL_MESSAGE)
1332 : 11 : return "5";
1333 [ + + ]: 185 : else if (log_level & G_LOG_LEVEL_INFO)
1334 : 3 : return "6";
1335 [ + + ]: 182 : else if (log_level & G_LOG_LEVEL_DEBUG)
1336 : 181 : return "7";
1337 : :
1338 : : /* Default to LOG_NOTICE for custom log levels. */
1339 : 1 : return "5";
1340 : : }
1341 : :
1342 : : #ifdef HAVE_SYSLOG_H
1343 : : static int
1344 : 0 : str_to_syslog_facility (const gchar *syslog_facility_str)
1345 : : {
1346 : 0 : int syslog_facility = LOG_USER;
1347 : :
1348 [ # # ]: 0 : if (g_strcmp0 (syslog_facility_str, "auth") == 0)
1349 : : {
1350 : 0 : syslog_facility = LOG_AUTH;
1351 : : }
1352 [ # # ]: 0 : else if (g_strcmp0 (syslog_facility_str, "daemon") == 0)
1353 : : {
1354 : 0 : syslog_facility = LOG_DAEMON;
1355 : : }
1356 : :
1357 : 0 : return syslog_facility;
1358 : : }
1359 : : #endif
1360 : :
1361 : : static inline FILE *
1362 : 396 : log_level_to_file (GLogLevelFlags log_level)
1363 : : {
1364 [ + + ]: 396 : if (gmessages_use_stderr)
1365 : 30 : return stderr;
1366 : :
1367 [ + + ]: 366 : if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL |
1368 : : G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE))
1369 : 28 : return stderr;
1370 : : else
1371 : 338 : return stdout;
1372 : : }
1373 : :
1374 : : static const gchar *
1375 : 198 : log_level_to_color (GLogLevelFlags log_level,
1376 : : gboolean use_color)
1377 : : {
1378 : : /* we may not call _any_ GLib functions here */
1379 : :
1380 [ + - ]: 198 : if (!use_color)
1381 : 198 : return "";
1382 : :
1383 [ # # ]: 0 : if (log_level & G_LOG_LEVEL_ERROR)
1384 : 0 : return "\033[1;31m"; /* red */
1385 [ # # ]: 0 : else if (log_level & G_LOG_LEVEL_CRITICAL)
1386 : 0 : return "\033[1;35m"; /* magenta */
1387 [ # # ]: 0 : else if (log_level & G_LOG_LEVEL_WARNING)
1388 : 0 : return "\033[1;33m"; /* yellow */
1389 [ # # ]: 0 : else if (log_level & G_LOG_LEVEL_MESSAGE)
1390 : 0 : return "\033[1;32m"; /* green */
1391 [ # # ]: 0 : else if (log_level & G_LOG_LEVEL_INFO)
1392 : 0 : return "\033[1;32m"; /* green */
1393 [ # # ]: 0 : else if (log_level & G_LOG_LEVEL_DEBUG)
1394 : 0 : return "\033[1;32m"; /* green */
1395 : :
1396 : : /* No color for custom log levels. */
1397 : 0 : return "";
1398 : : }
1399 : :
1400 : : static const gchar *
1401 : 396 : color_reset (gboolean use_color)
1402 : : {
1403 : : /* we may not call _any_ GLib functions here */
1404 : :
1405 [ + - ]: 396 : if (!use_color)
1406 : 396 : return "";
1407 : :
1408 : 0 : return "\033[0m";
1409 : : }
1410 : :
1411 : : #ifdef G_OS_WIN32
1412 : :
1413 : : /* We might be using tty emulators such as mintty, so try to detect it, if we passed in a valid FD
1414 : : * so we need to check the name of the pipe if _isatty (fd) == 0
1415 : : */
1416 : :
1417 : : static gboolean
1418 : : win32_is_pipe_tty (int fd)
1419 : : {
1420 : : gboolean result = FALSE;
1421 : : HANDLE h_fd;
1422 : : FILE_NAME_INFO *info = NULL;
1423 : : gint info_size = sizeof (FILE_NAME_INFO) + sizeof (WCHAR) * MAX_PATH;
1424 : : wchar_t *name = NULL;
1425 : : gint length;
1426 : :
1427 : : h_fd = (HANDLE) _get_osfhandle (fd);
1428 : :
1429 : : if (h_fd == INVALID_HANDLE_VALUE || GetFileType (h_fd) != FILE_TYPE_PIPE)
1430 : : goto done_query;
1431 : :
1432 : : /* mintty uses a pipe, in the form of \{cygwin|msys}-xxxxxxxxxxxxxxxx-ptyN-{from|to}-master */
1433 : :
1434 : : info = g_try_malloc (info_size);
1435 : :
1436 : : if (info == NULL ||
1437 : : !GetFileInformationByHandleEx (h_fd, FileNameInfo, info, info_size))
1438 : : goto done_query;
1439 : :
1440 : : info->FileName[info->FileNameLength / sizeof (WCHAR)] = L'\0';
1441 : : name = info->FileName;
1442 : :
1443 : : length = wcslen (L"\\cygwin-");
1444 : : if (wcsncmp (name, L"\\cygwin-", length))
1445 : : {
1446 : : length = wcslen (L"\\msys-");
1447 : : if (wcsncmp (name, L"\\msys-", length))
1448 : : goto done_query;
1449 : : }
1450 : :
1451 : : name += length;
1452 : : length = wcsspn (name, L"0123456789abcdefABCDEF");
1453 : : if (length != 16)
1454 : : goto done_query;
1455 : :
1456 : : name += length;
1457 : : length = wcslen (L"-pty");
1458 : : if (wcsncmp (name, L"-pty", length))
1459 : : goto done_query;
1460 : :
1461 : : name += length;
1462 : : length = wcsspn (name, L"0123456789");
1463 : : if (length != 1)
1464 : : goto done_query;
1465 : :
1466 : : name += length;
1467 : : length = wcslen (L"-to-master");
1468 : : if (wcsncmp (name, L"-to-master", length))
1469 : : {
1470 : : length = wcslen (L"-from-master");
1471 : : if (wcsncmp (name, L"-from-master", length))
1472 : : goto done_query;
1473 : : }
1474 : :
1475 : : result = TRUE;
1476 : :
1477 : : done_query:
1478 : : if (info != NULL)
1479 : : g_free (info);
1480 : :
1481 : : return result;
1482 : : }
1483 : : #endif
1484 : :
1485 : : #pragma GCC diagnostic push
1486 : : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1487 : :
1488 : : /**
1489 : : * g_log_structured:
1490 : : * @log_domain: log domain, usually `G_LOG_DOMAIN`
1491 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
1492 : : * level
1493 : : * @...: key-value pairs of structured data to add to the log entry, followed
1494 : : * by the key `MESSAGE`, followed by a `printf()`-style message format,
1495 : : * followed by parameters to insert in the format string
1496 : : *
1497 : : * Log a message with structured data.
1498 : : *
1499 : : * The message will be passed through to the log writer set by the application
1500 : : * using [func@GLib.log_set_writer_func]. If the message is fatal (i.e. its log level
1501 : : * is [flags@GLib.LogLevelFlags.LEVEL_ERROR]), the program will be aborted by calling
1502 : : * [func@GLib.BREAKPOINT] at the end of this function. If the log writer returns
1503 : : * [enum@GLib.LogWriterOutput.UNHANDLED] (failure), no other fallback writers will be tried.
1504 : : * See the documentation for [type@GLib.LogWriterFunc] for information on chaining
1505 : : * writers.
1506 : : *
1507 : : * The structured data is provided as key–value pairs, where keys are UTF-8
1508 : : * strings, and values are arbitrary pointers — typically pointing to UTF-8
1509 : : * strings, but that is not a requirement. To pass binary (non-nul-terminated)
1510 : : * structured data, use [func@GLib.log_structured_array]. The keys for structured data
1511 : : * should follow the [systemd journal
1512 : : * fields](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
1513 : : * specification. It is suggested that custom keys are namespaced according to
1514 : : * the code which sets them. For example, custom keys from GLib all have a
1515 : : * `GLIB_` prefix.
1516 : : *
1517 : : * Note that keys that expect UTF-8 strings (specifically `"MESSAGE"` and
1518 : : * `"GLIB_DOMAIN"`) must be passed as nul-terminated UTF-8 strings until GLib
1519 : : * version 2.74.1 because the default log handler did not consider the length of
1520 : : * the `GLogField`. Starting with GLib 2.74.1 this is fixed and
1521 : : * non-nul-terminated UTF-8 strings can be passed with their correct length.
1522 : : *
1523 : : * The @log_domain will be converted into a `GLIB_DOMAIN` field. @log_level will
1524 : : * be converted into a
1525 : : * [`PRIORITY`](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#PRIORITY=)
1526 : : * field. The format string will have its placeholders substituted for the provided
1527 : : * values and be converted into a
1528 : : * [`MESSAGE`](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#MESSAGE=)
1529 : : * field.
1530 : : *
1531 : : * Other fields you may commonly want to pass into this function:
1532 : : *
1533 : : * * [`MESSAGE_ID`](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#MESSAGE_ID=)
1534 : : * * [`CODE_FILE`](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#CODE_FILE=)
1535 : : * * [`CODE_LINE`](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#CODE_LINE=)
1536 : : * * [`CODE_FUNC`](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#CODE_FUNC=)
1537 : : * * [`ERRNO`](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#ERRNO=)
1538 : : *
1539 : : * Note that `CODE_FILE`, `CODE_LINE` and `CODE_FUNC` are automatically set by
1540 : : * the logging macros, [func@GLib.DEBUG_HERE], [func@GLib.message], [func@GLib.warning], [func@GLib.critical],
1541 : : * [func@GLib.error], etc, if the symbol `G_LOG_USE_STRUCTURED` is defined before including
1542 : : * `glib.h`.
1543 : : *
1544 : : * For example:
1545 : : *
1546 : : * ```c
1547 : : * g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
1548 : : * "MESSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e",
1549 : : * "MY_APPLICATION_CUSTOM_FIELD", "some debug string",
1550 : : * "MESSAGE", "This is a debug message about pointer %p and integer %u.",
1551 : : * some_pointer, some_integer);
1552 : : * ```
1553 : : *
1554 : : * Note that each `MESSAGE_ID` must be [uniquely and randomly
1555 : : * generated](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#MESSAGE_ID=).
1556 : : * If adding a `MESSAGE_ID`, consider shipping a [message
1557 : : * catalog](https://www.freedesktop.org/wiki/Software/systemd/catalog/) with
1558 : : * your software.
1559 : : *
1560 : : * To pass a user data pointer to the log writer function which is specific to
1561 : : * this logging call, you must use [func@GLib.log_structured_array] and pass the pointer
1562 : : * as a field with `GLogField.length` set to zero, otherwise it will be
1563 : : * interpreted as a string.
1564 : : *
1565 : : * For example:
1566 : : *
1567 : : * ```c
1568 : : * const GLogField fields[] = {
1569 : : * { "MESSAGE", "This is a debug message.", -1 },
1570 : : * { "MESSAGE_ID", "fcfb2e1e65c3494386b74878f1abf893", -1 },
1571 : : * { "MY_APPLICATION_CUSTOM_FIELD", "some debug string", -1 },
1572 : : * { "MY_APPLICATION_STATE", state_object, 0 },
1573 : : * };
1574 : : * g_log_structured_array (G_LOG_LEVEL_DEBUG, fields, G_N_ELEMENTS (fields));
1575 : : * ```
1576 : : *
1577 : : * Note also that, even if no other structured fields are specified, there
1578 : : * must always be a `MESSAGE` key before the format string. The `MESSAGE`-format
1579 : : * pair has to be the last of the key-value pairs, and `MESSAGE` is the only
1580 : : * field for which `printf()`-style formatting is supported.
1581 : : *
1582 : : * The default writer function for `stdout` and `stderr` will automatically
1583 : : * append a new-line character after the message, so you should not add one
1584 : : * manually to the format string.
1585 : : *
1586 : : * Since: 2.50
1587 : : */
1588 : : void
1589 : 5 : g_log_structured (const gchar *log_domain,
1590 : : GLogLevelFlags log_level,
1591 : : ...)
1592 : : {
1593 : : va_list args;
1594 : 5 : gchar buffer[1025], *message_allocated = NULL;
1595 : : const char *format;
1596 : : const gchar *message;
1597 : : gpointer p;
1598 : : gsize n_fields, i;
1599 : : GLogField stack_fields[16];
1600 : 5 : GLogField *fields = stack_fields;
1601 : 5 : GLogField *fields_allocated = NULL;
1602 : 5 : GArray *array = NULL;
1603 : :
1604 : 5 : va_start (args, log_level);
1605 : :
1606 : : /* MESSAGE and PRIORITY are a given */
1607 : 5 : n_fields = 2;
1608 : :
1609 [ + + ]: 5 : if (log_domain)
1610 : 4 : n_fields++;
1611 : :
1612 : 5 : for (p = va_arg (args, gchar *), i = n_fields;
1613 [ + + ]: 11 : strcmp (p, "MESSAGE") != 0;
1614 : 6 : p = va_arg (args, gchar *), i++)
1615 : : {
1616 : : GLogField field;
1617 : 6 : const gchar *key = p;
1618 : 6 : gconstpointer value = va_arg (args, gpointer);
1619 : :
1620 : 6 : field.key = key;
1621 : 6 : field.value = value;
1622 : 6 : field.length = -1;
1623 : :
1624 [ + - ]: 6 : if (i < 16)
1625 : 6 : stack_fields[i] = field;
1626 : : else
1627 : : {
1628 : : /* Don't allow dynamic allocation, since we're likely
1629 : : * in an out-of-memory situation. For lack of a better solution,
1630 : : * just ignore further key-value pairs.
1631 : : */
1632 [ # # ]: 0 : if (log_level & G_LOG_FLAG_RECURSION)
1633 : 0 : continue;
1634 : :
1635 [ # # ]: 0 : if (i == 16)
1636 : : {
1637 : 0 : array = g_array_sized_new (FALSE, FALSE, sizeof (GLogField), 32);
1638 : 0 : g_array_append_vals (array, stack_fields, 16);
1639 : : }
1640 : :
1641 : 0 : g_array_append_val (array, field);
1642 : : }
1643 : : }
1644 : :
1645 : 5 : n_fields = i;
1646 : :
1647 [ - + ]: 5 : if (array)
1648 : 0 : fields = fields_allocated = (GLogField *) g_array_free (array, FALSE);
1649 : :
1650 : 5 : format = va_arg (args, gchar *);
1651 : :
1652 [ - + ]: 5 : if (log_level & G_LOG_FLAG_RECURSION)
1653 : : {
1654 : : /* we use a stack buffer of fixed size, since we're likely
1655 : : * in an out-of-memory situation
1656 : : */
1657 : : gsize size G_GNUC_UNUSED;
1658 : :
1659 : 0 : size = _g_vsnprintf (buffer, sizeof (buffer), format, args);
1660 : 0 : message = buffer;
1661 : : }
1662 : : else
1663 : : {
1664 : 5 : message = format_string (format, args, &message_allocated);
1665 : : }
1666 : :
1667 : : /* Add MESSAGE, PRIORITY and GLIB_DOMAIN. */
1668 : 5 : fields[0].key = "MESSAGE";
1669 : 5 : fields[0].value = message;
1670 : 5 : fields[0].length = -1;
1671 : :
1672 : 5 : fields[1].key = "PRIORITY";
1673 : 5 : fields[1].value = log_level_to_priority (log_level);
1674 : 5 : fields[1].length = -1;
1675 : :
1676 [ + + ]: 5 : if (log_domain)
1677 : : {
1678 : 4 : fields[2].key = "GLIB_DOMAIN";
1679 : 4 : fields[2].value = log_domain;
1680 : 4 : fields[2].length = -1;
1681 : : }
1682 : :
1683 : : /* Log it. */
1684 : 5 : g_log_structured_array (log_level, fields, n_fields);
1685 : :
1686 : 5 : g_free (fields_allocated);
1687 : 5 : g_free (message_allocated);
1688 : :
1689 : 5 : va_end (args);
1690 : 5 : }
1691 : :
1692 : : /**
1693 : : * g_log_variant:
1694 : : * @log_domain: (nullable): log domain, usually `G_LOG_DOMAIN`
1695 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
1696 : : * level
1697 : : * @fields: a dictionary ([type@GLib.Variant] of the type `G_VARIANT_TYPE_VARDICT`)
1698 : : * containing the key-value pairs of message data.
1699 : : *
1700 : : * Log a message with structured data, accepting the data within a [type@GLib.Variant].
1701 : : *
1702 : : * This version is especially useful for use in other languages, via introspection.
1703 : : *
1704 : : * The only mandatory item in the @fields dictionary is the `"MESSAGE"` which must
1705 : : * contain the text shown to the user.
1706 : : *
1707 : : * The values in the @fields dictionary are likely to be of type `G_VARIANT_TYPE_STRING`.
1708 : : * Array of bytes (`G_VARIANT_TYPE_BYTESTRING`) is also
1709 : : * supported. In this case the message is handled as binary and will be forwarded
1710 : : * to the log writer as such. The size of the array should not be higher than
1711 : : * `G_MAXSSIZE`. Otherwise it will be truncated to this size. For other types
1712 : : * [method@GLib.Variant.print] will be used to convert the value into a string.
1713 : : *
1714 : : * For more details on its usage and about the parameters, see [func@GLib.log_structured].
1715 : : *
1716 : : * Since: 2.50
1717 : : */
1718 : : void
1719 : 2 : g_log_variant (const gchar *log_domain,
1720 : : GLogLevelFlags log_level,
1721 : : GVariant *fields)
1722 : : {
1723 : : GVariantIter iter;
1724 : : GVariant *value;
1725 : : gchar *key;
1726 : : GArray *fields_array;
1727 : : GLogField field;
1728 : : GSList *values_list, *print_list;
1729 : :
1730 : 2 : g_return_if_fail (g_variant_is_of_type (fields, G_VARIANT_TYPE_VARDICT));
1731 : :
1732 : 2 : values_list = print_list = NULL;
1733 : 2 : fields_array = g_array_new (FALSE, FALSE, sizeof (GLogField));
1734 : :
1735 : 2 : field.key = "PRIORITY";
1736 : 2 : field.value = log_level_to_priority (log_level);
1737 : 2 : field.length = -1;
1738 : 2 : g_array_append_val (fields_array, field);
1739 : :
1740 [ + - ]: 2 : if (log_domain)
1741 : : {
1742 : 2 : field.key = "GLIB_DOMAIN";
1743 : 2 : field.value = log_domain;
1744 : 2 : field.length = -1;
1745 : 2 : g_array_append_val (fields_array, field);
1746 : : }
1747 : :
1748 : 2 : g_variant_iter_init (&iter, fields);
1749 [ + + ]: 10 : while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
1750 : : {
1751 : 8 : gboolean defer_unref = TRUE;
1752 : :
1753 : 8 : field.key = key;
1754 : 8 : field.length = -1;
1755 : :
1756 [ + + ]: 8 : if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
1757 : : {
1758 : 6 : field.value = g_variant_get_string (value, NULL);
1759 : : }
1760 [ + - ]: 2 : else if (g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING))
1761 : : {
1762 : : gsize s;
1763 : 2 : field.value = g_variant_get_fixed_array (value, &s, sizeof (guchar));
1764 [ + - ]: 2 : if (G_LIKELY (s <= G_MAXSSIZE))
1765 : : {
1766 : 2 : field.length = s;
1767 : : }
1768 : : else
1769 : : {
1770 : 0 : _g_fprintf (stderr,
1771 : : "Byte array too large (%" G_GSIZE_FORMAT " bytes)"
1772 : : " passed to g_log_variant(). Truncating to " G_STRINGIFY (G_MAXSSIZE)
1773 : : " bytes.", s);
1774 : 0 : field.length = G_MAXSSIZE;
1775 : : }
1776 : : }
1777 : : else
1778 : : {
1779 : 0 : char *s = g_variant_print (value, FALSE);
1780 : 0 : field.value = s;
1781 : 0 : print_list = g_slist_prepend (print_list, s);
1782 : 0 : defer_unref = FALSE;
1783 : : }
1784 : :
1785 : 8 : g_array_append_val (fields_array, field);
1786 : :
1787 [ + - ]: 8 : if (G_LIKELY (defer_unref))
1788 : 8 : values_list = g_slist_prepend (values_list, value);
1789 : : else
1790 : 0 : g_variant_unref (value);
1791 : : }
1792 : :
1793 : : /* Log it. */
1794 : 2 : g_log_structured_array (log_level, (GLogField *) fields_array->data, fields_array->len);
1795 : :
1796 : 2 : g_array_free (fields_array, TRUE);
1797 : 2 : g_slist_free_full (values_list, (GDestroyNotify) g_variant_unref);
1798 : 2 : g_slist_free_full (print_list, g_free);
1799 : : }
1800 : :
1801 : :
1802 : : #pragma GCC diagnostic pop
1803 : :
1804 : : static GLogWriterOutput _g_log_writer_fallback (GLogLevelFlags log_level,
1805 : : const GLogField *fields,
1806 : : gsize n_fields,
1807 : : gpointer user_data);
1808 : :
1809 : : /**
1810 : : * g_log_structured_array:
1811 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
1812 : : * level
1813 : : * @fields: (array length=n_fields): key–value pairs of structured data to add
1814 : : * to the log message
1815 : : * @n_fields: number of elements in the @fields array
1816 : : *
1817 : : * Log a message with structured data.
1818 : : *
1819 : : * The message will be passed through to the log writer set by the application
1820 : : * using [func@GLib.log_set_writer_func]. If the
1821 : : * message is fatal (i.e. its log level is [flags@GLib.LogLevelFlags.LEVEL_ERROR]), the program will
1822 : : * be aborted at the end of this function.
1823 : : *
1824 : : * See [func@GLib.log_structured] for more documentation.
1825 : : *
1826 : : * This assumes that @log_level is already present in @fields (typically as the
1827 : : * `PRIORITY` field).
1828 : : *
1829 : : * Since: 2.50
1830 : : */
1831 : : void
1832 : 209 : g_log_structured_array (GLogLevelFlags log_level,
1833 : : const GLogField *fields,
1834 : : gsize n_fields)
1835 : : {
1836 : : GLogWriterFunc writer_func;
1837 : : gpointer writer_user_data;
1838 : : gboolean recursion;
1839 : : guint depth;
1840 : :
1841 [ - + ]: 209 : if (n_fields == 0)
1842 : 0 : return;
1843 : :
1844 : : /* Check for recursion and look up the writer function. */
1845 : 209 : depth = GPOINTER_TO_UINT (g_private_get (&g_log_structured_depth));
1846 : 209 : recursion = (depth > 0);
1847 : :
1848 : 209 : g_mutex_lock (&g_messages_lock);
1849 : :
1850 [ + - ]: 209 : writer_func = recursion ? _g_log_writer_fallback : log_writer_func;
1851 : 209 : writer_user_data = log_writer_user_data;
1852 : :
1853 : 209 : g_mutex_unlock (&g_messages_lock);
1854 : :
1855 : : /* Write the log entry. */
1856 : 209 : g_private_set (&g_log_structured_depth, GUINT_TO_POINTER (++depth));
1857 : :
1858 : 209 : g_assert (writer_func != NULL);
1859 : 209 : writer_func (log_level, fields, n_fields, writer_user_data);
1860 : :
1861 : 209 : g_private_set (&g_log_structured_depth, GUINT_TO_POINTER (--depth));
1862 : :
1863 : : /* Abort if the message was fatal. */
1864 [ - + ]: 209 : if (log_level & G_LOG_FATAL_MASK)
1865 : 0 : _g_log_abort (!(log_level & G_LOG_FLAG_RECURSION));
1866 : : }
1867 : :
1868 : : /* Semi-private helper function to implement the g_message() (etc.) macros
1869 : : * with support for G_GNUC_PRINTF so that @message_format can be checked
1870 : : * with -Wformat. */
1871 : : void
1872 : 2 : g_log_structured_standard (const gchar *log_domain,
1873 : : GLogLevelFlags log_level,
1874 : : const gchar *file,
1875 : : const gchar *line,
1876 : : const gchar *func,
1877 : : const gchar *message_format,
1878 : : ...)
1879 : : {
1880 : 4 : GLogField fields[] =
1881 : : {
1882 : 2 : { "PRIORITY", log_level_to_priority (log_level), -1 },
1883 : : { "CODE_FILE", file, -1 },
1884 : : { "CODE_LINE", line, -1 },
1885 : : { "CODE_FUNC", func, -1 },
1886 : : /* Filled in later: */
1887 : : { "MESSAGE", NULL, -1 },
1888 : : /* If @log_domain is %NULL, we will not pass this field: */
1889 : : { "GLIB_DOMAIN", log_domain, -1 },
1890 : : };
1891 : : gsize n_fields;
1892 : 2 : gchar *message_allocated = NULL;
1893 : : gchar buffer[1025];
1894 : : va_list args;
1895 : :
1896 : 2 : va_start (args, message_format);
1897 : :
1898 [ - + ]: 2 : if (log_level & G_LOG_FLAG_RECURSION)
1899 : : {
1900 : : /* we use a stack buffer of fixed size, since we're likely
1901 : : * in an out-of-memory situation
1902 : : */
1903 : : gsize size G_GNUC_UNUSED;
1904 : :
1905 : 0 : size = _g_vsnprintf (buffer, sizeof (buffer), message_format, args);
1906 : 0 : fields[4].value = buffer;
1907 : : }
1908 : : else
1909 : : {
1910 : 2 : fields[4].value = format_string (message_format, args, &message_allocated);
1911 : : }
1912 : :
1913 : 2 : va_end (args);
1914 : :
1915 [ - + ]: 2 : n_fields = G_N_ELEMENTS (fields) - ((log_domain == NULL) ? 1 : 0);
1916 : 2 : g_log_structured_array (log_level, fields, n_fields);
1917 : :
1918 : 2 : g_free (message_allocated);
1919 : 2 : }
1920 : :
1921 : : /**
1922 : : * g_log_set_writer_func:
1923 : : * @func: log writer function, which must not be `NULL`
1924 : : * @user_data: (closure func): user data to pass to @func
1925 : : * @user_data_free: (destroy func): function to free @user_data once it’s
1926 : : * finished with, if non-`NULL`
1927 : : *
1928 : : * Set a writer function which will be called to format and write out each log
1929 : : * message.
1930 : : *
1931 : : * Each program should set a writer function, or the default writer
1932 : : * ([func@GLib.log_writer_default]) will be used.
1933 : : *
1934 : : * Libraries **must not** call this function — only programs are allowed to
1935 : : * install a writer function, as there must be a single, central point where
1936 : : * log messages are formatted and outputted.
1937 : : *
1938 : : * There can only be one writer function. It is an error to set more than one.
1939 : : *
1940 : : * Since: 2.50
1941 : : */
1942 : : void
1943 : 9 : g_log_set_writer_func (GLogWriterFunc func,
1944 : : gpointer user_data,
1945 : : GDestroyNotify user_data_free)
1946 : : {
1947 : 9 : g_return_if_fail (func != NULL);
1948 : :
1949 : 9 : g_mutex_lock (&g_messages_lock);
1950 : :
1951 [ - + ]: 9 : if (log_writer_func != g_log_writer_default)
1952 : : {
1953 : 0 : g_mutex_unlock (&g_messages_lock);
1954 : 0 : g_error ("g_log_set_writer_func() called multiple times");
1955 : : return;
1956 : : }
1957 : :
1958 : 9 : log_writer_func = func;
1959 : 9 : log_writer_user_data = user_data;
1960 : 9 : log_writer_user_data_free = user_data_free;
1961 : :
1962 : 9 : g_mutex_unlock (&g_messages_lock);
1963 : : }
1964 : :
1965 : : /**
1966 : : * g_log_writer_supports_color:
1967 : : * @output_fd: output file descriptor to check
1968 : : *
1969 : : * Check whether the given @output_fd file descriptor supports
1970 : : * [ANSI color escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code).
1971 : : *
1972 : : * If so, they can safely be used when formatting log messages.
1973 : : *
1974 : : * Returns: `TRUE` if ANSI color escapes are supported, `FALSE` otherwise
1975 : : * Since: 2.50
1976 : : */
1977 : : gboolean
1978 : 198 : g_log_writer_supports_color (gint output_fd)
1979 : : {
1980 : : #ifdef G_OS_WIN32
1981 : : gboolean result = FALSE;
1982 : : GWin32InvalidParameterHandler handler;
1983 : : #endif
1984 : :
1985 : 198 : g_return_val_if_fail (output_fd >= 0, FALSE);
1986 : :
1987 : : /* FIXME: This check could easily be expanded in future to be more robust
1988 : : * against different types of terminal, which still vary in their color
1989 : : * support. cmd.exe on Windows, for example, supports ANSI colors only
1990 : : * from Windows 10 onwards; bash on Windows has always supported ANSI colors.
1991 : : * The Windows 10 color support is supported on:
1992 : : * -Output in the cmd.exe, MSYS/Cygwin standard consoles.
1993 : : * -Output in the cmd.exe, MSYS/Cygwin piped to the less program.
1994 : : * but not:
1995 : : * -Output in Cygwin via mintty (https://github.com/mintty/mintty/issues/482)
1996 : : * -Color code output when output redirected to file (i.e. program 2> some.txt)
1997 : : *
1998 : : * On UNIX systems, we probably want to use the functions from terminfo to
1999 : : * work out whether colors are supported.
2000 : : *
2001 : : * Some examples:
2002 : : * - https://github.com/chalk/supports-color/blob/9434c93918301a6b47faa01999482adfbf1b715c/index.js#L61
2003 : : * - http://stackoverflow.com/questions/16755142/how-to-make-win32-console-recognize-ansi-vt100-escape-sequences
2004 : : * - http://blog.mmediasys.com/2010/11/24/we-all-love-colors/
2005 : : * - http://unix.stackexchange.com/questions/198794/where-does-the-term-environment-variable-default-get-set
2006 : : */
2007 : : #ifdef G_OS_WIN32
2008 : :
2009 : : g_win32_push_empty_invalid_parameter_handler (&handler);
2010 : :
2011 : : if (g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_ANY))
2012 : : {
2013 : : HANDLE h_output;
2014 : : DWORD dw_mode;
2015 : :
2016 : : if (_isatty (output_fd))
2017 : : {
2018 : : h_output = (HANDLE) _get_osfhandle (output_fd);
2019 : :
2020 : : if (!GetConsoleMode (h_output, &dw_mode))
2021 : : goto reset_invalid_param_handler;
2022 : :
2023 : : if (dw_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
2024 : : result = TRUE;
2025 : :
2026 : : if (!SetConsoleMode (h_output, dw_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))
2027 : : goto reset_invalid_param_handler;
2028 : :
2029 : : result = TRUE;
2030 : : }
2031 : : }
2032 : :
2033 : : /* FIXME: Support colored outputs for structured logs for pre-Windows 10,
2034 : : * perhaps using WriteConsoleOutput or SetConsoleTextAttribute
2035 : : * (bug 775468), on standard Windows consoles, such as cmd.exe
2036 : : */
2037 : : if (!result)
2038 : : result = win32_is_pipe_tty (output_fd);
2039 : :
2040 : : reset_invalid_param_handler:
2041 : : g_win32_pop_invalid_parameter_handler (&handler);
2042 : :
2043 : : return result;
2044 : : #else
2045 : 198 : return isatty (output_fd);
2046 : : #endif
2047 : : }
2048 : :
2049 : : #ifdef HAVE_SYSLOG_H
2050 : : static gboolean syslog_opened = FALSE;
2051 : : #ifndef __linux__
2052 : : G_LOCK_DEFINE_STATIC (syslog_opened);
2053 : : #endif
2054 : : #endif
2055 : :
2056 : : #if defined(__linux__) && !defined(__BIONIC__)
2057 : : static int journal_fd = -1;
2058 : :
2059 : : #ifndef SOCK_CLOEXEC
2060 : : #define SOCK_CLOEXEC 0
2061 : : #else
2062 : : #define HAVE_SOCK_CLOEXEC 1
2063 : : #endif
2064 : :
2065 : : static void
2066 : 0 : open_journal (void)
2067 : : {
2068 [ # # ]: 0 : if ((journal_fd = socket (AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0)
2069 : 0 : return;
2070 : :
2071 : : #ifndef HAVE_SOCK_CLOEXEC
2072 : : if (fcntl (journal_fd, F_SETFD, FD_CLOEXEC) < 0)
2073 : : {
2074 : : close (journal_fd);
2075 : : journal_fd = -1;
2076 : : }
2077 : : #endif
2078 : : }
2079 : : #endif
2080 : :
2081 : : /**
2082 : : * g_log_writer_is_journald:
2083 : : * @output_fd: output file descriptor to check
2084 : : *
2085 : : * Check whether the given @output_fd file descriptor is a connection to the
2086 : : * systemd journal, or something else (like a log file or `stdout` or
2087 : : * `stderr`).
2088 : : *
2089 : : * Invalid file descriptors are accepted and return `FALSE`, which allows for
2090 : : * the following construct without needing any additional error handling:
2091 : : * ```c
2092 : : * is_journald = g_log_writer_is_journald (fileno (stderr));
2093 : : * ```
2094 : : *
2095 : : * Returns: `TRUE` if @output_fd points to the journal, `FALSE` otherwise
2096 : : * Since: 2.50
2097 : : */
2098 : : gboolean
2099 : 109 : g_log_writer_is_journald (gint output_fd)
2100 : : {
2101 : : #if defined(__linux__) && !defined(__BIONIC__)
2102 : 109 : return _g_fd_is_journal (output_fd);
2103 : : #else
2104 : : return FALSE;
2105 : : #endif
2106 : : }
2107 : :
2108 : : static void escape_string (GString *string);
2109 : :
2110 : : /**
2111 : : * g_log_writer_format_fields:
2112 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
2113 : : * level
2114 : : * @fields: (array length=n_fields): key–value pairs of structured data forming
2115 : : * the log message
2116 : : * @n_fields: number of elements in the @fields array
2117 : : * @use_color: `TRUE` to use
2118 : : * [ANSI color escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code)
2119 : : * when formatting the message, `FALSE` to not
2120 : : *
2121 : : * Format a structured log message as a string suitable for outputting to the
2122 : : * terminal (or elsewhere).
2123 : : *
2124 : : * This will include the values of all fields it knows
2125 : : * how to interpret, which includes `MESSAGE` and `GLIB_DOMAIN` (see the
2126 : : * documentation for [func@GLib.log_structured]). It does not include values from
2127 : : * unknown fields.
2128 : : *
2129 : : * The returned string does **not** have a trailing new-line character. It is
2130 : : * encoded in the character set of the current locale, which is not necessarily
2131 : : * UTF-8.
2132 : : *
2133 : : * Returns: (transfer full): string containing the formatted log message, in
2134 : : * the character set of the current locale
2135 : : * Since: 2.50
2136 : : */
2137 : : gchar *
2138 : 198 : g_log_writer_format_fields (GLogLevelFlags log_level,
2139 : : const GLogField *fields,
2140 : : gsize n_fields,
2141 : : gboolean use_color)
2142 : : {
2143 : : gsize i;
2144 : 198 : const gchar *message = NULL;
2145 : 198 : const gchar *log_domain = NULL;
2146 : 198 : gssize message_length = -1;
2147 : 198 : gssize log_domain_length = -1;
2148 : : gchar level_prefix[STRING_BUFFER_SIZE];
2149 : : GString *gstring;
2150 : : gint64 now;
2151 : : time_t now_secs;
2152 : : struct tm now_tm;
2153 : : gchar time_buf[128];
2154 : :
2155 : : /* Extract some common fields. */
2156 [ + + + + : 992 : for (i = 0; (message == NULL || log_domain == NULL) && i < n_fields; i++)
+ + ]
2157 : : {
2158 : 794 : const GLogField *field = &fields[i];
2159 : :
2160 [ + + ]: 794 : if (g_strcmp0 (field->key, "MESSAGE") == 0)
2161 : : {
2162 : 198 : message = field->value;
2163 : 198 : message_length = field->length;
2164 : : }
2165 [ + + ]: 596 : else if (g_strcmp0 (field->key, "GLIB_DOMAIN") == 0)
2166 : : {
2167 : 196 : log_domain = field->value;
2168 : 196 : log_domain_length = field->length;
2169 : : }
2170 : : }
2171 : :
2172 : : /* Format things. */
2173 : 198 : mklevel_prefix (level_prefix, log_level, use_color);
2174 : :
2175 : 198 : gstring = g_string_new (NULL);
2176 [ + + ]: 198 : if (log_level & ALERT_LEVELS)
2177 [ + - ]: 22 : g_string_append (gstring, "\n");
2178 [ + + ]: 198 : if (!log_domain)
2179 [ + - ]: 4 : g_string_append (gstring, "** ");
2180 : :
2181 : 198 : if ((g_log_msg_prefix & (log_level & G_LOG_LEVEL_MASK)) ==
2182 [ + + ]: 198 : (log_level & G_LOG_LEVEL_MASK))
2183 : : {
2184 : 192 : const gchar *prg_name = g_get_prgname ();
2185 : 192 : gulong pid = getpid ();
2186 : :
2187 [ + + ]: 192 : if (prg_name == NULL)
2188 : 66 : g_string_append_printf (gstring, "(process:%lu): ", pid);
2189 : : else
2190 : 126 : g_string_append_printf (gstring, "(%s:%lu): ", prg_name, pid);
2191 : : }
2192 : :
2193 [ + + ]: 198 : if (log_domain != NULL)
2194 : : {
2195 : : g_string_append_len (gstring, log_domain, log_domain_length);
2196 : : g_string_append_c (gstring, '-');
2197 : : }
2198 : : g_string_append (gstring, level_prefix);
2199 : :
2200 [ + - ]: 198 : g_string_append (gstring, ": ");
2201 : :
2202 : : /* Timestamp */
2203 : 198 : now = g_get_real_time ();
2204 : 198 : now_secs = (time_t) (now / 1000000);
2205 [ + - ]: 198 : if (_g_localtime (now_secs, &now_tm))
2206 : 198 : strftime (time_buf, sizeof (time_buf), "%H:%M:%S", &now_tm);
2207 : : else
2208 : 0 : strcpy (time_buf, "(error)");
2209 : :
2210 : 396 : g_string_append_printf (gstring, "%s%s.%03d%s: ",
2211 : : use_color ? "\033[34m" : "",
2212 [ - + ]: 198 : time_buf, (gint) ((now / 1000) % 1000),
2213 : : color_reset (use_color));
2214 : :
2215 [ - + ]: 198 : if (message == NULL)
2216 : : {
2217 [ # # ]: 0 : g_string_append (gstring, "(NULL) message");
2218 : : }
2219 : : else
2220 : : {
2221 : : GString *msg;
2222 : : const gchar *charset;
2223 : :
2224 : 198 : msg = g_string_new_len (message, message_length);
2225 : 198 : escape_string (msg);
2226 : :
2227 [ + + ]: 198 : if (g_get_console_charset (&charset))
2228 : : {
2229 : : /* charset is UTF-8 already */
2230 [ - + ]: 8 : g_string_append (gstring, msg->str);
2231 : : }
2232 : : else
2233 : : {
2234 : 190 : gchar *lstring = strdup_convert (msg->str, charset);
2235 : : g_string_append (gstring, lstring);
2236 : 190 : g_free (lstring);
2237 : : }
2238 : :
2239 : 198 : g_string_free (msg, TRUE);
2240 : : }
2241 : :
2242 : 198 : return g_string_free (gstring, FALSE);
2243 : : }
2244 : :
2245 : : /**
2246 : : * g_log_writer_syslog:
2247 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
2248 : : * level
2249 : : * @fields: (array length=n_fields): key–value pairs of structured data forming
2250 : : * the log message
2251 : : * @n_fields: number of elements in the @fields array
2252 : : * @user_data: user data passed to [func@GLib.log_set_writer_func]
2253 : : *
2254 : : * Format a structured log message and send it to the syslog daemon. Only fields
2255 : : * which are understood by this function are included in the formatted string
2256 : : * which is printed.
2257 : : *
2258 : : * Log facility will be defined via the SYSLOG_FACILITY field and accepts the following
2259 : : * values: "auth", "daemon", and "user". If SYSLOG_FACILITY is not specified, LOG_USER
2260 : : * facility will be used.
2261 : : *
2262 : : * This is suitable for use as a [type@GLib.LogWriterFunc].
2263 : : *
2264 : : * If syslog is not supported, this function is still defined, but will always
2265 : : * return [enum@GLib.LogWriterOutput.UNHANDLED].
2266 : : *
2267 : : * Returns: [enum@GLib.LogWriterOutput.HANDLED] on success, [enum@GLib.LogWriterOutput.UNHANDLED] otherwise
2268 : : * Since: 2.80
2269 : : */
2270 : : GLogWriterOutput
2271 : 0 : g_log_writer_syslog (GLogLevelFlags log_level,
2272 : : const GLogField *fields,
2273 : : gsize n_fields,
2274 : : gpointer user_data)
2275 : : {
2276 : : #ifdef HAVE_SYSLOG_H
2277 : : gsize i;
2278 : 0 : const char *message = NULL;
2279 : 0 : const char *log_domain = NULL;
2280 : 0 : int syslog_facility = 0;
2281 : : int syslog_level;
2282 : 0 : gssize message_length = -1;
2283 : 0 : gssize log_domain_length = -1;
2284 : : GString *gstring;
2285 : :
2286 : 0 : g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED);
2287 : 0 : g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED);
2288 : :
2289 : : /* As not all man pages provide sufficient information about the thread safety
2290 : : * of the openlog() routine or even describe alternative routines like logopen_r()
2291 : : * intended for multi-threaded applications, use locking on non-Linux platforms till
2292 : : * the situation can be cleared. See the following links for more information:
2293 : : * FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=openlog
2294 : : * NetBSD: https://man.netbsd.org/openlog.3
2295 : : * POSIX: https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/functions/openlog.html#
2296 : : */
2297 : : #ifndef __linux__
2298 : : G_LOCK (syslog_opened);
2299 : : #endif
2300 : :
2301 [ # # ]: 0 : if (!syslog_opened)
2302 : : {
2303 : 0 : openlog (NULL, 0, 0);
2304 : 0 : syslog_opened = TRUE;
2305 : : }
2306 : :
2307 : : #ifndef __linux__
2308 : : G_UNLOCK (syslog_opened);
2309 : : #endif
2310 : :
2311 [ # # ]: 0 : for (i = 0; i < n_fields; i++)
2312 : : {
2313 : 0 : const GLogField *field = &fields[i];
2314 : :
2315 [ # # ]: 0 : if (g_strcmp0 (field->key, "MESSAGE") == 0)
2316 : : {
2317 : 0 : message = field->value;
2318 : 0 : message_length = field->length;
2319 : : }
2320 [ # # ]: 0 : else if (g_strcmp0 (field->key, "GLIB_DOMAIN") == 0)
2321 : : {
2322 : 0 : log_domain = field->value;
2323 : 0 : log_domain_length = field->length;
2324 : : }
2325 [ # # ]: 0 : else if (g_strcmp0 (field->key, "SYSLOG_FACILITY") == 0)
2326 : : {
2327 : 0 : syslog_facility = str_to_syslog_facility (field->value);
2328 : : }
2329 : : }
2330 : :
2331 : 0 : gstring = g_string_new (NULL);
2332 : :
2333 [ # # ]: 0 : if (log_domain != NULL)
2334 : : {
2335 : : g_string_append_len (gstring, log_domain, log_domain_length);
2336 [ # # ]: 0 : g_string_append (gstring, ": ");
2337 : : }
2338 : :
2339 : : g_string_append_len (gstring, message, message_length);
2340 : :
2341 : 0 : syslog_level = atoi (log_level_to_priority (log_level));
2342 : 0 : syslog (syslog_level | syslog_facility, "%s", gstring->str);
2343 : :
2344 : 0 : g_string_free (gstring, TRUE);
2345 : :
2346 : 0 : return G_LOG_WRITER_HANDLED;
2347 : : #else
2348 : : return G_LOG_WRITER_UNHANDLED;
2349 : : #endif /* HAVE_SYSLOG_H */
2350 : : }
2351 : :
2352 : : /* Enable support for the journal if we're on a recent enough Linux */
2353 : : #if defined(__linux__) && !defined(__BIONIC__) && defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
2354 : : #define ENABLE_JOURNAL_SENDV
2355 : : #endif
2356 : :
2357 : : #ifdef ENABLE_JOURNAL_SENDV
2358 : : static int
2359 : 0 : journal_sendv (struct iovec *iov,
2360 : : gsize iovlen)
2361 : : {
2362 : 0 : int buf_fd = -1;
2363 : : struct msghdr mh;
2364 : : struct sockaddr_un sa;
2365 : : union {
2366 : : struct cmsghdr cmsghdr;
2367 : : guint8 buf[CMSG_SPACE(sizeof(int))];
2368 : : } control;
2369 : : struct cmsghdr *cmsg;
2370 : 0 : char path[] = "/dev/shm/journal.XXXXXX";
2371 : :
2372 [ # # ]: 0 : if (journal_fd < 0)
2373 : 0 : open_journal ();
2374 : :
2375 [ # # ]: 0 : if (journal_fd < 0)
2376 : 0 : return -1;
2377 : :
2378 : 0 : memset (&sa, 0, sizeof (sa));
2379 : 0 : sa.sun_family = AF_UNIX;
2380 [ # # ]: 0 : if (g_strlcpy (sa.sun_path, "/run/systemd/journal/socket", sizeof (sa.sun_path)) >= sizeof (sa.sun_path))
2381 : 0 : return -1;
2382 : :
2383 : 0 : memset (&mh, 0, sizeof (mh));
2384 : 0 : mh.msg_name = &sa;
2385 : 0 : mh.msg_namelen = offsetof (struct sockaddr_un, sun_path) + strlen (sa.sun_path);
2386 : 0 : mh.msg_iov = iov;
2387 : 0 : mh.msg_iovlen = iovlen;
2388 : :
2389 : 0 : retry:
2390 [ # # ]: 0 : if (sendmsg (journal_fd, &mh, MSG_NOSIGNAL) >= 0)
2391 : 0 : return 0;
2392 : :
2393 [ # # ]: 0 : if (errno == EINTR)
2394 : 0 : goto retry;
2395 : :
2396 [ # # # # ]: 0 : if (errno != EMSGSIZE && errno != ENOBUFS)
2397 : 0 : return -1;
2398 : :
2399 : : /* Message was too large, so dump to temporary file
2400 : : * and pass an FD to the journal
2401 : : */
2402 [ # # ]: 0 : if ((buf_fd = mkostemp (path, O_CLOEXEC|O_RDWR)) < 0)
2403 : 0 : return -1;
2404 : :
2405 [ # # ]: 0 : if (unlink (path) < 0)
2406 : : {
2407 : 0 : close (buf_fd);
2408 : 0 : return -1;
2409 : : }
2410 : :
2411 [ # # ]: 0 : if (writev (buf_fd, iov, iovlen) < 0)
2412 : : {
2413 : 0 : close (buf_fd);
2414 : 0 : return -1;
2415 : : }
2416 : :
2417 : 0 : mh.msg_iov = NULL;
2418 : 0 : mh.msg_iovlen = 0;
2419 : :
2420 : 0 : memset (&control, 0, sizeof (control));
2421 : 0 : mh.msg_control = &control;
2422 : 0 : mh.msg_controllen = sizeof (control);
2423 : :
2424 [ # # ]: 0 : cmsg = CMSG_FIRSTHDR (&mh);
2425 : 0 : cmsg->cmsg_level = SOL_SOCKET;
2426 : 0 : cmsg->cmsg_type = SCM_RIGHTS;
2427 : 0 : cmsg->cmsg_len = CMSG_LEN (sizeof (int));
2428 : 0 : memcpy (CMSG_DATA (cmsg), &buf_fd, sizeof (int));
2429 : :
2430 : 0 : mh.msg_controllen = cmsg->cmsg_len;
2431 : :
2432 : 0 : retry2:
2433 [ # # ]: 0 : if (sendmsg (journal_fd, &mh, MSG_NOSIGNAL) >= 0)
2434 : 0 : return 0;
2435 : :
2436 [ # # ]: 0 : if (errno == EINTR)
2437 : 0 : goto retry2;
2438 : :
2439 : 0 : return -1;
2440 : : }
2441 : : #endif /* ENABLE_JOURNAL_SENDV */
2442 : :
2443 : : /**
2444 : : * g_log_writer_journald:
2445 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
2446 : : * level
2447 : : * @fields: (array length=n_fields): key–value pairs of structured data forming
2448 : : * the log message
2449 : : * @n_fields: number of elements in the @fields array
2450 : : * @user_data: user data passed to [func@GLib.log_set_writer_func]
2451 : : *
2452 : : * Format a structured log message and send it to the systemd journal as a set
2453 : : * of key–value pairs.
2454 : : *
2455 : : * All fields are sent to the journal, but if a field has
2456 : : * length zero (indicating program-specific data) then only its key will be
2457 : : * sent.
2458 : : *
2459 : : * This is suitable for use as a [type@GLib.LogWriterFunc].
2460 : : *
2461 : : * If GLib has been compiled without systemd support, this function is still
2462 : : * defined, but will always return [enum@GLib.LogWriterOutput.UNHANDLED].
2463 : : *
2464 : : * Returns: [enum@GLib.LogWriterOutput.HANDLED] on success, [enum@GLib.LogWriterOutput.UNHANDLED] otherwise
2465 : : * Since: 2.50
2466 : : */
2467 : : GLogWriterOutput
2468 : 0 : g_log_writer_journald (GLogLevelFlags log_level,
2469 : : const GLogField *fields,
2470 : : gsize n_fields,
2471 : : gpointer user_data)
2472 : : {
2473 : : #ifdef ENABLE_JOURNAL_SENDV
2474 : 0 : const char equals = '=';
2475 : 0 : const char newline = '\n';
2476 : : gsize i, k;
2477 : : struct iovec *iov, *v;
2478 : : char *buf;
2479 : : gint retval;
2480 : :
2481 : 0 : g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED);
2482 : 0 : g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED);
2483 : :
2484 : : /* According to systemd.journal-fields(7), the journal allows fields in any
2485 : : * format (including arbitrary binary), but expects text fields to be UTF-8.
2486 : : * This is great, because we require input strings to be in UTF-8, so no
2487 : : * conversion is necessary and we don’t need to care about the current
2488 : : * locale’s character set.
2489 : : */
2490 : :
2491 : 0 : iov = g_alloca (sizeof (struct iovec) * 5 * n_fields);
2492 : 0 : buf = g_alloca (32 * n_fields);
2493 : :
2494 : 0 : k = 0;
2495 : 0 : v = iov;
2496 [ # # ]: 0 : for (i = 0; i < n_fields; i++)
2497 : : {
2498 : : guint64 length;
2499 : : gboolean binary;
2500 : :
2501 [ # # ]: 0 : if (fields[i].length < 0)
2502 : : {
2503 : 0 : length = strlen (fields[i].value);
2504 : 0 : binary = strchr (fields[i].value, '\n') != NULL;
2505 : : }
2506 : : else
2507 : : {
2508 : 0 : length = fields[i].length;
2509 : 0 : binary = TRUE;
2510 : : }
2511 : :
2512 [ # # ]: 0 : if (binary)
2513 : : {
2514 : : guint64 nstr;
2515 : :
2516 : 0 : v[0].iov_base = (gpointer)fields[i].key;
2517 : 0 : v[0].iov_len = strlen (fields[i].key);
2518 : :
2519 : 0 : v[1].iov_base = (gpointer)&newline;
2520 : 0 : v[1].iov_len = 1;
2521 : :
2522 : 0 : nstr = GUINT64_TO_LE(length);
2523 : 0 : memcpy (&buf[k], &nstr, sizeof (nstr));
2524 : :
2525 : 0 : v[2].iov_base = &buf[k];
2526 : 0 : v[2].iov_len = sizeof (nstr);
2527 : 0 : v += 3;
2528 : 0 : k += sizeof (nstr);
2529 : : }
2530 : : else
2531 : : {
2532 : 0 : v[0].iov_base = (gpointer)fields[i].key;
2533 : 0 : v[0].iov_len = strlen (fields[i].key);
2534 : :
2535 : 0 : v[1].iov_base = (gpointer)=
2536 : 0 : v[1].iov_len = 1;
2537 : 0 : v += 2;
2538 : : }
2539 : :
2540 : 0 : v[0].iov_base = (gpointer)fields[i].value;
2541 : 0 : v[0].iov_len = length;
2542 : :
2543 : 0 : v[1].iov_base = (gpointer)&newline;
2544 : 0 : v[1].iov_len = 1;
2545 : 0 : v += 2;
2546 : : }
2547 : :
2548 : 0 : retval = journal_sendv (iov, v - iov);
2549 : :
2550 : 0 : return retval == 0 ? G_LOG_WRITER_HANDLED : G_LOG_WRITER_UNHANDLED;
2551 : : #else
2552 : : return G_LOG_WRITER_UNHANDLED;
2553 : : #endif /* ENABLE_JOURNAL_SENDV */
2554 : : }
2555 : :
2556 : : /**
2557 : : * g_log_writer_standard_streams:
2558 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
2559 : : * level
2560 : : * @fields: (array length=n_fields): key–value pairs of structured data forming
2561 : : * the log message
2562 : : * @n_fields: number of elements in the @fields array
2563 : : * @user_data: user data passed to [func@GLib.log_set_writer_func]
2564 : : *
2565 : : * Format a structured log message and print it to either `stdout` or `stderr`,
2566 : : * depending on its log level.
2567 : : *
2568 : : * [flags@GLib.LogLevelFlags.LEVEL_INFO] and [flags@GLib.LogLevelFlags.LEVEL_DEBUG] messages
2569 : : * are sent to `stdout`, or to `stderr` if requested by
2570 : : * [func@GLib.log_writer_default_set_use_stderr];
2571 : : * all other log levels are sent to `stderr`. Only fields
2572 : : * which are understood by this function are included in the formatted string
2573 : : * which is printed.
2574 : : *
2575 : : * If the output stream supports
2576 : : * [ANSI color escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code),
2577 : : * they will be used in the output.
2578 : : *
2579 : : * A trailing new-line character is added to the log message when it is printed.
2580 : : *
2581 : : * This is suitable for use as a [type@GLib.LogWriterFunc].
2582 : : *
2583 : : * Returns: [enum@GLib.LogWriterOutput.HANDLED] on success,
2584 : : * [enum@GLib.LogWriterOutput.UNHANDLED] otherwise
2585 : : * Since: 2.50
2586 : : */
2587 : : GLogWriterOutput
2588 : 198 : g_log_writer_standard_streams (GLogLevelFlags log_level,
2589 : : const GLogField *fields,
2590 : : gsize n_fields,
2591 : : gpointer user_data)
2592 : : {
2593 : : FILE *stream;
2594 : 198 : gchar *out = NULL; /* in the current locale’s character set */
2595 : :
2596 : 198 : g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED);
2597 : 198 : g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED);
2598 : :
2599 : 198 : stream = log_level_to_file (log_level);
2600 [ + - - + ]: 198 : if (!stream || fileno (stream) < 0)
2601 : 0 : return G_LOG_WRITER_UNHANDLED;
2602 : :
2603 : 198 : out = g_log_writer_format_fields (log_level, fields, n_fields,
2604 : : g_log_writer_supports_color (fileno (stream)));
2605 : 198 : _g_fprintf (stream, "%s\n", out);
2606 : 198 : fflush (stream);
2607 : 198 : g_free (out);
2608 : :
2609 : 198 : return G_LOG_WRITER_HANDLED;
2610 : : }
2611 : :
2612 : : /* The old g_log() API is implemented in terms of the new structured log API.
2613 : : * However, some of the checks do not line up between the two APIs: the
2614 : : * structured API only handles fatalness of messages for log levels; the old API
2615 : : * handles it per-domain as well. Consequently, we need to disable fatalness
2616 : : * handling in the structured log API when called from the old g_log() API.
2617 : : *
2618 : : * We can guarantee that g_log_default_handler() will pass GLIB_OLD_LOG_API as
2619 : : * the first field to g_log_structured_array(), if that is the case.
2620 : : */
2621 : : static gboolean
2622 : 2 : log_is_old_api (const GLogField *fields,
2623 : : gsize n_fields)
2624 : : {
2625 [ + - ]: 2 : return (n_fields >= 1 &&
2626 [ + - + - ]: 4 : g_strcmp0 (fields[0].key, "GLIB_OLD_LOG_API") == 0 &&
2627 : 2 : g_strcmp0 (fields[0].value, "1") == 0);
2628 : : }
2629 : :
2630 : : static gboolean
2631 : 95951 : domain_found (const gchar *domains,
2632 : : const char *log_domain)
2633 : : {
2634 : : guint len;
2635 : : const gchar *found;
2636 : :
2637 : 95951 : len = strlen (log_domain);
2638 : :
2639 [ + + ]: 95962 : for (found = strstr (domains, log_domain); found;
2640 : 11 : found = strstr (found + 1, log_domain))
2641 : : {
2642 [ + + + + ]: 46706 : if ((found == domains || found[-1] == ' ')
2643 [ + + + + ]: 46700 : && (found[len] == 0 || found[len] == ' '))
2644 : 46695 : return TRUE;
2645 : : }
2646 : :
2647 : 49256 : return FALSE;
2648 : : }
2649 : :
2650 : : static struct {
2651 : : GRWLock lock;
2652 : : gchar *domains;
2653 : : gboolean domains_set;
2654 : : } g_log_global;
2655 : :
2656 : : /**
2657 : : * g_log_writer_default_set_debug_domains:
2658 : : * @domains: (nullable) (transfer none): `NULL`-terminated array with domains to be printed.
2659 : : * `NULL` or an array with no values means none. Array with a single value `"all"` means all.
2660 : : *
2661 : : * Reset the list of domains to be logged, that might be initially set by the
2662 : : * `G_MESSAGES_DEBUG` environment variable.
2663 : : *
2664 : : * This function is thread-safe.
2665 : : *
2666 : : * Since: 2.80
2667 : : */
2668 : : void
2669 : 88599 : g_log_writer_default_set_debug_domains (const gchar * const *domains)
2670 : : {
2671 : 88599 : g_rw_lock_writer_lock (&g_log_global.lock);
2672 : :
2673 : 88599 : g_free (g_log_global.domains);
2674 : 88599 : g_log_global.domains = domains ?
2675 [ + + ]: 88599 : g_strjoinv (" ", (gchar **)domains) : NULL;
2676 : :
2677 : 88599 : g_log_global.domains_set = TRUE;
2678 : :
2679 : 88599 : g_rw_lock_writer_unlock (&g_log_global.lock);
2680 : 88599 : }
2681 : :
2682 : : /*
2683 : : * Internal version of g_log_writer_default_would_drop(), which can
2684 : : * read from either a log_domain or an array of fields. This avoids
2685 : : * having to iterate through the fields if the @log_level is sufficient
2686 : : * to make the decision.
2687 : : */
2688 : : static gboolean
2689 : 131346 : should_drop_message (GLogLevelFlags log_level,
2690 : : const char *log_domain,
2691 : : const GLogField *fields,
2692 : : gsize n_fields)
2693 : : {
2694 : : /* Disable debug message output unless specified in G_MESSAGES_DEBUG. */
2695 [ + + ]: 131346 : if (!(log_level & DEFAULT_LEVELS) &&
2696 [ + + + - ]: 262598 : !(log_level >> G_LOG_LEVEL_USER_SHIFT) &&
2697 : 131295 : !g_log_get_debug_enabled ())
2698 : : {
2699 : : gsize i;
2700 : :
2701 : 131295 : g_rw_lock_reader_lock (&g_log_global.lock);
2702 : :
2703 [ + + ]: 131295 : if (G_UNLIKELY (!g_log_global.domains_set))
2704 : : {
2705 : 109 : g_log_global.domains = g_strdup (g_getenv ("G_MESSAGES_DEBUG"));
2706 : 109 : g_log_global.domains_set = TRUE;
2707 : : }
2708 : :
2709 [ + - ]: 131295 : if ((log_level & INFO_LEVELS) == 0 ||
2710 [ + + ]: 131295 : g_log_global.domains == NULL)
2711 : : {
2712 : 2911 : g_rw_lock_reader_unlock (&g_log_global.lock);
2713 : 2911 : return TRUE;
2714 : : }
2715 : :
2716 [ + + ]: 128384 : if (log_domain == NULL)
2717 : : {
2718 [ + + ]: 32977 : for (i = 0; i < n_fields; i++)
2719 : : {
2720 [ + + ]: 726 : if (g_strcmp0 (fields[i].key, "GLIB_DOMAIN") == 0)
2721 : : {
2722 : 180 : log_domain = fields[i].value;
2723 : 180 : break;
2724 : : }
2725 : : }
2726 : : }
2727 : :
2728 [ + + + + ]: 128384 : if (strcmp (g_log_global.domains, "all") != 0 &&
2729 [ + + ]: 95951 : (log_domain == NULL || !domain_found (g_log_global.domains, log_domain)))
2730 : : {
2731 : 81505 : g_rw_lock_reader_unlock (&g_log_global.lock);
2732 : 81505 : return TRUE;
2733 : : }
2734 : :
2735 : 46879 : g_rw_lock_reader_unlock (&g_log_global.lock);
2736 : : }
2737 : :
2738 : 46930 : return FALSE;
2739 : : }
2740 : :
2741 : : /**
2742 : : * g_log_writer_default_would_drop:
2743 : : * @log_domain: (nullable): log domain
2744 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
2745 : : * level
2746 : : *
2747 : : * Check whether [func@GLib.log_writer_default] and [func@GLib.log_default_handler] would
2748 : : * ignore a message with the given domain and level.
2749 : : *
2750 : : * As with [func@GLib.log_default_handler], this function drops debug and informational
2751 : : * messages unless their log domain (or `all`) is listed in the space-separated
2752 : : * `G_MESSAGES_DEBUG` environment variable, or by [func@GLib.log_writer_default_set_debug_domains].
2753 : : *
2754 : : * This can be used when implementing log writers with the same filtering
2755 : : * behaviour as the default, but a different destination or output format:
2756 : : *
2757 : : * ```c
2758 : : * if (g_log_writer_default_would_drop (log_level, log_domain))
2759 : : * return G_LOG_WRITER_HANDLED;
2760 : : * ]|
2761 : : *
2762 : : * or to skip an expensive computation if it is only needed for a debugging
2763 : : * message, and `G_MESSAGES_DEBUG` is not set:
2764 : : *
2765 : : * ```c
2766 : : * if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
2767 : : * {
2768 : : * g_autofree gchar *result = expensive_computation (my_object);
2769 : : *
2770 : : * g_debug ("my_object result: %s", result);
2771 : : * }
2772 : : * ```
2773 : : *
2774 : : * Returns: `TRUE` if the log message would be dropped by GLib’s
2775 : : * default log handlers
2776 : : * Since: 2.68
2777 : : */
2778 : : gboolean
2779 : 131146 : g_log_writer_default_would_drop (GLogLevelFlags log_level,
2780 : : const char *log_domain)
2781 : : {
2782 : 131146 : return should_drop_message (log_level, log_domain, NULL, 0);
2783 : : }
2784 : :
2785 : : /**
2786 : : * g_log_writer_default:
2787 : : * @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
2788 : : * level
2789 : : * @fields: (array length=n_fields): key–value pairs of structured data forming
2790 : : * the log message
2791 : : * @n_fields: number of elements in the @fields array
2792 : : * @user_data: user data passed to [func@GLib.log_set_writer_func]
2793 : : *
2794 : : * Format a structured log message and output it to the default log destination
2795 : : * for the platform.
2796 : : *
2797 : : * On Linux, this is typically the systemd journal, falling
2798 : : * back to `stdout` or `stderr` if running from the terminal or if output is
2799 : : * being redirected to a file.
2800 : : *
2801 : : * Support for other platform-specific logging mechanisms may be added in
2802 : : * future. Distributors of GLib may modify this function to impose their own
2803 : : * (documented) platform-specific log writing policies.
2804 : : *
2805 : : * This is suitable for use as a [type@GLib.LogWriterFunc], and is the default writer used
2806 : : * if no other is set using [func@GLib.log_set_writer_func].
2807 : : *
2808 : : * As with [func@GLib.log_default_handler], this function drops debug and informational
2809 : : * messages unless their log domain (or `all`) is listed in the space-separated
2810 : : * `G_MESSAGES_DEBUG` environment variable, or set at runtime by [func@GLib.log_writer_default_set_debug_domains].
2811 : : *
2812 : : * [func@GLib.log_writer_default] uses the mask set by [func@GLib.log_set_always_fatal] to
2813 : : * determine which messages are fatal. When using a custom writer function instead it is
2814 : : * up to the writer function to determine which log messages are fatal.
2815 : : *
2816 : : * Returns: [enum@GLib.LogWriterOutput.HANDLED] on success,
2817 : : * [enum@GLib.LogWriterOutput.UNHANDLED] otherwise
2818 : : * Since: 2.50
2819 : : */
2820 : : GLogWriterOutput
2821 : 200 : g_log_writer_default (GLogLevelFlags log_level,
2822 : : const GLogField *fields,
2823 : : gsize n_fields,
2824 : : gpointer user_data)
2825 : : {
2826 : : static gsize initialized = 0;
2827 : : static gboolean stderr_is_journal = FALSE;
2828 : :
2829 : 200 : g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED);
2830 : 200 : g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED);
2831 : :
2832 [ + + ]: 200 : if (should_drop_message (log_level, NULL, fields, n_fields))
2833 : 2 : return G_LOG_WRITER_HANDLED;
2834 : :
2835 : : /* Mark messages as fatal if they have a level set in
2836 : : * g_log_set_always_fatal().
2837 : : */
2838 [ + + - + ]: 198 : if ((log_level & g_log_always_fatal) && !log_is_old_api (fields, n_fields))
2839 : 0 : log_level |= G_LOG_FLAG_FATAL;
2840 : :
2841 : : /* Try logging to the systemd journal as first choice. */
2842 [ + + + - : 198 : if (g_once_init_enter (&initialized))
+ + ]
2843 : : {
2844 : 109 : stderr_is_journal = g_log_writer_is_journald (fileno (stderr));
2845 : 109 : g_once_init_leave (&initialized, TRUE);
2846 : : }
2847 : :
2848 [ - + - - ]: 198 : if (stderr_is_journal &&
2849 : 0 : g_log_writer_journald (log_level, fields, n_fields, user_data) ==
2850 : : G_LOG_WRITER_HANDLED)
2851 : 0 : goto handled;
2852 : :
2853 : : /* FIXME: Add support for the Windows log. */
2854 : :
2855 [ + - ]: 198 : if (g_log_writer_standard_streams (log_level, fields, n_fields, user_data) ==
2856 : : G_LOG_WRITER_HANDLED)
2857 : 198 : goto handled;
2858 : :
2859 : 0 : return G_LOG_WRITER_UNHANDLED;
2860 : :
2861 : 198 : handled:
2862 : : /* Abort if the message was fatal. */
2863 [ - + ]: 198 : if (log_level & G_LOG_FLAG_FATAL)
2864 : : {
2865 : : /* MessageBox is allowed on UWP apps only when building against
2866 : : * the debug CRT, which will set -D_DEBUG */
2867 : : #if defined(G_OS_WIN32) && (defined(_DEBUG) || !defined(G_WINAPI_ONLY_APP))
2868 : : if (!g_test_initialized ())
2869 : : {
2870 : : WCHAR *wide_msg;
2871 : :
2872 : : wide_msg = g_utf8_to_utf16 (fatal_msg_buf, -1, NULL, NULL, NULL);
2873 : :
2874 : : MessageBoxW (NULL, wide_msg, NULL, MB_ICONERROR | MB_SETFOREGROUND);
2875 : :
2876 : : g_free (wide_msg);
2877 : : }
2878 : : #endif /* !G_OS_WIN32 */
2879 : :
2880 : 0 : _g_log_abort (!(log_level & G_LOG_FLAG_RECURSION));
2881 : : }
2882 : :
2883 : 198 : return G_LOG_WRITER_HANDLED;
2884 : : }
2885 : :
2886 : : static GLogWriterOutput
2887 : 0 : _g_log_writer_fallback (GLogLevelFlags log_level,
2888 : : const GLogField *fields,
2889 : : gsize n_fields,
2890 : : gpointer user_data)
2891 : : {
2892 : : FILE *stream;
2893 : : gsize i;
2894 : :
2895 : : /* we cannot call _any_ GLib functions in this fallback handler,
2896 : : * which is why we skip UTF-8 conversion, etc.
2897 : : * since we either recursed or ran out of memory, we're in a pretty
2898 : : * pathologic situation anyways, what we can do is giving the
2899 : : * the process ID unconditionally however.
2900 : : */
2901 : :
2902 : 0 : stream = log_level_to_file (log_level);
2903 : :
2904 [ # # ]: 0 : for (i = 0; i < n_fields; i++)
2905 : : {
2906 : 0 : const GLogField *field = &fields[i];
2907 : :
2908 : : /* Only print fields we definitely recognise, otherwise we could end up
2909 : : * printing a random non-string pointer provided by the user to be
2910 : : * interpreted by their writer function.
2911 : : */
2912 [ # # ]: 0 : if (strcmp (field->key, "MESSAGE") != 0 &&
2913 [ # # ]: 0 : strcmp (field->key, "MESSAGE_ID") != 0 &&
2914 [ # # ]: 0 : strcmp (field->key, "PRIORITY") != 0 &&
2915 [ # # ]: 0 : strcmp (field->key, "CODE_FILE") != 0 &&
2916 [ # # ]: 0 : strcmp (field->key, "CODE_LINE") != 0 &&
2917 [ # # ]: 0 : strcmp (field->key, "CODE_FUNC") != 0 &&
2918 [ # # ]: 0 : strcmp (field->key, "ERRNO") != 0 &&
2919 [ # # ]: 0 : strcmp (field->key, "SYSLOG_FACILITY") != 0 &&
2920 [ # # ]: 0 : strcmp (field->key, "SYSLOG_IDENTIFIER") != 0 &&
2921 [ # # ]: 0 : strcmp (field->key, "SYSLOG_PID") != 0 &&
2922 [ # # ]: 0 : strcmp (field->key, "GLIB_DOMAIN") != 0)
2923 : 0 : continue;
2924 : :
2925 : 0 : write_string (stream, field->key);
2926 : 0 : write_string (stream, "=");
2927 : 0 : write_string_sized (stream, field->value, field->length);
2928 : : }
2929 : :
2930 : : #ifndef G_OS_WIN32
2931 : : {
2932 : : gchar pid_string[FORMAT_UNSIGNED_BUFSIZE];
2933 : :
2934 : 0 : format_unsigned (pid_string, getpid (), 10);
2935 : 0 : write_string (stream, "_PID=");
2936 : 0 : write_string (stream, pid_string);
2937 : : }
2938 : : #endif
2939 : :
2940 : 0 : return G_LOG_WRITER_HANDLED;
2941 : : }
2942 : :
2943 : : /**
2944 : : * g_log_get_debug_enabled:
2945 : : *
2946 : : * Return whether debug output from the GLib logging system is enabled.
2947 : : *
2948 : : * Note that this should not be used to conditionalise calls to [func@GLib.debug] or
2949 : : * other logging functions; it should only be used from [type@GLib.LogWriterFunc]
2950 : : * implementations.
2951 : : *
2952 : : * Note also that the value of this does not depend on `G_MESSAGES_DEBUG`, nor
2953 : : * [func@GLib.log_writer_default_set_debug_domains]; see the docs for [func@GLib.log_set_debug_enabled].
2954 : : *
2955 : : * Returns: `TRUE` if debug output is enabled, `FALSE` otherwise
2956 : : *
2957 : : * Since: 2.72
2958 : : */
2959 : : gboolean
2960 : 131295 : g_log_get_debug_enabled (void)
2961 : : {
2962 : 131295 : return g_atomic_int_get (&g_log_debug_enabled);
2963 : : }
2964 : :
2965 : : /**
2966 : : * g_log_set_debug_enabled:
2967 : : * @enabled: `TRUE` to enable debug output, `FALSE` otherwise
2968 : : *
2969 : : * Enable or disable debug output from the GLib logging system for all domains.
2970 : : *
2971 : : * This value interacts disjunctively with `G_MESSAGES_DEBUG` and
2972 : : * [func@GLib.log_writer_default_set_debug_domains] — if any of them would allow
2973 : : * a debug message to be outputted, it will be.
2974 : : *
2975 : : * Note that this should not be used from within library code to enable debug
2976 : : * output — it is intended for external use.
2977 : : *
2978 : : * Since: 2.72
2979 : : */
2980 : : void
2981 : 4 : g_log_set_debug_enabled (gboolean enabled)
2982 : : {
2983 : 4 : g_atomic_int_set (&g_log_debug_enabled, enabled);
2984 : 4 : }
2985 : :
2986 : : /**
2987 : : * g_return_if_fail_warning: (skip)
2988 : : * @log_domain: (nullable): log domain
2989 : : * @pretty_function: function containing the assertion
2990 : : * @expression: (nullable): expression which failed
2991 : : *
2992 : : * Internal function used to print messages from the public [func@GLib.return_if_fail]
2993 : : * and [func@GLib.return_val_if_fail] macros.
2994 : : */
2995 : : void
2996 : 412 : g_return_if_fail_warning (const char *log_domain,
2997 : : const char *pretty_function,
2998 : : const char *expression)
2999 : : {
3000 : 412 : g_log (log_domain,
3001 : : G_LOG_LEVEL_CRITICAL,
3002 : : "%s: assertion '%s' failed",
3003 : : pretty_function,
3004 : : expression);
3005 : 412 : }
3006 : :
3007 : : /**
3008 : : * g_warn_message: (skip)
3009 : : * @domain: (nullable): log domain
3010 : : * @file: file containing the warning
3011 : : * @line: line number of the warning
3012 : : * @func: function containing the warning
3013 : : * @warnexpr: (nullable): expression which failed
3014 : : *
3015 : : * Internal function used to print messages from the public [func@GLib.warn_if_reached]
3016 : : * and [func@GLib.warn_if_fail] macros.
3017 : : */
3018 : : void
3019 : 4 : g_warn_message (const char *domain,
3020 : : const char *file,
3021 : : int line,
3022 : : const char *func,
3023 : : const char *warnexpr)
3024 : : {
3025 : : char *s, lstr[32];
3026 : 4 : g_snprintf (lstr, 32, "%d", line);
3027 [ + + ]: 4 : if (warnexpr)
3028 : 3 : s = g_strconcat ("(", file, ":", lstr, "):",
3029 [ + - ]: 3 : func, func[0] ? ":" : "",
3030 : : " runtime check failed: (", warnexpr, ")", NULL);
3031 : : else
3032 : 1 : s = g_strconcat ("(", file, ":", lstr, "):",
3033 [ + - ]: 1 : func, func[0] ? ":" : "",
3034 : : " ", "code should not be reached", NULL);
3035 : 4 : g_log (domain, G_LOG_LEVEL_WARNING, "%s", s);
3036 : 4 : g_free (s);
3037 : 4 : }
3038 : :
3039 : : void
3040 : 0 : g_assert_warning (const char *log_domain,
3041 : : const char *file,
3042 : : const int line,
3043 : : const char *pretty_function,
3044 : : const char *expression)
3045 : : {
3046 [ # # ]: 0 : if (expression)
3047 : 0 : g_log (log_domain,
3048 : : G_LOG_LEVEL_ERROR,
3049 : : "file %s: line %d (%s): assertion failed: (%s)",
3050 : : file,
3051 : : line,
3052 : : pretty_function,
3053 : : expression);
3054 : : else
3055 : 0 : g_log (log_domain,
3056 : : G_LOG_LEVEL_ERROR,
3057 : : "file %s: line %d (%s): should not be reached",
3058 : : file,
3059 : : line,
3060 : : pretty_function);
3061 : 0 : _g_log_abort (FALSE);
3062 : 0 : g_abort ();
3063 : : }
3064 : :
3065 : : /**
3066 : : * g_test_expect_message:
3067 : : * @log_domain: (nullable): the log domain of the message
3068 : : * @log_level: the log level of the message
3069 : : * @pattern: a glob-style pattern (see [type@GLib.PatternSpec])
3070 : : *
3071 : : * Indicates that a message with the given @log_domain and @log_level,
3072 : : * with text matching @pattern, is expected to be logged.
3073 : : *
3074 : : * When this message is logged, it will not be printed, and the test case will
3075 : : * not abort.
3076 : : *
3077 : : * This API may only be used with the old logging API ([func@GLib.log] without
3078 : : * `G_LOG_USE_STRUCTURED` defined). It will not work with the structured logging
3079 : : * API. See [Testing for Messages](logging.html#testing-for-messages).
3080 : : *
3081 : : * Use [func@GLib.test_assert_expected_messages] to assert that all
3082 : : * previously-expected messages have been seen and suppressed.
3083 : : *
3084 : : * You can call this multiple times in a row, if multiple messages are
3085 : : * expected as a result of a single call. (The messages must appear in
3086 : : * the same order as the calls to [func@GLib.test_expect_message].)
3087 : : *
3088 : : * For example:
3089 : : *
3090 : : * ```c
3091 : : * // g_main_context_push_thread_default() should fail if the
3092 : : * // context is already owned by another thread.
3093 : : * g_test_expect_message (G_LOG_DOMAIN,
3094 : : * G_LOG_LEVEL_CRITICAL,
3095 : : * "assertion*acquired_context*failed");
3096 : : * g_main_context_push_thread_default (bad_context);
3097 : : * g_test_assert_expected_messages ();
3098 : : * ```
3099 : : *
3100 : : * Note that you cannot use this to test [func@GLib.error] messages, since
3101 : : * [func@GLib.error] intentionally never returns even if the program doesn’t
3102 : : * abort; use [func@GLib.test_trap_subprocess] in this case.
3103 : : *
3104 : : * If messages at [flags@GLib.LogLevelFlags.LEVEL_DEBUG] are emitted, but not explicitly
3105 : : * expected via [func@GLib.test_expect_message] then they will be ignored.
3106 : : *
3107 : : * Since: 2.34
3108 : : */
3109 : : void
3110 : 2527 : g_test_expect_message (const gchar *log_domain,
3111 : : GLogLevelFlags log_level,
3112 : : const gchar *pattern)
3113 : : {
3114 : : GTestExpectedMessage *expected;
3115 : :
3116 : 2527 : g_return_if_fail (log_level != 0);
3117 : 2527 : g_return_if_fail (pattern != NULL);
3118 : 2527 : g_return_if_fail (~log_level & G_LOG_LEVEL_ERROR);
3119 : :
3120 : 2526 : expected = g_new (GTestExpectedMessage, 1);
3121 : 2526 : expected->log_domain = g_strdup (log_domain);
3122 : 2526 : expected->log_level = log_level;
3123 : 2526 : expected->pattern = g_strdup (pattern);
3124 : :
3125 : 2526 : expected_messages = g_slist_append (expected_messages, expected);
3126 : : }
3127 : :
3128 : : void
3129 : 1547 : g_test_assert_expected_messages_internal (const char *domain,
3130 : : const char *file,
3131 : : int line,
3132 : : const char *func)
3133 : : {
3134 [ - + ]: 1547 : if (expected_messages)
3135 : : {
3136 : : GTestExpectedMessage *expected;
3137 : : gchar level_prefix[STRING_BUFFER_SIZE];
3138 : : gchar *message;
3139 : :
3140 : 0 : expected = expected_messages->data;
3141 : :
3142 : 0 : mklevel_prefix (level_prefix, expected->log_level, FALSE);
3143 : 0 : message = g_strdup_printf ("Did not see expected message %s-%s: %s",
3144 [ # # ]: 0 : expected->log_domain ? expected->log_domain : "**",
3145 : : level_prefix, expected->pattern);
3146 : 0 : g_assertion_message (G_LOG_DOMAIN, file, line, func, message);
3147 : 0 : g_free (message);
3148 : : }
3149 : 1547 : }
3150 : :
3151 : : /**
3152 : : * g_test_assert_expected_messages:
3153 : : *
3154 : : * Asserts that all messages previously indicated via
3155 : : * [func@GLib.test_expect_message] have been seen and suppressed.
3156 : : *
3157 : : * This API may only be used with the old logging API ([func@GLib.log] without
3158 : : * `G_LOG_USE_STRUCTURED` defined). It will not work with the structured logging
3159 : : * API. See [Testing for Messages](logging.html#testing-for-messages).
3160 : : *
3161 : : * If messages at [flags@GLib.LogLevelFlags.LEVEL_DEBUG] are emitted, but not explicitly
3162 : : * expected via [func@GLib.test_expect_message] then they will be ignored.
3163 : : *
3164 : : * Since: 2.34
3165 : : */
3166 : :
3167 : : void
3168 : 0 : _g_log_fallback_handler (const gchar *log_domain,
3169 : : GLogLevelFlags log_level,
3170 : : const gchar *message,
3171 : : gpointer unused_data)
3172 : : {
3173 : : gchar level_prefix[STRING_BUFFER_SIZE];
3174 : : #ifndef G_OS_WIN32
3175 : : gchar pid_string[FORMAT_UNSIGNED_BUFSIZE];
3176 : : #endif
3177 : : FILE *stream;
3178 : :
3179 : : /* we cannot call _any_ GLib functions in this fallback handler,
3180 : : * which is why we skip UTF-8 conversion, etc.
3181 : : * since we either recursed or ran out of memory, we're in a pretty
3182 : : * pathologic situation anyways, what we can do is giving the
3183 : : * the process ID unconditionally however.
3184 : : */
3185 : :
3186 : 0 : stream = mklevel_prefix (level_prefix, log_level, FALSE);
3187 [ # # ]: 0 : if (!message)
3188 : 0 : message = "(NULL) message";
3189 : :
3190 : : #ifndef G_OS_WIN32
3191 : 0 : format_unsigned (pid_string, getpid (), 10);
3192 : : #endif
3193 : :
3194 [ # # ]: 0 : if (log_domain)
3195 : 0 : write_string (stream, "\n");
3196 : : else
3197 : 0 : write_string (stream, "\n** ");
3198 : :
3199 : : #ifndef G_OS_WIN32
3200 : 0 : write_string (stream, "(process:");
3201 : 0 : write_string (stream, pid_string);
3202 : 0 : write_string (stream, "): ");
3203 : : #endif
3204 : :
3205 [ # # ]: 0 : if (log_domain)
3206 : : {
3207 : 0 : write_string (stream, log_domain);
3208 : 0 : write_string (stream, "-");
3209 : : }
3210 : 0 : write_string (stream, level_prefix);
3211 : 0 : write_string (stream, ": ");
3212 : 0 : write_string (stream, message);
3213 : 0 : write_string (stream, "\n");
3214 : 0 : }
3215 : :
3216 : : static void
3217 : 198 : escape_string (GString *string)
3218 : : {
3219 : 198 : const char *p = string->str;
3220 : : gunichar wc;
3221 : :
3222 [ + + ]: 19539 : while (p < string->str + string->len)
3223 : : {
3224 : : gboolean safe;
3225 : :
3226 : 19341 : wc = g_utf8_get_char_validated (p, -1);
3227 [ + - - + ]: 19341 : if (wc == (gunichar)-1 || wc == (gunichar)-2)
3228 : 0 : {
3229 : : gchar *tmp;
3230 : : guint pos;
3231 : :
3232 : 0 : pos = p - string->str;
3233 : :
3234 : : /* Emit invalid UTF-8 as hex escapes
3235 : : */
3236 : 0 : tmp = g_strdup_printf ("\\x%02x", (guint)(guchar)*p);
3237 : 0 : g_string_erase (string, pos, 1);
3238 : 0 : g_string_insert (string, pos, tmp);
3239 : :
3240 : 0 : p = string->str + (pos + 4); /* Skip over escape sequence */
3241 : :
3242 : 0 : g_free (tmp);
3243 : 0 : continue;
3244 : : }
3245 [ - + ]: 19341 : if (wc == '\r')
3246 : : {
3247 : 0 : safe = *(p + 1) == '\n';
3248 : : }
3249 : : else
3250 : : {
3251 [ - + - - : 19341 : safe = CHAR_IS_SAFE (wc);
- - - - +
- + + +
- ]
3252 : : }
3253 : :
3254 [ - + ]: 19341 : if (!safe)
3255 : : {
3256 : : gchar *tmp;
3257 : : guint pos;
3258 : :
3259 : 0 : pos = p - string->str;
3260 : :
3261 : : /* Largest char we escape is 0x0a, so we don't have to worry
3262 : : * about 8-digit \Uxxxxyyyy
3263 : : */
3264 : 0 : tmp = g_strdup_printf ("\\u%04x", wc);
3265 : 0 : g_string_erase (string, pos, g_utf8_next_char (p) - p);
3266 : 0 : g_string_insert (string, pos, tmp);
3267 : 0 : g_free (tmp);
3268 : :
3269 : 0 : p = string->str + (pos + 6); /* Skip over escape sequence */
3270 : : }
3271 : : else
3272 : 19341 : p = g_utf8_next_char (p);
3273 : : }
3274 : 198 : }
3275 : :
3276 : : /**
3277 : : * g_log_default_handler:
3278 : : * @log_domain: (nullable): the log domain of the message, or `NULL` for the
3279 : : * default `""` application domain
3280 : : * @log_level: the level of the message
3281 : : * @message: (nullable): the message
3282 : : * @unused_data: (nullable): data passed from [func@GLib.log] which is unused
3283 : : *
3284 : : * The default log handler set up by GLib; [func@GLib.log_set_default_handler]
3285 : : * allows to install an alternate default log handler.
3286 : : *
3287 : : * This is used if no log handler has been set for the particular log
3288 : : * domain and log level combination. It outputs the message to `stderr`
3289 : : * or `stdout` and if the log level is fatal it calls [func@GLib.BREAKPOINT]. It automatically
3290 : : * prints a new-line character after the message, so one does not need to be
3291 : : * manually included in @message.
3292 : : *
3293 : : * The behavior of this log handler can be influenced by a number of
3294 : : * environment variables:
3295 : : *
3296 : : * - `G_MESSAGES_PREFIXED`: A `:`-separated list of log levels for which
3297 : : * messages should be prefixed by the program name and PID of the
3298 : : * application.
3299 : : * - `G_MESSAGES_DEBUG`: A space-separated list of log domains for
3300 : : * which debug and informational messages are printed. By default
3301 : : * these messages are not printed. If you need to set the allowed
3302 : : * domains at runtime, use [func@GLib.log_writer_default_set_debug_domains].
3303 : : *
3304 : : * `stderr` is used for levels [flags@GLib.LogLevelFlags.LEVEL_ERROR],
3305 : : * [flags@GLib.LogLevelFlags.LEVEL_CRITICAL], [flags@GLib.LogLevelFlags.LEVEL_WARNING] and
3306 : : * [flags@GLib.LogLevelFlags.LEVEL_MESSAGE]. `stdout` is used for
3307 : : * the rest, unless `stderr` was requested by
3308 : : * [func@GLib.log_writer_default_set_use_stderr].
3309 : : *
3310 : : * This has no effect if structured logging is enabled; see
3311 : : * [Using Structured Logging](logging.html#using-structured-logging).
3312 : : */
3313 : : void
3314 : 199 : g_log_default_handler (const gchar *log_domain,
3315 : : GLogLevelFlags log_level,
3316 : : const gchar *message,
3317 : : gpointer unused_data)
3318 : : {
3319 : : GLogField fields[4];
3320 : 199 : int n_fields = 0;
3321 : :
3322 : : /* we can be called externally with recursion for whatever reason */
3323 [ - + ]: 199 : if (log_level & G_LOG_FLAG_RECURSION)
3324 : : {
3325 : 0 : _g_log_fallback_handler (log_domain, log_level, message, unused_data);
3326 : 0 : return;
3327 : : }
3328 : :
3329 : 199 : fields[0].key = "GLIB_OLD_LOG_API";
3330 : 199 : fields[0].value = "1";
3331 : 199 : fields[0].length = -1;
3332 : 199 : n_fields++;
3333 : :
3334 : 199 : fields[1].key = "MESSAGE";
3335 : 199 : fields[1].value = message;
3336 : 199 : fields[1].length = -1;
3337 : 199 : n_fields++;
3338 : :
3339 : 199 : fields[2].key = "PRIORITY";
3340 : 199 : fields[2].value = log_level_to_priority (log_level);
3341 : 199 : fields[2].length = -1;
3342 : 199 : n_fields++;
3343 : :
3344 [ + + ]: 199 : if (log_domain)
3345 : : {
3346 : 196 : fields[3].key = "GLIB_DOMAIN";
3347 : 196 : fields[3].value = log_domain;
3348 : 196 : fields[3].length = -1;
3349 : 196 : n_fields++;
3350 : : }
3351 : :
3352 : : /* Print out via the structured log API, but drop any fatal flags since we
3353 : : * have already handled them. The fatal handling in the structured logging
3354 : : * API is more coarse-grained than in the old g_log() API, so we don't want
3355 : : * to use it here.
3356 : : */
3357 : 199 : g_log_structured_array (log_level & ~G_LOG_FLAG_FATAL, fields, n_fields);
3358 : : }
3359 : :
3360 : : /**
3361 : : * g_set_print_handler:
3362 : : * @func: (nullable): the new print handler or `NULL` to
3363 : : * reset to the default
3364 : : *
3365 : : * Sets the print handler to @func, or resets it to the
3366 : : * default GLib handler if `NULL`.
3367 : : *
3368 : : * Any messages passed to [func@GLib.print] will be output via
3369 : : * the new handler. The default handler outputs
3370 : : * the encoded message to `stdout`. By providing your own handler
3371 : : * you can redirect the output, to a GTK widget or a
3372 : : * log file for example.
3373 : : *
3374 : : * Since 2.76 this functions always returns a valid
3375 : : * [type@GLib.PrintFunc], and never returns `NULL`. If no custom
3376 : : * print handler was set, it will return the GLib
3377 : : * default print handler and that can be re-used to
3378 : : * decorate its output and/or to write to `stderr`
3379 : : * in all platforms. Before GLib 2.76, this was `NULL`.
3380 : : *
3381 : : * Returns: (not nullable): the old print handler
3382 : : */
3383 : : GPrintFunc
3384 : 638 : g_set_print_handler (GPrintFunc func)
3385 : : {
3386 [ + + ]: 638 : return g_atomic_pointer_exchange (&glib_print_func,
3387 : : func ? func : g_default_print_func);
3388 : : }
3389 : :
3390 : : static void
3391 : 24124 : print_string (FILE *stream,
3392 : : const gchar *string)
3393 : : {
3394 : : const gchar *charset;
3395 : : int ret;
3396 : :
3397 [ + + ]: 24124 : if (g_get_console_charset (&charset))
3398 : : {
3399 : : /* charset is UTF-8 already */
3400 : 4714 : ret = fputs (string, stream);
3401 : : }
3402 : : else
3403 : : {
3404 : 19410 : gchar *converted_string = strdup_convert (string, charset);
3405 : :
3406 : 19410 : ret = fputs (converted_string, stream);
3407 : 19410 : g_free (converted_string);
3408 : : }
3409 : :
3410 : : /* In case of failure we can just return early, but there's nothing else
3411 : : * we can do at this level
3412 : : */
3413 [ - + ]: 24124 : if (ret == EOF)
3414 : 0 : return;
3415 : :
3416 : 24124 : fflush (stream);
3417 : : }
3418 : :
3419 : : G_ALWAYS_INLINE static inline const char *
3420 : : format_string (const char *format,
3421 : : va_list args,
3422 : : char **out_allocated_string)
3423 : : {
3424 : : #ifdef G_ENABLE_DEBUG
3425 : 10853 : g_assert (out_allocated_string != NULL);
3426 : : #endif
3427 : :
3428 : : /* If there is no formatting to be done, avoid an allocation */
3429 [ + + + + : 27263 : if (strchr (format, '%') == NULL)
+ - + + +
+ ]
3430 : : {
3431 : 2189 : *out_allocated_string = NULL;
3432 : 2189 : return format;
3433 : : }
3434 : : else
3435 : : {
3436 : 25074 : *out_allocated_string = g_strdup_vprintf (format, args);
3437 : 25074 : return *out_allocated_string;
3438 : : }
3439 : : }
3440 : :
3441 : : static void
3442 : 24065 : g_default_print_func (const gchar *string)
3443 : : {
3444 : 24065 : print_string (stdout, string);
3445 : 24065 : }
3446 : :
3447 : : static void
3448 : 59 : g_default_printerr_func (const gchar *string)
3449 : : {
3450 : 59 : print_string (stderr, string);
3451 : 59 : }
3452 : :
3453 : : /**
3454 : : * g_print:
3455 : : * @format: the message format. See the `printf()` documentation
3456 : : * @...: the parameters to insert into the format string
3457 : : *
3458 : : * Outputs a formatted message via the print handler.
3459 : : *
3460 : : * The default print handler outputs the encoded message to `stdout`, without
3461 : : * appending a trailing new-line character. Typically, @format should end with
3462 : : * its own new-line character.
3463 : : *
3464 : : * This function should not be used from within libraries for debugging
3465 : : * messages, since it may be redirected by applications to special
3466 : : * purpose message windows or even files. Instead, libraries should
3467 : : * use [func@GLib.log], [func@GLib.log_structured], or the convenience macros
3468 : : * [func@GLib.message], [func@GLib.warning] and [func@GLib.error].
3469 : : */
3470 : : void
3471 : 16350 : g_print (const gchar *format,
3472 : : ...)
3473 : : {
3474 : : va_list args;
3475 : : const gchar *string;
3476 : 16350 : gchar *free_me = NULL;
3477 : : GPrintFunc local_glib_print_func;
3478 : :
3479 : 16350 : g_return_if_fail (format != NULL);
3480 : :
3481 [ - + ]: 16350 : va_start (args, format);
3482 : 16350 : string = format_string (format, args, &free_me);
3483 : 16350 : va_end (args);
3484 : :
3485 : 16350 : local_glib_print_func = g_atomic_pointer_get (&glib_print_func);
3486 : 16350 : local_glib_print_func (string);
3487 : 16350 : g_free (free_me);
3488 : : }
3489 : :
3490 : : /**
3491 : : * g_set_printerr_handler:
3492 : : * @func: (nullable): he new error message handler or `NULL`
3493 : : * to reset to the default
3494 : : *
3495 : : * Sets the handler for printing error messages to @func,
3496 : : * or resets it to the default GLib handler if `NULL`.
3497 : : *
3498 : : * Any messages passed to [func@GLib.printerr] will be output via
3499 : : * the new handler. The default handler outputs the encoded
3500 : : * message to `stderr`. By providing your own handler you can
3501 : : * redirect the output, to a GTK widget or a log file for
3502 : : * example.
3503 : : *
3504 : : * Since 2.76 this functions always returns a valid
3505 : : * [type@GLib.PrintFunc], and never returns `NULL`. If no custom error
3506 : : * print handler was set, it will return the GLib default
3507 : : * error print handler and that can be re-used to decorate
3508 : : * its output and/or to write to `stderr` in all platforms.
3509 : : * Before GLib 2.76, this was `NULL`.
3510 : : *
3511 : : * Returns: (not nullable): the old error message handler
3512 : : */
3513 : : GPrintFunc
3514 : 4 : g_set_printerr_handler (GPrintFunc func)
3515 : : {
3516 [ + + ]: 4 : return g_atomic_pointer_exchange (&glib_printerr_func,
3517 : : func ? func : g_default_printerr_func);
3518 : : }
3519 : :
3520 : : /**
3521 : : * g_printerr:
3522 : : * @format: the message format. See the `printf()` documentation
3523 : : * @...: the parameters to insert into the format string
3524 : : *
3525 : : * Outputs a formatted message via the error message handler.
3526 : : *
3527 : : * The default handler outputs the encoded message to `stderr`, without appending
3528 : : * a trailing new-line character. Typically, @format should end with its own
3529 : : * new-line character.
3530 : : *
3531 : : * This function should not be used from within libraries.
3532 : : * Instead [func@GLib.log] or [func@GLib.log_structured] should be used, or the convenience
3533 : : * macros [func@GLib.message], [func@GLib.warning] and [func@GLib.error].
3534 : : */
3535 : : void
3536 : 60 : g_printerr (const gchar *format,
3537 : : ...)
3538 : : {
3539 : : va_list args;
3540 : : const char *string;
3541 : 60 : char *free_me = NULL;
3542 : : GPrintFunc local_glib_printerr_func;
3543 : :
3544 : 60 : g_return_if_fail (format != NULL);
3545 : :
3546 [ - + ]: 60 : va_start (args, format);
3547 : 60 : string = format_string (format, args, &free_me);
3548 : 60 : va_end (args);
3549 : :
3550 : 60 : local_glib_printerr_func = g_atomic_pointer_get (&glib_printerr_func);
3551 : 60 : local_glib_printerr_func (string);
3552 : 60 : g_free (free_me);
3553 : : }
3554 : :
3555 : : /**
3556 : : * g_printf_string_upper_bound:
3557 : : * @format: the format string. See the `printf()` documentation
3558 : : * @args: the parameters to be inserted into the format string
3559 : : *
3560 : : * Calculates the maximum space needed to store the output
3561 : : * of the `sprintf()` function.
3562 : : *
3563 : : * If @format or @args are invalid, `0` is returned. This could happen if, for
3564 : : * example, @format contains an `%lc` or `%ls` placeholder and @args contains a
3565 : : * wide character which cannot be represented in multibyte encoding. `0`
3566 : : * can also be returned legitimately if, for example, @format is `%s` and @args
3567 : : * is an empty string. The caller is responsible for differentiating these two
3568 : : * return cases if necessary. It is recommended to not use `%lc` or `%ls`
3569 : : * placeholders in any case, as their behaviour is locale-dependent.
3570 : : *
3571 : : * Returns: the maximum space needed to store the formatted string, or `0` on error
3572 : : */
3573 : : gsize
3574 : 2 : g_printf_string_upper_bound (const gchar *format,
3575 : : va_list args)
3576 : : {
3577 : : gchar c;
3578 : 2 : int count = _g_vsnprintf (&c, 1, format, args);
3579 : :
3580 [ + + ]: 2 : if (count < 0)
3581 : 1 : return 0;
3582 : :
3583 : 1 : return count + 1;
3584 : : }
|