Coverage Report

Created: 2026-09-13 06:25

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