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

source code of gtk/subprojects/glib/glib/gmessages.c