LCOV - code coverage report
Current view: top level - glib/glib - gmessages.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 577 887 65.1 %
Date: 2024-03-26 05:16:46 Functions: 52 63 82.5 %
Branches: 239 481 49.7 %

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

Generated by: LCOV version 1.14