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