LCOV - code coverage report
Current view: top level - glib/gio - gsubprocesslauncher.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 148 190 77.9 %
Date: 2024-04-23 05:16:05 Functions: 24 28 85.7 %
Branches: 41 82 50.0 %

           Branch data     Line data    Source code
       1                 :            : /* GIO - GLib Input, Output and Streaming Library
       2                 :            :  *
       3                 :            :  * Copyright © 2012 Red Hat, Inc.
       4                 :            :  * Copyright © 2012-2013 Canonical Limited
       5                 :            :  *
       6                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       7                 :            :  *
       8                 :            :  * This library is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU Lesser General Public
      10                 :            :  * License as published by the Free Software Foundation; either
      11                 :            :  * version 2.1 of the License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * See the included COPYING file for more information.
      14                 :            :  *
      15                 :            :  * Authors: Colin Walters <walters@verbum.org>
      16                 :            :  *          Ryan Lortie <desrt@desrt.ca>
      17                 :            :  */
      18                 :            : 
      19                 :            : /**
      20                 :            :  * GSubprocessLauncher:
      21                 :            :  *
      22                 :            :  * This class contains a set of options for launching child processes,
      23                 :            :  * such as where its standard input and output will be directed, the
      24                 :            :  * argument list, the environment, and more.
      25                 :            :  *
      26                 :            :  * While the [class@Gio.Subprocess] class has high level functions covering
      27                 :            :  * popular cases, use of this class allows access to more advanced
      28                 :            :  * options.  It can also be used to launch multiple subprocesses with
      29                 :            :  * a similar configuration.
      30                 :            :  *
      31                 :            :  * Since: 2.40
      32                 :            :  */
      33                 :            : 
      34                 :            : #define ALL_STDIN_FLAGS         (G_SUBPROCESS_FLAGS_STDIN_PIPE |        \
      35                 :            :                                  G_SUBPROCESS_FLAGS_STDIN_INHERIT)
      36                 :            : #define ALL_STDOUT_FLAGS        (G_SUBPROCESS_FLAGS_STDOUT_PIPE |       \
      37                 :            :                                  G_SUBPROCESS_FLAGS_STDOUT_SILENCE)
      38                 :            : #define ALL_STDERR_FLAGS        (G_SUBPROCESS_FLAGS_STDERR_PIPE |       \
      39                 :            :                                  G_SUBPROCESS_FLAGS_STDERR_SILENCE |    \
      40                 :            :                                  G_SUBPROCESS_FLAGS_STDERR_MERGE)
      41                 :            : 
      42                 :            : #include "config.h"
      43                 :            : 
      44                 :            : #include "gsubprocesslauncher-private.h"
      45                 :            : #include "gioenumtypes.h"
      46                 :            : #include "gsubprocess.h"
      47                 :            : #include "ginitable.h"
      48                 :            : #include "gioerror.h"
      49                 :            : 
      50                 :            : #ifdef G_OS_UNIX
      51                 :            : #include <unistd.h>
      52                 :            : #include <fcntl.h>
      53                 :            : #endif
      54                 :            : 
      55                 :            : typedef GObjectClass GSubprocessLauncherClass;
      56                 :            : 
      57   [ +  +  +  -  :        104 : G_DEFINE_TYPE (GSubprocessLauncher, g_subprocess_launcher, G_TYPE_OBJECT)
                   +  + ]
      58                 :            : 
      59                 :            : static gboolean
      60                 :        134 : verify_disposition (const gchar      *stream_name,
      61                 :            :                     GSubprocessFlags  filtered_flags,
      62                 :            :                     gint              fd,
      63                 :            :                     const gchar      *filename)
      64                 :            : {
      65                 :            :   guint n_bits;
      66                 :            : 
      67         [ +  + ]:        134 :   if (!filtered_flags)
      68                 :        117 :     n_bits = 0;
      69         [ +  - ]:         17 :   else if (((filtered_flags - 1) & filtered_flags) == 0)
      70                 :         17 :     n_bits = 1;
      71                 :            :   else
      72                 :          0 :     n_bits = 2; /* ...or more */
      73                 :            : 
      74         [ -  + ]:        134 :   if (n_bits + (fd >= 0) + (filename != NULL) > 1)
      75                 :            :     {
      76                 :            :       GString *err;
      77                 :            : 
      78                 :          0 :       err = g_string_new (NULL);
      79         [ #  # ]:          0 :       if (n_bits)
      80                 :            :         {
      81                 :            :           GFlagsClass *class;
      82                 :            :           guint i;
      83                 :            : 
      84                 :          0 :           class = g_type_class_peek (G_TYPE_SUBPROCESS_FLAGS);
      85                 :            : 
      86         [ #  # ]:          0 :           for (i = 0; i < class->n_values; i++)
      87                 :            :             {
      88                 :          0 :               const GFlagsValue *value = &class->values[i];
      89                 :            : 
      90         [ #  # ]:          0 :               if (filtered_flags & value->value)
      91                 :          0 :                 g_string_append_printf (err, " %s", value->value_name);
      92                 :            :             }
      93                 :            : 
      94                 :          0 :           g_type_class_unref (class);
      95                 :            :         }
      96                 :            : 
      97         [ #  # ]:          0 :       if (fd >= 0)
      98                 :          0 :         g_string_append_printf (err, " g_subprocess_launcher_take_%s_fd()", stream_name);
      99                 :            : 
     100         [ #  # ]:          0 :       if (filename)
     101                 :          0 :         g_string_append_printf (err, " g_subprocess_launcher_set_%s_file_path()", stream_name);
     102                 :            : 
     103                 :          0 :       g_critical ("You may specify at most one disposition for the %s stream, but you specified:%s.",
     104                 :            :                   stream_name, err->str);
     105                 :          0 :       g_string_free (err, TRUE);
     106                 :            : 
     107                 :          0 :       return FALSE;
     108                 :            :     }
     109                 :            : 
     110                 :        134 :   return TRUE;
     111                 :            : }
     112                 :            : 
     113                 :            : static gboolean
     114                 :         41 : verify_flags (GSubprocessFlags flags)
     115                 :            : {
     116         [ +  - ]:         82 :   return verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, -1, NULL) &&
     117   [ +  -  +  - ]:         82 :          verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, -1, NULL) &&
     118                 :         41 :          verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, -1, NULL);
     119                 :            : }
     120                 :            : 
     121                 :            : static void
     122                 :         21 : g_subprocess_launcher_set_property (GObject *object, guint prop_id,
     123                 :            :                                     const GValue *value, GParamSpec *pspec)
     124                 :            : {
     125                 :         21 :   GSubprocessLauncher *launcher = G_SUBPROCESS_LAUNCHER (object);
     126                 :            : 
     127                 :         21 :   g_assert (prop_id == 1);
     128                 :            : 
     129         [ +  - ]:         21 :   if (verify_flags (g_value_get_flags (value)))
     130                 :         21 :     launcher->flags = g_value_get_flags (value);
     131                 :         21 : }
     132                 :            : 
     133                 :            : static void
     134                 :         21 : g_subprocess_launcher_dispose (GObject *object)
     135                 :            : {
     136                 :         21 :   GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
     137                 :            : 
     138                 :            : #ifdef G_OS_UNIX
     139                 :         21 :   g_clear_pointer (&self->stdin_path, g_free);
     140                 :         21 :   g_clear_pointer (&self->stdout_path, g_free);
     141                 :         21 :   g_clear_pointer (&self->stderr_path, g_free);
     142                 :            : 
     143                 :         21 :   g_subprocess_launcher_close (self);
     144                 :            : 
     145         [ -  + ]:         21 :   if (self->child_setup_destroy_notify)
     146                 :          0 :     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
     147                 :         21 :   self->child_setup_destroy_notify = NULL;
     148                 :         21 :   self->child_setup_user_data = NULL;
     149                 :            : #endif
     150                 :            : 
     151                 :         21 :   g_clear_pointer (&self->envp, g_strfreev);
     152                 :         21 :   g_clear_pointer (&self->cwd, g_free);
     153                 :            : 
     154                 :         21 :   G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->dispose (object);
     155                 :         21 : }
     156                 :            : 
     157                 :            : static void
     158                 :         21 : g_subprocess_launcher_init (GSubprocessLauncher  *self)
     159                 :            : {
     160                 :         21 :   self->envp = g_get_environ ();
     161                 :            : 
     162                 :            : #ifdef G_OS_UNIX
     163                 :         21 :   self->stdin_fd = -1;
     164                 :         21 :   self->stdout_fd = -1;
     165                 :         21 :   self->stderr_fd = -1;
     166                 :         21 :   self->source_fds = g_array_new (FALSE, 0, sizeof (int));
     167                 :         21 :   self->target_fds = g_array_new (FALSE, 0, sizeof (int));
     168                 :            : #endif
     169                 :         21 : }
     170                 :            : 
     171                 :            : static void
     172                 :          9 : g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
     173                 :            : {
     174                 :          9 :   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
     175                 :            : 
     176                 :          9 :   gobject_class->set_property = g_subprocess_launcher_set_property;
     177                 :          9 :   gobject_class->dispose = g_subprocess_launcher_dispose;
     178                 :            : 
     179                 :            :   /**
     180                 :            :    * GSubprocessLauncher:flags:
     181                 :            :    *
     182                 :            :    * [flags@Gio.SubprocessFlags] for launched processes.
     183                 :            :    *
     184                 :            :    * Since: 2.40
     185                 :            :    */
     186                 :          9 :   g_object_class_install_property (gobject_class, 1,
     187                 :            :                                    g_param_spec_flags ("flags", NULL, NULL,
     188                 :            :                                                        G_TYPE_SUBPROCESS_FLAGS, 0, G_PARAM_WRITABLE |
     189                 :            :                                                        G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
     190                 :          9 : }
     191                 :            : 
     192                 :            : /**
     193                 :            :  * g_subprocess_launcher_new:
     194                 :            :  * @flags: #GSubprocessFlags
     195                 :            :  *
     196                 :            :  * Creates a new #GSubprocessLauncher.
     197                 :            :  *
     198                 :            :  * The launcher is created with the default options.  A copy of the
     199                 :            :  * environment of the calling process is made at the time of this call
     200                 :            :  * and will be used as the environment that the process is launched in.
     201                 :            :  *
     202                 :            :  * Since: 2.40
     203                 :            :  **/
     204                 :            : GSubprocessLauncher *
     205                 :         20 : g_subprocess_launcher_new (GSubprocessFlags flags)
     206                 :            : {
     207         [ -  + ]:         20 :   if (!verify_flags (flags))
     208                 :          0 :     return NULL;
     209                 :            : 
     210                 :         20 :   return g_object_new (G_TYPE_SUBPROCESS_LAUNCHER,
     211                 :            :                        "flags", flags,
     212                 :            :                        NULL);
     213                 :            : }
     214                 :            : 
     215                 :            : /**
     216                 :            :  * g_subprocess_launcher_set_environ:
     217                 :            :  * @self: a #GSubprocessLauncher
     218                 :            :  * @env: (array zero-terminated=1) (element-type filename) (transfer none):
     219                 :            :  *     the replacement environment
     220                 :            :  *
     221                 :            :  * Replace the entire environment of processes launched from this
     222                 :            :  * launcher with the given 'environ' variable.
     223                 :            :  *
     224                 :            :  * Typically you will build this variable by using g_listenv() to copy
     225                 :            :  * the process 'environ' and using the functions g_environ_setenv(),
     226                 :            :  * g_environ_unsetenv(), etc.
     227                 :            :  *
     228                 :            :  * As an alternative, you can use g_subprocess_launcher_setenv(),
     229                 :            :  * g_subprocess_launcher_unsetenv(), etc.
     230                 :            :  *
     231                 :            :  * Pass an empty array to set an empty environment. Pass %NULL to inherit the
     232                 :            :  * parent process’ environment. As of GLib 2.54, the parent process’ environment
     233                 :            :  * will be copied when g_subprocess_launcher_set_environ() is called.
     234                 :            :  * Previously, it was copied when the subprocess was executed. This means the
     235                 :            :  * copied environment may now be modified (using g_subprocess_launcher_setenv(),
     236                 :            :  * etc.) before launching the subprocess.
     237                 :            :  *
     238                 :            :  * On UNIX, all strings in this array can be arbitrary byte strings.
     239                 :            :  * On Windows, they should be in UTF-8.
     240                 :            :  *
     241                 :            :  * Since: 2.40
     242                 :            :  **/
     243                 :            : void
     244                 :          4 : g_subprocess_launcher_set_environ (GSubprocessLauncher  *self,
     245                 :            :                                    gchar               **env)
     246                 :            : {
     247                 :          4 :   g_strfreev (self->envp);
     248                 :          4 :   self->envp = g_strdupv (env);
     249                 :            : 
     250         [ +  + ]:          4 :   if (self->envp == NULL)
     251                 :          3 :     self->envp = g_get_environ ();
     252                 :          4 : }
     253                 :            : 
     254                 :            : /**
     255                 :            :  * g_subprocess_launcher_setenv:
     256                 :            :  * @self: a #GSubprocessLauncher
     257                 :            :  * @variable: (type filename): the environment variable to set,
     258                 :            :  *     must not contain '='
     259                 :            :  * @value: (type filename): the new value for the variable
     260                 :            :  * @overwrite: whether to change the variable if it already exists
     261                 :            :  *
     262                 :            :  * Sets the environment variable @variable in the environment of
     263                 :            :  * processes launched from this launcher.
     264                 :            :  *
     265                 :            :  * On UNIX, both the variable's name and value can be arbitrary byte
     266                 :            :  * strings, except that the variable's name cannot contain '='.
     267                 :            :  * On Windows, they should be in UTF-8.
     268                 :            :  *
     269                 :            :  * Since: 2.40
     270                 :            :  **/
     271                 :            : void
     272                 :          5 : g_subprocess_launcher_setenv (GSubprocessLauncher *self,
     273                 :            :                               const gchar         *variable,
     274                 :            :                               const gchar         *value,
     275                 :            :                               gboolean             overwrite)
     276                 :            : {
     277                 :          5 :   self->envp = g_environ_setenv (self->envp, variable, value, overwrite);
     278                 :          5 : }
     279                 :            : 
     280                 :            : /**
     281                 :            :  * g_subprocess_launcher_unsetenv:
     282                 :            :  * @self: a #GSubprocessLauncher
     283                 :            :  * @variable: (type filename): the environment variable to unset,
     284                 :            :  *     must not contain '='
     285                 :            :  *
     286                 :            :  * Removes the environment variable @variable from the environment of
     287                 :            :  * processes launched from this launcher.
     288                 :            :  *
     289                 :            :  * On UNIX, the variable's name can be an arbitrary byte string not
     290                 :            :  * containing '='. On Windows, it should be in UTF-8.
     291                 :            :  *
     292                 :            :  * Since: 2.40
     293                 :            :  **/
     294                 :            : void
     295                 :          3 : g_subprocess_launcher_unsetenv (GSubprocessLauncher *self,
     296                 :            :                                 const gchar         *variable)
     297                 :            : {
     298                 :          3 :   self->envp = g_environ_unsetenv (self->envp, variable);
     299                 :          3 : }
     300                 :            : 
     301                 :            : /**
     302                 :            :  * g_subprocess_launcher_getenv:
     303                 :            :  * @self: a #GSubprocessLauncher
     304                 :            :  * @variable: (type filename): the environment variable to get
     305                 :            :  *
     306                 :            :  * Returns the value of the environment variable @variable in the
     307                 :            :  * environment of processes launched from this launcher.
     308                 :            :  *
     309                 :            :  * On UNIX, the returned string can be an arbitrary byte string.
     310                 :            :  * On Windows, it will be UTF-8.
     311                 :            :  *
     312                 :            :  * Returns: (nullable) (type filename): the value of the environment variable,
     313                 :            :  *     %NULL if unset
     314                 :            :  *
     315                 :            :  * Since: 2.40
     316                 :            :  **/
     317                 :            : const gchar *
     318                 :          4 : g_subprocess_launcher_getenv (GSubprocessLauncher *self,
     319                 :            :                               const gchar         *variable)
     320                 :            : {
     321                 :          4 :   return g_environ_getenv (self->envp, variable);
     322                 :            : }
     323                 :            : 
     324                 :            : /**
     325                 :            :  * g_subprocess_launcher_set_cwd:
     326                 :            :  * @self: a #GSubprocessLauncher
     327                 :            :  * @cwd: (type filename): the cwd for launched processes
     328                 :            :  *
     329                 :            :  * Sets the current working directory that processes will be launched
     330                 :            :  * with.
     331                 :            :  *
     332                 :            :  * By default processes are launched with the current working directory
     333                 :            :  * of the launching process at the time of launch.
     334                 :            :  *
     335                 :            :  * Since: 2.40
     336                 :            :  **/
     337                 :            : void
     338                 :          1 : g_subprocess_launcher_set_cwd (GSubprocessLauncher *self,
     339                 :            :                                const gchar         *cwd)
     340                 :            : {
     341                 :          1 :   g_free (self->cwd);
     342                 :          1 :   self->cwd = g_strdup (cwd);
     343                 :          1 : }
     344                 :            : 
     345                 :            : /**
     346                 :            :  * g_subprocess_launcher_set_flags:
     347                 :            :  * @self: a #GSubprocessLauncher
     348                 :            :  * @flags: #GSubprocessFlags
     349                 :            :  *
     350                 :            :  * Sets the flags on the launcher.
     351                 :            :  *
     352                 :            :  * The default flags are %G_SUBPROCESS_FLAGS_NONE.
     353                 :            :  *
     354                 :            :  * You may not set flags that specify conflicting options for how to
     355                 :            :  * handle a particular stdio stream (eg: specifying both
     356                 :            :  * %G_SUBPROCESS_FLAGS_STDIN_PIPE and
     357                 :            :  * %G_SUBPROCESS_FLAGS_STDIN_INHERIT).
     358                 :            :  *
     359                 :            :  * You may also not set a flag that conflicts with a previous call to a
     360                 :            :  * function like g_subprocess_launcher_set_stdin_file_path() or
     361                 :            :  * g_subprocess_launcher_take_stdout_fd().
     362                 :            :  *
     363                 :            :  * Since: 2.40
     364                 :            :  **/
     365                 :            : void
     366                 :          3 : g_subprocess_launcher_set_flags (GSubprocessLauncher *self,
     367                 :            :                                  GSubprocessFlags     flags)
     368                 :            : {
     369                 :          3 :   const gchar *stdin_path = NULL, *stdout_path = NULL, *stderr_path = NULL;
     370                 :          3 :   gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
     371                 :            : 
     372                 :            : #ifdef G_OS_UNIX
     373                 :          3 :   stdin_fd = self->stdin_fd;
     374                 :          3 :   stdout_fd = self->stdout_fd;
     375                 :          3 :   stderr_fd = self->stderr_fd;
     376                 :          3 :   stdin_path = self->stdin_path;
     377                 :          3 :   stdout_path = self->stdout_path;
     378                 :          3 :   stderr_path = self->stderr_path;
     379                 :            : #endif
     380                 :            : 
     381   [ +  -  +  - ]:          6 :   if (verify_disposition ("stdin", flags & ALL_STDIN_FLAGS, stdin_fd, stdin_path) &&
     382         [ +  - ]:          6 :       verify_disposition ("stdout", flags & ALL_STDOUT_FLAGS, stdout_fd, stdout_path) &&
     383                 :          3 :       verify_disposition ("stderr", flags & ALL_STDERR_FLAGS, stderr_fd, stderr_path))
     384                 :          3 :     self->flags = flags;
     385                 :          3 : }
     386                 :            : 
     387                 :            : #ifdef G_OS_UNIX
     388                 :            : static void
     389                 :          1 : assign_fd (gint *fd_ptr, gint fd)
     390                 :            : {
     391                 :            :   gint flags;
     392                 :            : 
     393         [ -  + ]:          1 :   if (*fd_ptr != -1)
     394                 :          0 :     close (*fd_ptr);
     395                 :            : 
     396                 :          1 :   *fd_ptr = fd;
     397                 :            : 
     398         [ +  - ]:          1 :   if (fd != -1)
     399                 :            :     {
     400                 :            :       /* best effort */
     401                 :          1 :       flags = fcntl (fd, F_GETFD);
     402         [ +  - ]:          1 :       if (~flags & FD_CLOEXEC)
     403                 :          1 :         fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
     404                 :            :     }
     405                 :          1 : }
     406                 :            : 
     407                 :            : /**
     408                 :            :  * g_subprocess_launcher_set_stdin_file_path:
     409                 :            :  * @self: a #GSubprocessLauncher
     410                 :            :  * @path: (type filename) (nullable): a filename or %NULL
     411                 :            :  *
     412                 :            :  * Sets the file path to use as the stdin for spawned processes.
     413                 :            :  *
     414                 :            :  * If @path is %NULL then any previously given path is unset.
     415                 :            :  *
     416                 :            :  * The file must exist or spawning the process will fail.
     417                 :            :  *
     418                 :            :  * You may not set a stdin file path if a stdin fd is already set or if
     419                 :            :  * the launcher flags contain any flags directing stdin elsewhere.
     420                 :            :  *
     421                 :            :  * This feature is only available on UNIX.
     422                 :            :  *
     423                 :            :  * Since: 2.40
     424                 :            :  **/
     425                 :            : void
     426                 :          0 : g_subprocess_launcher_set_stdin_file_path (GSubprocessLauncher *self,
     427                 :            :                                            const gchar         *path)
     428                 :            : {
     429         [ #  # ]:          0 :   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, self->stdin_fd, path))
     430                 :            :     {
     431                 :          0 :       g_free (self->stdin_path);
     432                 :          0 :       self->stdin_path = g_strdup (path);
     433                 :            :     }
     434                 :          0 : }
     435                 :            : 
     436                 :            : /**
     437                 :            :  * g_subprocess_launcher_take_stdin_fd:
     438                 :            :  * @self: a #GSubprocessLauncher
     439                 :            :  * @fd: a file descriptor, or -1
     440                 :            :  *
     441                 :            :  * Sets the file descriptor to use as the stdin for spawned processes.
     442                 :            :  *
     443                 :            :  * If @fd is -1 then any previously given fd is unset.
     444                 :            :  *
     445                 :            :  * Note that if your intention is to have the stdin of the calling
     446                 :            :  * process inherited by the child then %G_SUBPROCESS_FLAGS_STDIN_INHERIT
     447                 :            :  * is a better way to go about doing that.
     448                 :            :  *
     449                 :            :  * The passed @fd is noted but will not be touched in the current
     450                 :            :  * process.  It is therefore necessary that it be kept open by the
     451                 :            :  * caller until the subprocess is spawned.  The file descriptor will
     452                 :            :  * also not be explicitly closed on the child side, so it must be marked
     453                 :            :  * O_CLOEXEC if that's what you want.
     454                 :            :  *
     455                 :            :  * You may not set a stdin fd if a stdin file path is already set or if
     456                 :            :  * the launcher flags contain any flags directing stdin elsewhere.
     457                 :            :  *
     458                 :            :  * This feature is only available on UNIX.
     459                 :            :  *
     460                 :            :  * Since: 2.40
     461                 :            :  **/
     462                 :            : void
     463                 :          0 : g_subprocess_launcher_take_stdin_fd (GSubprocessLauncher *self,
     464                 :            :                                      gint                 fd)
     465                 :            : {
     466         [ #  # ]:          0 :   if (verify_disposition ("stdin", self->flags & ALL_STDIN_FLAGS, fd, self->stdin_path))
     467                 :          0 :     assign_fd (&self->stdin_fd, fd);
     468                 :          0 : }
     469                 :            : 
     470                 :            : /**
     471                 :            :  * g_subprocess_launcher_set_stdout_file_path:
     472                 :            :  * @self: a #GSubprocessLauncher
     473                 :            :  * @path: (type filename) (nullable): a filename or %NULL
     474                 :            :  *
     475                 :            :  * Sets the file path to use as the stdout for spawned processes.
     476                 :            :  *
     477                 :            :  * If @path is %NULL then any previously given path is unset.
     478                 :            :  *
     479                 :            :  * The file will be created or truncated when the process is spawned, as
     480                 :            :  * would be the case if using '>' at the shell.
     481                 :            :  *
     482                 :            :  * You may not set a stdout file path if a stdout fd is already set or
     483                 :            :  * if the launcher flags contain any flags directing stdout elsewhere.
     484                 :            :  *
     485                 :            :  * This feature is only available on UNIX.
     486                 :            :  *
     487                 :            :  * Since: 2.40
     488                 :            :  **/
     489                 :            : void
     490                 :          1 : g_subprocess_launcher_set_stdout_file_path (GSubprocessLauncher *self,
     491                 :            :                                             const gchar         *path)
     492                 :            : {
     493         [ +  - ]:          1 :   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, self->stdout_fd, path))
     494                 :            :     {
     495                 :          1 :       g_free (self->stdout_path);
     496                 :          1 :       self->stdout_path = g_strdup (path);
     497                 :            :     }
     498                 :          1 : }
     499                 :            : 
     500                 :            : /**
     501                 :            :  * g_subprocess_launcher_take_stdout_fd:
     502                 :            :  * @self: a #GSubprocessLauncher
     503                 :            :  * @fd: a file descriptor, or -1
     504                 :            :  *
     505                 :            :  * Sets the file descriptor to use as the stdout for spawned processes.
     506                 :            :  *
     507                 :            :  * If @fd is -1 then any previously given fd is unset.
     508                 :            :  *
     509                 :            :  * Note that the default behaviour is to pass stdout through to the
     510                 :            :  * stdout of the parent process.
     511                 :            :  *
     512                 :            :  * The passed @fd is noted but will not be touched in the current
     513                 :            :  * process.  It is therefore necessary that it be kept open by the
     514                 :            :  * caller until the subprocess is spawned.  The file descriptor will
     515                 :            :  * also not be explicitly closed on the child side, so it must be marked
     516                 :            :  * O_CLOEXEC if that's what you want.
     517                 :            :  *
     518                 :            :  * You may not set a stdout fd if a stdout file path is already set or
     519                 :            :  * if the launcher flags contain any flags directing stdout elsewhere.
     520                 :            :  *
     521                 :            :  * This feature is only available on UNIX.
     522                 :            :  *
     523                 :            :  * Since: 2.40
     524                 :            :  **/
     525                 :            : void
     526                 :          1 : g_subprocess_launcher_take_stdout_fd (GSubprocessLauncher *self,
     527                 :            :                                       gint                 fd)
     528                 :            : {
     529         [ +  - ]:          1 :   if (verify_disposition ("stdout", self->flags & ALL_STDOUT_FLAGS, fd, self->stdout_path))
     530                 :          1 :     assign_fd (&self->stdout_fd, fd);
     531                 :          1 : }
     532                 :            : 
     533                 :            : /**
     534                 :            :  * g_subprocess_launcher_set_stderr_file_path:
     535                 :            :  * @self: a #GSubprocessLauncher
     536                 :            :  * @path: (type filename) (nullable): a filename or %NULL
     537                 :            :  *
     538                 :            :  * Sets the file path to use as the stderr for spawned processes.
     539                 :            :  *
     540                 :            :  * If @path is %NULL then any previously given path is unset.
     541                 :            :  *
     542                 :            :  * The file will be created or truncated when the process is spawned, as
     543                 :            :  * would be the case if using '2>' at the shell.
     544                 :            :  *
     545                 :            :  * If you want to send both stdout and stderr to the same file then use
     546                 :            :  * %G_SUBPROCESS_FLAGS_STDERR_MERGE.
     547                 :            :  *
     548                 :            :  * You may not set a stderr file path if a stderr fd is already set or
     549                 :            :  * if the launcher flags contain any flags directing stderr elsewhere.
     550                 :            :  *
     551                 :            :  * This feature is only available on UNIX.
     552                 :            :  *
     553                 :            :  * Since: 2.40
     554                 :            :  **/
     555                 :            : void
     556                 :          0 : g_subprocess_launcher_set_stderr_file_path (GSubprocessLauncher *self,
     557                 :            :                                             const gchar         *path)
     558                 :            : {
     559         [ #  # ]:          0 :   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, self->stderr_fd, path))
     560                 :            :     {
     561                 :          0 :       g_free (self->stderr_path);
     562                 :          0 :       self->stderr_path = g_strdup (path);
     563                 :            :     }
     564                 :          0 : }
     565                 :            : 
     566                 :            : /**
     567                 :            :  * g_subprocess_launcher_take_stderr_fd:
     568                 :            :  * @self: a #GSubprocessLauncher
     569                 :            :  * @fd: a file descriptor, or -1
     570                 :            :  *
     571                 :            :  * Sets the file descriptor to use as the stderr for spawned processes.
     572                 :            :  *
     573                 :            :  * If @fd is -1 then any previously given fd is unset.
     574                 :            :  *
     575                 :            :  * Note that the default behaviour is to pass stderr through to the
     576                 :            :  * stderr of the parent process.
     577                 :            :  *
     578                 :            :  * The passed @fd belongs to the #GSubprocessLauncher.  It will be
     579                 :            :  * automatically closed when the launcher is finalized.  The file
     580                 :            :  * descriptor will also be closed on the child side when executing the
     581                 :            :  * spawned process.
     582                 :            :  *
     583                 :            :  * You may not set a stderr fd if a stderr file path is already set or
     584                 :            :  * if the launcher flags contain any flags directing stderr elsewhere.
     585                 :            :  *
     586                 :            :  * This feature is only available on UNIX.
     587                 :            :  *
     588                 :            :  * Since: 2.40
     589                 :            :  **/
     590                 :            : void
     591                 :          0 : g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self,
     592                 :            :                                      gint                 fd)
     593                 :            : {
     594         [ #  # ]:          0 :   if (verify_disposition ("stderr", self->flags & ALL_STDERR_FLAGS, fd, self->stderr_path))
     595                 :          0 :     assign_fd (&self->stderr_fd, fd);
     596                 :          0 : }
     597                 :            : 
     598                 :            : /**
     599                 :            :  * g_subprocess_launcher_take_fd:
     600                 :            :  * @self: a #GSubprocessLauncher
     601                 :            :  * @source_fd: File descriptor in parent process
     602                 :            :  * @target_fd: Target descriptor for child process
     603                 :            :  *
     604                 :            :  * Transfer an arbitrary file descriptor from parent process to the
     605                 :            :  * child.  This function takes ownership of the @source_fd; it will be closed
     606                 :            :  * in the parent when @self is freed.
     607                 :            :  *
     608                 :            :  * By default, all file descriptors from the parent will be closed.
     609                 :            :  * This function allows you to create (for example) a custom `pipe()` or
     610                 :            :  * `socketpair()` before launching the process, and choose the target
     611                 :            :  * descriptor in the child.
     612                 :            :  *
     613                 :            :  * An example use case is GNUPG, which has a command line argument
     614                 :            :  * `--passphrase-fd` providing a file descriptor number where it expects
     615                 :            :  * the passphrase to be written.
     616                 :            :  */
     617                 :            : void
     618                 :         15 : g_subprocess_launcher_take_fd (GSubprocessLauncher   *self,
     619                 :            :                                gint                   source_fd,
     620                 :            :                                gint                   target_fd)
     621                 :            : {
     622   [ +  -  +  - ]:         15 :   if (self->source_fds != NULL && self->target_fds != NULL)
     623                 :            :     {
     624                 :         15 :       g_array_append_val (self->source_fds, source_fd);
     625                 :         15 :       g_array_append_val (self->target_fds, target_fd);
     626                 :            :     }
     627                 :         15 : }
     628                 :            : 
     629                 :            : /**
     630                 :            :  * g_subprocess_launcher_close:
     631                 :            :  * @self: a #GSubprocessLauncher
     632                 :            :  *
     633                 :            :  * Closes all the file descriptors previously passed to the object with
     634                 :            :  * g_subprocess_launcher_take_fd(), g_subprocess_launcher_take_stderr_fd(), etc.
     635                 :            :  *
     636                 :            :  * After calling this method, any subsequent calls to g_subprocess_launcher_spawn() or g_subprocess_launcher_spawnv() will
     637                 :            :  * return %G_IO_ERROR_CLOSED. This method is idempotent if
     638                 :            :  * called more than once.
     639                 :            :  *
     640                 :            :  * This function is called automatically when the #GSubprocessLauncher
     641                 :            :  * is disposed, but is provided separately so that garbage collected
     642                 :            :  * language bindings can call it earlier to guarantee when FDs are closed.
     643                 :            :  *
     644                 :            :  * Since: 2.68
     645                 :            :  */
     646                 :            : void
     647                 :         22 : g_subprocess_launcher_close (GSubprocessLauncher *self)
     648                 :            : {
     649                 :            :   guint i;
     650                 :            : 
     651                 :         22 :   g_return_if_fail (G_IS_SUBPROCESS_LAUNCHER (self));
     652                 :            : 
     653         [ -  + ]:         22 :   if (self->stdin_fd != -1)
     654                 :          0 :     close (self->stdin_fd);
     655                 :         22 :   self->stdin_fd = -1;
     656                 :            : 
     657         [ +  + ]:         22 :   if (self->stdout_fd != -1)
     658                 :          1 :     close (self->stdout_fd);
     659                 :         22 :   self->stdout_fd = -1;
     660                 :            : 
     661         [ -  + ]:         22 :   if (self->stderr_fd != -1)
     662                 :          0 :     close (self->stderr_fd);
     663                 :         22 :   self->stderr_fd = -1;
     664                 :            : 
     665         [ +  + ]:         22 :   if (self->source_fds)
     666                 :            :     {
     667                 :         21 :       g_assert (self->target_fds != NULL);
     668                 :         21 :       g_assert (self->source_fds->len == self->target_fds->len);
     669                 :            : 
     670                 :            :       /* Note: Don’t close the target_fds, as they’re only valid FDs in the
     671                 :            :        * child process. This code never executes in the child process. */
     672         [ +  + ]:         36 :       for (i = 0; i < self->source_fds->len; i++)
     673                 :         15 :         (void) close (g_array_index (self->source_fds, int, i));
     674                 :            : 
     675                 :         21 :       g_clear_pointer (&self->source_fds, g_array_unref);
     676                 :         21 :       g_clear_pointer (&self->target_fds, g_array_unref);
     677                 :            :     }
     678                 :            : 
     679                 :         22 :   self->closed_fd = TRUE;
     680                 :            : }
     681                 :            : 
     682                 :            : /**
     683                 :            :  * g_subprocess_launcher_set_child_setup: (skip)
     684                 :            :  * @self: a #GSubprocessLauncher
     685                 :            :  * @child_setup: (closure user_data): a #GSpawnChildSetupFunc to use as the child setup function
     686                 :            :  * @user_data: user data for @child_setup
     687                 :            :  * @destroy_notify: a #GDestroyNotify for @user_data
     688                 :            :  *
     689                 :            :  * Sets up a child setup function.
     690                 :            :  *
     691                 :            :  * The child setup function will be called after fork() but before
     692                 :            :  * exec() on the child's side.
     693                 :            :  *
     694                 :            :  * @destroy_notify will not be automatically called on the child's side
     695                 :            :  * of the fork().  It will only be called when the last reference on the
     696                 :            :  * #GSubprocessLauncher is dropped or when a new child setup function is
     697                 :            :  * given.
     698                 :            :  *
     699                 :            :  * %NULL can be given as @child_setup to disable the functionality.
     700                 :            :  *
     701                 :            :  * Child setup functions are only available on UNIX.
     702                 :            :  *
     703                 :            :  * Since: 2.40
     704                 :            :  **/
     705                 :            : void
     706                 :          4 : g_subprocess_launcher_set_child_setup (GSubprocessLauncher  *self,
     707                 :            :                                        GSpawnChildSetupFunc  child_setup,
     708                 :            :                                        gpointer              user_data,
     709                 :            :                                        GDestroyNotify        destroy_notify)
     710                 :            : {
     711         [ -  + ]:          4 :   if (self->child_setup_destroy_notify)
     712                 :          0 :     (* self->child_setup_destroy_notify) (self->child_setup_user_data);
     713                 :            : 
     714                 :          4 :   self->child_setup_func = child_setup;
     715                 :          4 :   self->child_setup_user_data = user_data;
     716                 :          4 :   self->child_setup_destroy_notify = destroy_notify;
     717                 :          4 : }
     718                 :            : #endif
     719                 :            : 
     720                 :            : /**
     721                 :            :  * g_subprocess_launcher_spawn:
     722                 :            :  * @self: a #GSubprocessLauncher
     723                 :            :  * @error: Error
     724                 :            :  * @argv0: Command line arguments
     725                 :            :  * @...: Continued arguments, %NULL terminated
     726                 :            :  *
     727                 :            :  * Creates a #GSubprocess given a provided varargs list of arguments.
     728                 :            :  *
     729                 :            :  * Since: 2.40
     730                 :            :  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
     731                 :            :  **/
     732                 :            : GSubprocess *
     733                 :          3 : g_subprocess_launcher_spawn (GSubprocessLauncher  *launcher,
     734                 :            :                              GError              **error,
     735                 :            :                              const gchar          *argv0,
     736                 :            :                              ...)
     737                 :            : {
     738                 :            :   GSubprocess *result;
     739                 :            :   GPtrArray *args;
     740                 :            :   const gchar *arg;
     741                 :            :   va_list ap;
     742                 :            : 
     743                 :          3 :   g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL);
     744                 :          3 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     745                 :            : 
     746                 :          3 :   args = g_ptr_array_new ();
     747                 :            : 
     748                 :          3 :   va_start (ap, argv0);
     749                 :          3 :   g_ptr_array_add (args, (gchar *) argv0);
     750         [ +  + ]:          6 :   while ((arg = va_arg (ap, const gchar *)))
     751                 :          3 :     g_ptr_array_add (args, (gchar *) arg);
     752                 :            : 
     753                 :          3 :   g_ptr_array_add (args, NULL);
     754                 :          3 :   va_end (ap);
     755                 :            : 
     756                 :          3 :   result = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
     757                 :            : 
     758                 :          3 :   g_ptr_array_free (args, TRUE);
     759                 :            : 
     760                 :          3 :   return result;
     761                 :            : 
     762                 :            : }
     763                 :            : 
     764                 :            : /**
     765                 :            :  * g_subprocess_launcher_spawnv:
     766                 :            :  * @self: a #GSubprocessLauncher
     767                 :            :  * @argv: (array zero-terminated=1) (element-type filename): Command line arguments
     768                 :            :  * @error: Error
     769                 :            :  *
     770                 :            :  * Creates a #GSubprocess given a provided array of arguments.
     771                 :            :  *
     772                 :            :  * Since: 2.40
     773                 :            :  * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error will be set)
     774                 :            :  **/
     775                 :            : GSubprocess *
     776                 :         22 : g_subprocess_launcher_spawnv (GSubprocessLauncher  *launcher,
     777                 :            :                               const gchar * const  *argv,
     778                 :            :                               GError              **error)
     779                 :            : {
     780                 :            :   GSubprocess *subprocess;
     781                 :            : 
     782                 :         22 :   g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL);
     783                 :            : 
     784                 :            : #ifdef G_OS_UNIX
     785         [ +  + ]:         22 :   if (launcher->closed_fd)
     786                 :            :     {
     787                 :          1 :       g_set_error (error,
     788                 :            :                    G_IO_ERROR,
     789                 :            :                    G_IO_ERROR_CLOSED,
     790                 :            :                    "Can't spawn a new child because a passed file descriptor has been closed.");
     791                 :          1 :       return NULL;
     792                 :            :     }
     793                 :            : #endif
     794                 :            : 
     795                 :         21 :   subprocess = g_object_new (G_TYPE_SUBPROCESS,
     796                 :            :                              "argv", argv,
     797                 :         21 :                              "flags", launcher->flags,
     798                 :            :                              NULL);
     799                 :         21 :   g_subprocess_set_launcher (subprocess, launcher);
     800                 :            : 
     801         [ -  + ]:         21 :   if (!g_initable_init (G_INITABLE (subprocess), NULL, error))
     802                 :            :     {
     803                 :          0 :       g_object_unref (subprocess);
     804                 :          0 :       return NULL;
     805                 :            :     }
     806                 :            : 
     807                 :         21 :   return subprocess;
     808                 :            : }

Generated by: LCOV version 1.14