Coverage Report

Created: 2025-09-05 06:29

/src/gstreamer/subprojects/glib-2.82.5/glib/gspawn-posix.c
Line
Count
Source (jump to first uncovered line)
1
/* gspawn.c - Process launching
2
 *
3
 *  Copyright 2000 Red Hat, Inc.
4
 *  g_execvpe implementation based on GNU libc execvp:
5
 *   Copyright 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
6
 *
7
 * SPDX-License-Identifier: LGPL-2.1-or-later
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this library; if not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "config.h"
24
25
#include <sys/time.h>
26
#include <sys/types.h>
27
#include <sys/wait.h>
28
#include <unistd.h>
29
#include <errno.h>
30
#include <fcntl.h>
31
#include <signal.h>
32
#include <string.h>
33
#include <stdlib.h>   /* for fdwalk */
34
#include <dirent.h>
35
#include <unistd.h>
36
37
#ifdef HAVE_SPAWN_H
38
#include <spawn.h>
39
#endif /* HAVE_SPAWN_H */
40
41
#ifdef HAVE_CRT_EXTERNS_H
42
#include <crt_externs.h> /* for _NSGetEnviron */
43
#endif
44
45
#ifdef HAVE_SYS_SELECT_H
46
#include <sys/select.h>
47
#endif /* HAVE_SYS_SELECT_H */
48
49
#ifdef HAVE_SYS_RESOURCE_H
50
#include <sys/resource.h>
51
#endif /* HAVE_SYS_RESOURCE_H */
52
53
#if defined(__linux__) || defined(__DragonFly__)
54
#include <sys/syscall.h>  /* for syscall and SYS_getdents64 */
55
#endif
56
57
#include "gspawn.h"
58
#include "gspawn-private.h"
59
#include "gthread.h"
60
#include "gtrace-private.h"
61
#include "glib/gstdio.h"
62
63
#include "genviron.h"
64
#include "gmem.h"
65
#include "gshell.h"
66
#include "gstring.h"
67
#include "gstrfuncs.h"
68
#include "gtestutils.h"
69
#include "gutils.h"
70
#include "glibintl.h"
71
#include "glib-unix.h"
72
73
#if defined(__APPLE__) && defined(HAVE_LIBPROC_H)
74
#include <libproc.h>
75
#include <sys/proc_info.h>
76
#endif
77
78
2
#define INHERITS_OR_NULL_STDIN  (G_SPAWN_STDIN_FROM_DEV_NULL | G_SPAWN_CHILD_INHERITS_STDIN)
79
2
#define INHERITS_OR_NULL_STDOUT (G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_CHILD_INHERITS_STDOUT)
80
2
#define INHERITS_OR_NULL_STDERR (G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_CHILD_INHERITS_STDERR)
81
82
0
#define IS_STD_FILENO(_fd) ((_fd >= STDIN_FILENO) && (_fd <= STDERR_FILENO))
83
0
#define IS_VALID_FILENO(_fd) (_fd >= 0)
84
85
/* posix_spawn() is assumed the fastest way to spawn, but glibc's
86
 * implementation was buggy before glibc 2.24, so avoid it on old versions.
87
 */
88
#ifdef HAVE_POSIX_SPAWN
89
#ifdef __GLIBC__
90
91
#if __GLIBC_PREREQ(2,24)
92
#define POSIX_SPAWN_AVAILABLE
93
#endif
94
95
#else /* !__GLIBC__ */
96
/* Assume that all non-glibc posix_spawn implementations are fine. */
97
#define POSIX_SPAWN_AVAILABLE
98
#endif /* __GLIBC__ */
99
#endif /* HAVE_POSIX_SPAWN */
100
101
#ifdef HAVE__NSGETENVIRON
102
#define environ (*_NSGetEnviron())
103
#else
104
extern char **environ;
105
#endif
106
107
#ifndef O_CLOEXEC
108
#define O_CLOEXEC 0
109
#else
110
#define HAVE_O_CLOEXEC 1
111
#endif
112
113
static gint g_execute (const gchar  *file,
114
                       gchar       **argv,
115
                       gchar       **argv_buffer,
116
                       gsize         argv_buffer_len,
117
                       gchar       **envp,
118
                       const gchar  *search_path,
119
                       gchar        *search_path_buffer,
120
                       gsize         search_path_buffer_len);
121
122
static gboolean fork_exec (gboolean              intermediate_child,
123
                           const gchar          *working_directory,
124
                           const gchar * const  *argv,
125
                           const gchar * const  *envp,
126
                           gboolean              close_descriptors,
127
                           gboolean              search_path,
128
                           gboolean              search_path_from_envp,
129
                           gboolean              stdout_to_null,
130
                           gboolean              stderr_to_null,
131
                           gboolean              child_inherits_stdin,
132
                           gboolean              file_and_argv_zero,
133
                           gboolean              cloexec_pipes,
134
                           GSpawnChildSetupFunc  child_setup,
135
                           gpointer              user_data,
136
                           GPid                 *child_pid,
137
                           gint                 *stdin_pipe_out,
138
                           gint                 *stdout_pipe_out,
139
                           gint                 *stderr_pipe_out,
140
                           gint                  stdin_fd,
141
                           gint                  stdout_fd,
142
                           gint                  stderr_fd,
143
                           const gint           *source_fds,
144
                           const gint           *target_fds,
145
                           gsize                 n_fds,
146
                           GError              **error);
147
148
G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
149
G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
150
151
/* Some versions of OS X define READ_OK in public headers */
152
#undef READ_OK
153
154
typedef enum
155
{
156
  READ_FAILED = 0, /* FALSE */
157
  READ_OK,
158
  READ_EOF
159
} ReadResult;
160
161
static ReadResult
162
read_data (GString *str,
163
           gint     fd,
164
           GError **error)
165
0
{
166
0
  gssize bytes;
167
0
  gchar buf[4096];
168
169
0
 again:
170
0
  bytes = read (fd, buf, 4096);
171
172
0
  if (bytes == 0)
173
0
    return READ_EOF;
174
0
  else if (bytes > 0)
175
0
    {
176
0
      g_string_append_len (str, buf, bytes);
177
0
      return READ_OK;
178
0
    }
179
0
  else if (errno == EINTR)
180
0
    goto again;
181
0
  else
182
0
    {
183
0
      int errsv = errno;
184
185
0
      g_set_error (error,
186
0
                   G_SPAWN_ERROR,
187
0
                   G_SPAWN_ERROR_READ,
188
0
                   _("Failed to read data from child process (%s)"),
189
0
                   g_strerror (errsv));
190
191
0
      return READ_FAILED;
192
0
    }
193
0
}
194
195
gboolean
196
g_spawn_sync_impl (const gchar           *working_directory,
197
                   gchar                **argv,
198
                   gchar                **envp,
199
                   GSpawnFlags            flags,
200
                   GSpawnChildSetupFunc   child_setup,
201
                   gpointer               user_data,
202
                   gchar                **standard_output,
203
                   gchar                **standard_error,
204
                   gint                  *wait_status,
205
                   GError               **error)
206
0
{
207
0
  gint outpipe = -1;
208
0
  gint errpipe = -1;
209
0
  GPid pid;
210
0
  gint ret;
211
0
  GString *outstr = NULL;
212
0
  GString *errstr = NULL;
213
0
  gboolean failed;
214
0
  gint status;
215
  
216
0
  g_return_val_if_fail (argv != NULL, FALSE);
217
0
  g_return_val_if_fail (argv[0] != NULL, FALSE);
218
0
  g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
219
0
  g_return_val_if_fail (standard_output == NULL ||
220
0
                        !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
221
0
  g_return_val_if_fail (standard_error == NULL ||
222
0
                        !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
223
  
224
  /* Just to ensure segfaults if callers try to use
225
   * these when an error is reported.
226
   */
227
0
  if (standard_output)
228
0
    *standard_output = NULL;
229
230
0
  if (standard_error)
231
0
    *standard_error = NULL;
232
  
233
0
  if (!fork_exec (FALSE,
234
0
                  working_directory,
235
0
                  (const gchar * const *) argv,
236
0
                  (const gchar * const *) envp,
237
0
                  !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
238
0
                  (flags & G_SPAWN_SEARCH_PATH) != 0,
239
0
                  (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
240
0
                  (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
241
0
                  (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
242
0
                  (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
243
0
                  (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
244
0
                  (flags & G_SPAWN_CLOEXEC_PIPES) != 0,
245
0
                  child_setup,
246
0
                  user_data,
247
0
                  &pid,
248
0
                  NULL,
249
0
                  standard_output ? &outpipe : NULL,
250
0
                  standard_error ? &errpipe : NULL,
251
0
                  -1, -1, -1,
252
0
                  NULL, NULL, 0,
253
0
                  error))
254
0
    return FALSE;
255
256
  /* Read data from child. */
257
  
258
0
  failed = FALSE;
259
260
0
  if (outpipe >= 0)
261
0
    {
262
0
      outstr = g_string_new (NULL);
263
0
    }
264
      
265
0
  if (errpipe >= 0)
266
0
    {
267
0
      errstr = g_string_new (NULL);
268
0
    }
269
270
  /* Read data until we get EOF on both pipes. */
271
0
  while (!failed &&
272
0
         (outpipe >= 0 ||
273
0
          errpipe >= 0))
274
0
    {
275
      /* Any negative FD in the array is ignored, so we can use a fixed length.
276
       * We can use UNIX FDs here without worrying about Windows HANDLEs because
277
       * the Windows implementation is entirely in gspawn-win32.c. */
278
0
      GPollFD fds[] =
279
0
        {
280
0
          { outpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 },
281
0
          { errpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 },
282
0
        };
283
284
0
      ret = g_poll (fds, G_N_ELEMENTS (fds), -1  /* no timeout */);
285
286
0
      if (ret < 0)
287
0
        {
288
0
          int errsv = errno;
289
290
0
    if (errno == EINTR)
291
0
      continue;
292
293
0
          failed = TRUE;
294
295
0
          g_set_error (error,
296
0
                       G_SPAWN_ERROR,
297
0
                       G_SPAWN_ERROR_READ,
298
0
                       _("Unexpected error in reading data from a child process (%s)"),
299
0
                       g_strerror (errsv));
300
              
301
0
          break;
302
0
        }
303
304
0
      if (outpipe >= 0 && fds[0].revents != 0)
305
0
        {
306
0
          switch (read_data (outstr, outpipe, error))
307
0
            {
308
0
            case READ_FAILED:
309
0
              failed = TRUE;
310
0
              break;
311
0
            case READ_EOF:
312
0
              g_clear_fd (&outpipe, NULL);
313
0
              break;
314
0
            default:
315
0
              break;
316
0
            }
317
318
0
          if (failed)
319
0
            break;
320
0
        }
321
322
0
      if (errpipe >= 0 && fds[1].revents != 0)
323
0
        {
324
0
          switch (read_data (errstr, errpipe, error))
325
0
            {
326
0
            case READ_FAILED:
327
0
              failed = TRUE;
328
0
              break;
329
0
            case READ_EOF:
330
0
              g_clear_fd (&errpipe, NULL);
331
0
              break;
332
0
            default:
333
0
              break;
334
0
            }
335
336
0
          if (failed)
337
0
            break;
338
0
        }
339
0
    }
340
341
  /* These should only be open still if we had an error.  */
342
0
  g_clear_fd (&outpipe, NULL);
343
0
  g_clear_fd (&errpipe, NULL);
344
345
  /* Wait for child to exit, even if we have
346
   * an error pending.
347
   */
348
0
 again:
349
      
350
0
  ret = waitpid (pid, &status, 0);
351
352
0
  if (ret < 0)
353
0
    {
354
0
      if (errno == EINTR)
355
0
        goto again;
356
0
      else if (errno == ECHILD)
357
0
        {
358
0
          if (wait_status)
359
0
            {
360
0
              g_warning ("In call to g_spawn_sync(), wait status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes.");
361
0
            }
362
0
          else
363
0
            {
364
              /* We don't need the wait status. */
365
0
            }
366
0
        }
367
0
      else
368
0
        {
369
0
          if (!failed) /* avoid error pileups */
370
0
            {
371
0
              int errsv = errno;
372
373
0
              failed = TRUE;
374
                  
375
0
              g_set_error (error,
376
0
                           G_SPAWN_ERROR,
377
0
                           G_SPAWN_ERROR_READ,
378
0
                           _("Unexpected error in waitpid() (%s)"),
379
0
                           g_strerror (errsv));
380
0
            }
381
0
        }
382
0
    }
383
  
384
0
  if (failed)
385
0
    {
386
0
      if (outstr)
387
0
        g_string_free (outstr, TRUE);
388
0
      if (errstr)
389
0
        g_string_free (errstr, TRUE);
390
391
0
      return FALSE;
392
0
    }
393
0
  else
394
0
    {
395
0
      if (wait_status)
396
0
        *wait_status = status;
397
      
398
0
      if (standard_output)        
399
0
        *standard_output = g_string_free (outstr, FALSE);
400
401
0
      if (standard_error)
402
0
        *standard_error = g_string_free (errstr, FALSE);
403
404
0
      return TRUE;
405
0
    }
406
0
}
407
408
gboolean
409
g_spawn_async_with_pipes_and_fds_impl (const gchar           *working_directory,
410
                                       const gchar * const   *argv,
411
                                       const gchar * const   *envp,
412
                                       GSpawnFlags            flags,
413
                                       GSpawnChildSetupFunc   child_setup,
414
                                       gpointer               user_data,
415
                                       gint                   stdin_fd,
416
                                       gint                   stdout_fd,
417
                                       gint                   stderr_fd,
418
                                       const gint            *source_fds,
419
                                       const gint            *target_fds,
420
                                       gsize                  n_fds,
421
                                       GPid                  *child_pid_out,
422
                                       gint                  *stdin_pipe_out,
423
                                       gint                  *stdout_pipe_out,
424
                                       gint                  *stderr_pipe_out,
425
                                       GError               **error)
426
2
{
427
2
  g_return_val_if_fail (argv != NULL, FALSE);
428
2
  g_return_val_if_fail (argv[0] != NULL, FALSE);
429
  /* can’t both inherit and set pipes to /dev/null */
430
2
  g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDIN) != INHERITS_OR_NULL_STDIN, FALSE);
431
2
  g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDOUT) != INHERITS_OR_NULL_STDOUT, FALSE);
432
2
  g_return_val_if_fail ((flags & INHERITS_OR_NULL_STDERR) != INHERITS_OR_NULL_STDERR, FALSE);
433
  /* can’t use pipes and stdin/stdout/stderr FDs */
434
2
  g_return_val_if_fail (stdin_pipe_out == NULL || stdin_fd < 0, FALSE);
435
2
  g_return_val_if_fail (stdout_pipe_out == NULL || stdout_fd < 0, FALSE);
436
2
  g_return_val_if_fail (stderr_pipe_out == NULL || stderr_fd < 0, FALSE);
437
438
2
  if ((flags & INHERITS_OR_NULL_STDIN) != 0)
439
0
    stdin_pipe_out = NULL;
440
2
  if ((flags & INHERITS_OR_NULL_STDOUT) != 0)
441
0
    stdout_pipe_out = NULL;
442
2
  if ((flags & INHERITS_OR_NULL_STDERR) != 0)
443
0
    stderr_pipe_out = NULL;
444
445
2
  return fork_exec (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
446
2
                    working_directory,
447
2
                    (const gchar * const *) argv,
448
2
                    (const gchar * const *) envp,
449
2
                    !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
450
2
                    (flags & G_SPAWN_SEARCH_PATH) != 0,
451
2
                    (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0,
452
2
                    (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
453
2
                    (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
454
2
                    (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
455
2
                    (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
456
2
                    (flags & G_SPAWN_CLOEXEC_PIPES) != 0,
457
2
                    child_setup,
458
2
                    user_data,
459
2
                    child_pid_out,
460
2
                    stdin_pipe_out,
461
2
                    stdout_pipe_out,
462
2
                    stderr_pipe_out,
463
2
                    stdin_fd,
464
2
                    stdout_fd,
465
2
                    stderr_fd,
466
2
                    source_fds,
467
2
                    target_fds,
468
2
                    n_fds,
469
2
                    error);
470
2
}
471
472
gboolean
473
g_spawn_check_wait_status_impl (gint     wait_status,
474
                                GError **error)
475
0
{
476
0
  gboolean ret = FALSE;
477
478
0
  if (WIFEXITED (wait_status))
479
0
    {
480
0
      if (WEXITSTATUS (wait_status) != 0)
481
0
  {
482
0
    g_set_error (error, G_SPAWN_EXIT_ERROR, WEXITSTATUS (wait_status),
483
0
           _("Child process exited with code %ld"),
484
0
           (long) WEXITSTATUS (wait_status));
485
0
    goto out;
486
0
  }
487
0
    }
488
0
  else if (WIFSIGNALED (wait_status))
489
0
    {
490
0
      g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
491
0
       _("Child process killed by signal %ld"),
492
0
       (long) WTERMSIG (wait_status));
493
0
      goto out;
494
0
    }
495
0
  else if (WIFSTOPPED (wait_status))
496
0
    {
497
0
      g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
498
0
       _("Child process stopped by signal %ld"),
499
0
       (long) WSTOPSIG (wait_status));
500
0
      goto out;
501
0
    }
502
0
  else
503
0
    {
504
0
      g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
505
0
       _("Child process exited abnormally"));
506
0
      goto out;
507
0
    }
508
509
0
  ret = TRUE;
510
0
 out:
511
0
  return ret;
512
0
}
513
514
/* This function is called between fork() and exec() and hence must be
515
 * async-signal-safe (see signal-safety(7)). */
516
static gssize
517
write_all (gint fd, gconstpointer vbuf, gsize to_write)
518
0
{
519
0
  gchar *buf = (gchar *) vbuf;
520
  
521
0
  while (to_write > 0)
522
0
    {
523
0
      gssize count = write (fd, buf, to_write);
524
0
      if (count < 0)
525
0
        {
526
0
          if (errno != EINTR)
527
0
            return FALSE;
528
0
        }
529
0
      else
530
0
        {
531
0
          to_write -= count;
532
0
          buf += count;
533
0
        }
534
0
    }
535
  
536
0
  return TRUE;
537
0
}
538
539
/* This function is called between fork() and exec() and hence must be
540
 * async-signal-safe (see signal-safety(7)). */
541
G_NORETURN
542
static void
543
write_err_and_exit (gint fd, gint msg)
544
0
{
545
0
  gint en = errno;
546
  
547
0
  write_all (fd, &msg, sizeof(msg));
548
0
  write_all (fd, &en, sizeof(en));
549
  
550
0
  _exit (1);
551
0
}
552
553
/* This function is called between fork() and exec() and hence must be
554
 * async-signal-safe (see signal-safety(7)). */
555
static void
556
set_cloexec (int fd)
557
0
{
558
0
  fcntl (fd, F_SETFD, FD_CLOEXEC);
559
0
}
560
561
/* This function is called between fork() and exec() and hence must be
562
 * async-signal-safe (see signal-safety(7)). */
563
static void
564
unset_cloexec (int fd)
565
0
{
566
0
  int flags;
567
0
  int result;
568
569
0
  flags = fcntl (fd, F_GETFD, 0);
570
571
0
  if (flags != -1)
572
0
    {
573
0
      int errsv;
574
0
      flags &= (~FD_CLOEXEC);
575
0
      do
576
0
        {
577
0
          result = fcntl (fd, F_SETFD, flags);
578
0
          errsv = errno;
579
0
        }
580
0
      while (result == -1 && errsv == EINTR);
581
0
    }
582
0
}
583
584
/* This function is called between fork() and exec() and hence must be
585
 * async-signal-safe (see signal-safety(7)). */
586
static int
587
dupfd_cloexec (int old_fd, int new_fd_min)
588
0
{
589
0
  int fd, errsv;
590
0
#ifdef F_DUPFD_CLOEXEC
591
0
  do
592
0
    {
593
0
      fd = fcntl (old_fd, F_DUPFD_CLOEXEC, new_fd_min);
594
0
      errsv = errno;
595
0
    }
596
0
  while (fd == -1 && errsv == EINTR);
597
#else
598
  /* OS X Snow Lion and earlier don't have F_DUPFD_CLOEXEC:
599
   * https://bugzilla.gnome.org/show_bug.cgi?id=710962
600
   */
601
  int result, flags;
602
  do
603
    {
604
      fd = fcntl (old_fd, F_DUPFD, new_fd_min);
605
      errsv = errno;
606
    }
607
  while (fd == -1 && errsv == EINTR);
608
  flags = fcntl (fd, F_GETFD, 0);
609
  if (flags != -1)
610
    {
611
      flags |= FD_CLOEXEC;
612
      do
613
        {
614
          result = fcntl (fd, F_SETFD, flags);
615
          errsv = errno;
616
        }
617
      while (result == -1 && errsv == EINTR);
618
    }
619
#endif
620
0
  return fd;
621
0
}
622
623
/* This function is called between fork() and exec() and hence must be
624
 * async-signal-safe (see signal-safety(7)). */
625
static gint
626
safe_dup2 (gint fd1, gint fd2)
627
0
{
628
0
  gint ret;
629
630
0
  do
631
0
    ret = dup2 (fd1, fd2);
632
0
  while (ret < 0 && (errno == EINTR || errno == EBUSY));
633
634
0
  return ret;
635
0
}
636
637
/* This function is called between fork() and exec() and hence must be
638
 * async-signal-safe (see signal-safety(7)). */
639
static gboolean
640
relocate_fd_out_of_standard_range (gint *fd)
641
0
{
642
0
  gint ret = -1;
643
0
  const int min_fileno = STDERR_FILENO + 1;
644
645
0
  do
646
0
    ret = fcntl (*fd, F_DUPFD, min_fileno);
647
0
  while (ret < 0 && errno == EINTR);
648
649
  /* Note we don't need to close the old fd, because the caller is expected
650
   * to close fds in the standard range itself.
651
   */
652
0
  if (ret >= min_fileno)
653
0
    {
654
0
      *fd = ret;
655
0
      return TRUE;
656
0
    }
657
658
0
  return FALSE;
659
0
}
660
661
/* This function is called between fork() and exec() and hence must be
662
 * async-signal-safe (see signal-safety(7)). */
663
static gint
664
safe_open (const char *path, gint mode)
665
0
{
666
0
  gint ret;
667
668
0
  do
669
0
    ret = open (path, mode);
670
0
  while (ret < 0 && errno == EINTR);
671
672
0
  return ret;
673
0
}
674
675
enum
676
{
677
  CHILD_CHDIR_FAILED,
678
  CHILD_EXEC_FAILED,
679
  CHILD_OPEN_FAILED,
680
  CHILD_DUPFD_FAILED,
681
  CHILD_FORK_FAILED,
682
  CHILD_CLOSE_FAILED,
683
};
684
685
/* This function is called between fork() and exec() and hence must be
686
 * async-signal-safe (see signal-safety(7)) until it calls exec().
687
 *
688
 * All callers must guarantee that @argv and @argv[0] are non-NULL. */
689
static void
690
do_exec (gint                  child_err_report_fd,
691
         gint                  stdin_fd,
692
         gint                  stdout_fd,
693
         gint                  stderr_fd,
694
         gint                 *source_fds,
695
         const gint           *target_fds,
696
         gsize                 n_fds,
697
         const gchar          *working_directory,
698
         const gchar * const  *argv,
699
         gchar               **argv_buffer,
700
         gsize                 argv_buffer_len,
701
         const gchar * const  *envp,
702
         gboolean              close_descriptors,
703
         const gchar          *search_path,
704
         gchar                *search_path_buffer,
705
         gsize                 search_path_buffer_len,
706
         gboolean              stdout_to_null,
707
         gboolean              stderr_to_null,
708
         gboolean              child_inherits_stdin,
709
         gboolean              file_and_argv_zero,
710
         GSpawnChildSetupFunc  child_setup,
711
         gpointer              user_data)
712
0
{
713
0
  gsize i;
714
0
  gint max_target_fd = 0;
715
716
0
  if (working_directory && chdir (working_directory) < 0)
717
0
    write_err_and_exit (child_err_report_fd,
718
0
                        CHILD_CHDIR_FAILED);
719
720
  /* It's possible the caller assigned stdin to an fd with a
721
   * file number that is supposed to be reserved for
722
   * stdout or stderr.
723
   *
724
   * If so, move it up out of the standard range, so it doesn't
725
   * cause a conflict.
726
   */
727
0
  if (IS_STD_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
728
0
    {
729
0
      int old_fd = stdin_fd;
730
731
0
      if (!relocate_fd_out_of_standard_range (&stdin_fd))
732
0
        write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
733
734
0
      if (stdout_fd == old_fd)
735
0
        stdout_fd = stdin_fd;
736
737
0
      if (stderr_fd == old_fd)
738
0
        stderr_fd = stdin_fd;
739
0
    }
740
741
  /* Redirect pipes as required
742
   *
743
   * There are two cases where we don't need to do the redirection
744
   * 1. Where the associated file descriptor is cleared/invalid
745
   * 2. When the associated file descriptor is already given the
746
   * correct file number.
747
   */
748
0
  if (IS_VALID_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
749
0
    {
750
0
      if (safe_dup2 (stdin_fd, 0) < 0)
751
0
        write_err_and_exit (child_err_report_fd,
752
0
                            CHILD_DUPFD_FAILED);
753
754
0
      set_cloexec (stdin_fd);
755
0
    }
756
0
  else if (!child_inherits_stdin)
757
0
    {
758
      /* Keep process from blocking on a read of stdin */
759
0
      gint read_null = safe_open ("/dev/null", O_RDONLY);
760
0
      if (read_null < 0)
761
0
        write_err_and_exit (child_err_report_fd,
762
0
                            CHILD_OPEN_FAILED);
763
0
      if (safe_dup2 (read_null, 0) < 0)
764
0
        write_err_and_exit (child_err_report_fd,
765
0
                            CHILD_DUPFD_FAILED);
766
0
      g_clear_fd (&read_null, NULL);
767
0
    }
768
769
  /* Like with stdin above, it's possible the caller assigned
770
   * stdout to an fd with a file number that's intruding on the
771
   * standard range.
772
   *
773
   * If so, move it out of the way, too.
774
   */
775
0
  if (IS_STD_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
776
0
    {
777
0
      int old_fd = stdout_fd;
778
779
0
      if (!relocate_fd_out_of_standard_range (&stdout_fd))
780
0
        write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
781
782
0
      if (stderr_fd == old_fd)
783
0
        stderr_fd = stdout_fd;
784
0
    }
785
786
0
  if (IS_VALID_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
787
0
    {
788
0
      if (safe_dup2 (stdout_fd, 1) < 0)
789
0
        write_err_and_exit (child_err_report_fd,
790
0
                            CHILD_DUPFD_FAILED);
791
792
0
      set_cloexec (stdout_fd);
793
0
    }
794
0
  else if (stdout_to_null)
795
0
    {
796
0
      gint write_null = safe_open ("/dev/null", O_WRONLY);
797
0
      if (write_null < 0)
798
0
        write_err_and_exit (child_err_report_fd,
799
0
                            CHILD_OPEN_FAILED);
800
0
      if (safe_dup2 (write_null, 1) < 0)
801
0
        write_err_and_exit (child_err_report_fd,
802
0
                            CHILD_DUPFD_FAILED);
803
0
      g_clear_fd (&write_null, NULL);
804
0
    }
805
806
0
  if (IS_STD_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
807
0
    {
808
0
      if (!relocate_fd_out_of_standard_range (&stderr_fd))
809
0
        write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
810
0
    }
811
812
  /* Like with stdin/stdout above, it's possible the caller assigned
813
   * stderr to an fd with a file number that's intruding on the
814
   * standard range.
815
   *
816
   * Make sure it's out of the way, also.
817
   */
818
0
  if (IS_VALID_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
819
0
    {
820
0
      if (safe_dup2 (stderr_fd, 2) < 0)
821
0
        write_err_and_exit (child_err_report_fd,
822
0
                            CHILD_DUPFD_FAILED);
823
824
0
      set_cloexec (stderr_fd);
825
0
    }
826
0
  else if (stderr_to_null)
827
0
    {
828
0
      gint write_null = safe_open ("/dev/null", O_WRONLY);
829
0
      if (write_null < 0)
830
0
        write_err_and_exit (child_err_report_fd,
831
0
                            CHILD_OPEN_FAILED);
832
0
      if (safe_dup2 (write_null, 2) < 0)
833
0
        write_err_and_exit (child_err_report_fd,
834
0
                            CHILD_DUPFD_FAILED);
835
0
      g_clear_fd (&write_null, NULL);
836
0
    }
837
838
  /* Close all file descriptors but stdin, stdout and stderr, and any of source_fds,
839
   * before we exec. Note that this includes
840
   * child_err_report_fd, which keeps the parent from blocking
841
   * forever on the other end of that pipe.
842
   */
843
0
  if (close_descriptors)
844
0
    {
845
0
      if (child_setup == NULL && n_fds == 0)
846
0
        {
847
0
          if (safe_dup2 (child_err_report_fd, 3) < 0)
848
0
            write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
849
0
          set_cloexec (3);
850
0
          if (g_closefrom (4) < 0)
851
0
            write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
852
0
          child_err_report_fd = 3;
853
0
        }
854
0
      else
855
0
        {
856
0
          if (g_fdwalk_set_cloexec (3) < 0)
857
0
            write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
858
0
        }
859
0
    }
860
0
  else
861
0
    {
862
      /* We need to do child_err_report_fd anyway */
863
0
      set_cloexec (child_err_report_fd);
864
0
    }
865
866
  /*
867
   * Work through the @source_fds and @target_fds mapping.
868
   *
869
   * Based on code originally derived from
870
   * gnome-terminal:src/terminal-screen.c:terminal_screen_child_setup(),
871
   * used under the LGPLv2+ with permission from author. (The code has
872
   * since migrated to vte:src/spawn.cc:SpawnContext::exec and is no longer
873
   * terribly similar to what we have here.)
874
   */
875
876
0
  if (n_fds > 0)
877
0
    {
878
0
      for (i = 0; i < n_fds; i++)
879
0
        max_target_fd = MAX (max_target_fd, target_fds[i]);
880
881
0
      if (max_target_fd == G_MAXINT)
882
0
        {
883
0
          errno = EINVAL;
884
0
          write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
885
0
        }
886
887
      /* If we're doing remapping fd assignments, we need to handle
888
       * the case where the user has specified e.g. 5 -> 4, 4 -> 6.
889
       * We do this by duping all source fds, taking care to ensure the new
890
       * fds are larger than any target fd to avoid introducing new conflicts.
891
       */
892
0
      for (i = 0; i < n_fds; i++)
893
0
        {
894
0
          if (source_fds[i] != target_fds[i])
895
0
            {
896
0
              source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
897
0
              if (source_fds[i] < 0)
898
0
                write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
899
0
            }
900
0
        }
901
902
0
      for (i = 0; i < n_fds; i++)
903
0
        {
904
          /* For basic fd assignments (where source == target), we can just
905
           * unset FD_CLOEXEC.
906
           */
907
0
          if (source_fds[i] == target_fds[i])
908
0
            {
909
0
              unset_cloexec (source_fds[i]);
910
0
            }
911
0
          else
912
0
            {
913
              /* If any of the @target_fds conflict with @child_err_report_fd,
914
               * dup it so it doesn’t get conflated.
915
               */
916
0
              if (target_fds[i] == child_err_report_fd)
917
0
                {
918
0
                  child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1);
919
0
                  if (child_err_report_fd < 0)
920
0
                    write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
921
0
                }
922
923
0
              if (safe_dup2 (source_fds[i], target_fds[i]) < 0)
924
0
                write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
925
926
0
              g_clear_fd (&source_fds[i], NULL);
927
0
            }
928
0
        }
929
0
    }
930
931
  /* Call user function just before we exec */
932
0
  if (child_setup)
933
0
    {
934
0
      (* child_setup) (user_data);
935
0
    }
936
937
0
  g_execute (argv[0],
938
0
             (gchar **) (file_and_argv_zero ? argv + 1 : argv),
939
0
             argv_buffer, argv_buffer_len,
940
0
             (gchar **) envp, search_path, search_path_buffer, search_path_buffer_len);
941
942
  /* Exec failed */
943
0
  write_err_and_exit (child_err_report_fd,
944
0
                      CHILD_EXEC_FAILED);
945
0
}
946
947
static gboolean
948
read_ints (int      fd,
949
           gint*    buf,
950
           gint     n_ints_in_buf,    
951
           gint    *n_ints_read,      
952
           GError **error)
953
2
{
954
2
  gsize bytes = 0;    
955
  
956
4
  while (TRUE)
957
4
    {
958
4
      gssize chunk;    
959
960
4
      if (bytes >= sizeof(gint)*2)
961
2
        break; /* give up, who knows what happened, should not be
962
                * possible.
963
                */
964
          
965
2
    again:
966
2
      chunk = read (fd,
967
2
                    ((gchar*)buf) + bytes,
968
2
                    sizeof(gint) * n_ints_in_buf - bytes);
969
2
      if (chunk < 0 && errno == EINTR)
970
0
        goto again;
971
          
972
2
      if (chunk < 0)
973
0
        {
974
0
          int errsv = errno;
975
976
          /* Some weird shit happened, bail out */
977
0
          g_set_error (error,
978
0
                       G_SPAWN_ERROR,
979
0
                       G_SPAWN_ERROR_FAILED,
980
0
                       _("Failed to read from child pipe (%s)"),
981
0
                       g_strerror (errsv));
982
983
0
          return FALSE;
984
0
        }
985
2
      else if (chunk == 0)
986
0
        break; /* EOF */
987
2
      else /* chunk > 0 */
988
2
  bytes += chunk;
989
2
    }
990
991
2
  *n_ints_read = (gint)(bytes / sizeof(gint));
992
993
2
  return TRUE;
994
2
}
995
996
#ifdef POSIX_SPAWN_AVAILABLE
997
static gboolean
998
do_posix_spawn (const gchar * const *argv,
999
                const gchar * const *envp,
1000
                gboolean    search_path,
1001
                gboolean    stdout_to_null,
1002
                gboolean    stderr_to_null,
1003
                gboolean    child_inherits_stdin,
1004
                gboolean    file_and_argv_zero,
1005
                GPid       *child_pid,
1006
                gint       *child_close_fds,
1007
                gint        stdin_fd,
1008
                gint        stdout_fd,
1009
                gint        stderr_fd,
1010
                const gint *source_fds,
1011
                const gint *target_fds,
1012
                gsize       n_fds)
1013
0
{
1014
0
  pid_t pid;
1015
0
  gint *duped_source_fds = NULL;
1016
0
  gint max_target_fd = 0;
1017
0
  const gchar * const *argv_pass;
1018
0
  posix_spawnattr_t attr;
1019
0
  posix_spawn_file_actions_t file_actions;
1020
0
  gint parent_close_fds[3];
1021
0
  gsize num_parent_close_fds = 0;
1022
0
  GSList *child_close = NULL;
1023
0
  GSList *elem;
1024
0
  sigset_t mask;
1025
0
  gsize i;
1026
0
  int r;
1027
1028
0
  g_assert (argv != NULL && argv[0] != NULL);
1029
1030
0
  if (*argv[0] == '\0')
1031
0
    {
1032
      /* We check the simple case first. */
1033
0
      return ENOENT;
1034
0
    }
1035
1036
0
  r = posix_spawnattr_init (&attr);
1037
0
  if (r != 0)
1038
0
    return r;
1039
1040
0
  if (child_close_fds)
1041
0
    {
1042
0
      int i = -1;
1043
0
      while (child_close_fds[++i] != -1)
1044
0
        child_close = g_slist_prepend (child_close,
1045
0
                                       GINT_TO_POINTER (child_close_fds[i]));
1046
0
    }
1047
1048
0
  r = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF);
1049
0
  if (r != 0)
1050
0
    goto out_free_spawnattr;
1051
1052
  /* Reset some signal handlers that we may use */
1053
0
  sigemptyset (&mask);
1054
0
  sigaddset (&mask, SIGCHLD);
1055
0
  sigaddset (&mask, SIGINT);
1056
0
  sigaddset (&mask, SIGTERM);
1057
0
  sigaddset (&mask, SIGHUP);
1058
1059
0
  r = posix_spawnattr_setsigdefault (&attr, &mask);
1060
0
  if (r != 0)
1061
0
    goto out_free_spawnattr;
1062
1063
0
  r = posix_spawn_file_actions_init (&file_actions);
1064
0
  if (r != 0)
1065
0
    goto out_free_spawnattr;
1066
1067
  /* Redirect pipes as required */
1068
1069
0
  if (stdin_fd >= 0)
1070
0
    {
1071
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, stdin_fd, 0);
1072
0
      if (r != 0)
1073
0
        goto out_close_fds;
1074
1075
0
      if (!g_slist_find (child_close, GINT_TO_POINTER (stdin_fd)))
1076
0
        child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdin_fd));
1077
0
    }
1078
0
  else if (!child_inherits_stdin)
1079
0
    {
1080
      /* Keep process from blocking on a read of stdin */
1081
0
      gint read_null = safe_open ("/dev/null", O_RDONLY | O_CLOEXEC);
1082
0
      g_assert (read_null != -1);
1083
0
      parent_close_fds[num_parent_close_fds++] = read_null;
1084
1085
#ifndef HAVE_O_CLOEXEC
1086
      fcntl (read_null, F_SETFD, FD_CLOEXEC);
1087
#endif
1088
1089
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, read_null, 0);
1090
0
      if (r != 0)
1091
0
        goto out_close_fds;
1092
0
    }
1093
1094
0
  if (stdout_fd >= 0)
1095
0
    {
1096
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, stdout_fd, 1);
1097
0
      if (r != 0)
1098
0
        goto out_close_fds;
1099
1100
0
      if (!g_slist_find (child_close, GINT_TO_POINTER (stdout_fd)))
1101
0
        child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdout_fd));
1102
0
    }
1103
0
  else if (stdout_to_null)
1104
0
    {
1105
0
      gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1106
0
      g_assert (write_null != -1);
1107
0
      parent_close_fds[num_parent_close_fds++] = write_null;
1108
1109
#ifndef HAVE_O_CLOEXEC
1110
      fcntl (write_null, F_SETFD, FD_CLOEXEC);
1111
#endif
1112
1113
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 1);
1114
0
      if (r != 0)
1115
0
        goto out_close_fds;
1116
0
    }
1117
1118
0
  if (stderr_fd >= 0)
1119
0
    {
1120
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, stderr_fd, 2);
1121
0
      if (r != 0)
1122
0
        goto out_close_fds;
1123
1124
0
      if (!g_slist_find (child_close, GINT_TO_POINTER (stderr_fd)))
1125
0
        child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stderr_fd));
1126
0
    }
1127
0
  else if (stderr_to_null)
1128
0
    {
1129
0
      gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1130
0
      g_assert (write_null != -1);
1131
0
      parent_close_fds[num_parent_close_fds++] = write_null;
1132
1133
#ifndef HAVE_O_CLOEXEC
1134
      fcntl (write_null, F_SETFD, FD_CLOEXEC);
1135
#endif
1136
1137
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 2);
1138
0
      if (r != 0)
1139
0
        goto out_close_fds;
1140
0
    }
1141
1142
  /* If source_fds[i] != target_fds[i], we need to handle the case
1143
   * where the user has specified, e.g., 5 -> 4, 4 -> 6. We do this
1144
   * by duping the source fds, taking care to ensure the new fds are
1145
   * larger than any target fd to avoid introducing new conflicts.
1146
   *
1147
   * If source_fds[i] == target_fds[i], then we just need to leak
1148
   * the fd into the child process, which we *could* do by temporarily
1149
   * unsetting CLOEXEC and then setting it again after we spawn if
1150
   * it was originally set. POSIX requires that the addup2 action unset
1151
   * CLOEXEC if source and target are identical, so you'd think doing it
1152
   * manually wouldn't be needed, but unfortunately as of 2021 many
1153
   * libcs still don't do so. Example nonconforming libcs:
1154
   *  Bionic: https://android.googlesource.com/platform/bionic/+/f6e5b582604715729b09db3e36a7aeb8c24b36a4/libc/bionic/spawn.cpp#71
1155
   *  uclibc-ng: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/librt/spawn.c?id=7c36bcae09d66bbaa35cbb02253ae0556f42677e#n88
1156
   *
1157
   * Anyway, unsetting CLOEXEC ourselves would open a small race window
1158
   * where the fd could be inherited into a child process if another
1159
   * thread spawns something at the same time, because we have not
1160
   * called fork() and are multithreaded here. This race is avoidable by
1161
   * using dupfd_cloexec, which we already have to do to handle the
1162
   * source_fds[i] != target_fds[i] case. So let's always do it!
1163
   */
1164
1165
0
  for (i = 0; i < n_fds; i++)
1166
0
    max_target_fd = MAX (max_target_fd, target_fds[i]);
1167
1168
0
  if (max_target_fd == G_MAXINT)
1169
0
    goto out_close_fds;
1170
1171
0
  duped_source_fds = g_new (gint, n_fds);
1172
0
  for (i = 0; i < n_fds; i++)
1173
0
    duped_source_fds[i] = -1;  /* initialise in case dupfd_cloexec() fails below */
1174
0
  for (i = 0; i < n_fds; i++)
1175
0
    {
1176
0
      duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
1177
0
      if (duped_source_fds[i] < 0)
1178
0
        goto out_close_fds;
1179
0
    }
1180
1181
0
  for (i = 0; i < n_fds; i++)
1182
0
    {
1183
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, duped_source_fds[i], target_fds[i]);
1184
0
      if (r != 0)
1185
0
        goto out_close_fds;
1186
0
    }
1187
1188
  /* Intentionally close the fds in the child as the last file action,
1189
   * having been careful not to add the same fd to this list twice.
1190
   *
1191
   * This is important to allow (e.g.) for the same fd to be passed as stdout
1192
   * and stderr (we must not close it before we have dupped it in both places,
1193
   * and we must not attempt to close it twice).
1194
   */
1195
0
  for (elem = child_close; elem != NULL; elem = elem->next)
1196
0
    {
1197
0
      r = posix_spawn_file_actions_addclose (&file_actions,
1198
0
                                             GPOINTER_TO_INT (elem->data));
1199
0
      if (r != 0)
1200
0
        goto out_close_fds;
1201
0
    }
1202
1203
0
  argv_pass = file_and_argv_zero ? argv + 1 : argv;
1204
0
  if (envp == NULL)
1205
0
    envp = (const gchar * const *) environ;
1206
1207
  /* Don't search when it contains a slash. */
1208
0
  if (!search_path || strchr (argv[0], '/') != NULL)
1209
0
    r = posix_spawn (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1210
0
  else
1211
0
    r = posix_spawnp (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1212
1213
0
  if (r == 0 && child_pid != NULL)
1214
0
    *child_pid = pid;
1215
1216
0
out_close_fds:
1217
0
  for (i = 0; i < num_parent_close_fds; i++)
1218
0
    g_clear_fd (&parent_close_fds[i], NULL);
1219
1220
0
  if (duped_source_fds != NULL)
1221
0
    {
1222
0
      for (i = 0; i < n_fds; i++)
1223
0
        g_clear_fd (&duped_source_fds[i], NULL);
1224
0
      g_free (duped_source_fds);
1225
0
    }
1226
1227
0
  posix_spawn_file_actions_destroy (&file_actions);
1228
0
out_free_spawnattr:
1229
0
  posix_spawnattr_destroy (&attr);
1230
0
  g_slist_free (child_close);
1231
1232
0
  return r;
1233
0
}
1234
#endif /* POSIX_SPAWN_AVAILABLE */
1235
1236
static gboolean
1237
source_fds_collide_with_pipe (const GUnixPipe  *pipefd,
1238
                              const int        *source_fds,
1239
                              gsize             n_fds,
1240
                              GError          **error)
1241
6
{
1242
6
  return (_g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_READ], source_fds, n_fds, error) ||
1243
6
          _g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_WRITE], source_fds, n_fds, error));
1244
6
}
1245
1246
static gboolean
1247
fork_exec (gboolean              intermediate_child,
1248
           const gchar          *working_directory,
1249
           const gchar * const  *argv,
1250
           const gchar * const  *envp,
1251
           gboolean              close_descriptors,
1252
           gboolean              search_path,
1253
           gboolean              search_path_from_envp,
1254
           gboolean              stdout_to_null,
1255
           gboolean              stderr_to_null,
1256
           gboolean              child_inherits_stdin,
1257
           gboolean              file_and_argv_zero,
1258
           gboolean              cloexec_pipes,
1259
           GSpawnChildSetupFunc  child_setup,
1260
           gpointer              user_data,
1261
           GPid                 *child_pid,
1262
           gint                 *stdin_pipe_out,
1263
           gint                 *stdout_pipe_out,
1264
           gint                 *stderr_pipe_out,
1265
           gint                  stdin_fd,
1266
           gint                  stdout_fd,
1267
           gint                  stderr_fd,
1268
           const gint           *source_fds,
1269
           const gint           *target_fds,
1270
           gsize                 n_fds,
1271
           GError              **error)
1272
2
{
1273
2
  GPid pid = -1;
1274
2
  GUnixPipe child_err_report_pipe = G_UNIX_PIPE_INIT;
1275
2
  GUnixPipe child_pid_report_pipe = G_UNIX_PIPE_INIT;
1276
2
  guint pipe_flags = cloexec_pipes ? O_CLOEXEC : 0;
1277
2
  gint status;
1278
2
  const gchar *chosen_search_path;
1279
2
  gchar *search_path_buffer = NULL;
1280
2
  gchar *search_path_buffer_heap = NULL;
1281
2
  gsize search_path_buffer_len = 0;
1282
2
  gchar **argv_buffer = NULL;
1283
2
  gchar **argv_buffer_heap = NULL;
1284
2
  gsize argv_buffer_len = 0;
1285
2
  GUnixPipe stdin_pipe = G_UNIX_PIPE_INIT;
1286
2
  GUnixPipe stdout_pipe = G_UNIX_PIPE_INIT;
1287
2
  GUnixPipe stderr_pipe = G_UNIX_PIPE_INIT;
1288
2
  gint child_close_fds[4] = { -1, -1, -1, -1 };
1289
2
  gint n_child_close_fds = 0;
1290
2
  gint *source_fds_copy = NULL;
1291
1292
2
  g_assert (argv != NULL && argv[0] != NULL);
1293
2
  g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
1294
2
  g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
1295
2
  g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
1296
1297
  /* If pipes have been requested, open them */
1298
2
  if (stdin_pipe_out != NULL)
1299
2
    {
1300
2
      if (!g_unix_pipe_open (&stdin_pipe, pipe_flags, error))
1301
0
        goto cleanup_and_fail;
1302
2
      if (source_fds_collide_with_pipe (&stdin_pipe, source_fds, n_fds, error))
1303
0
        goto cleanup_and_fail;
1304
2
      child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1305
2
      stdin_fd = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_READ);
1306
2
    }
1307
1308
2
  if (stdout_pipe_out != NULL)
1309
2
    {
1310
2
      if (!g_unix_pipe_open (&stdout_pipe, pipe_flags, error))
1311
0
        goto cleanup_and_fail;
1312
2
      if (source_fds_collide_with_pipe (&stdout_pipe, source_fds, n_fds, error))
1313
0
        goto cleanup_and_fail;
1314
2
      child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_READ);
1315
2
      stdout_fd = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_WRITE);
1316
2
    }
1317
1318
2
  if (stderr_pipe_out != NULL)
1319
0
    {
1320
0
      if (!g_unix_pipe_open (&stderr_pipe, pipe_flags, error))
1321
0
        goto cleanup_and_fail;
1322
0
      if (source_fds_collide_with_pipe (&stderr_pipe, source_fds, n_fds, error))
1323
0
        goto cleanup_and_fail;
1324
0
      child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_READ);
1325
0
      stderr_fd = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_WRITE);
1326
0
    }
1327
1328
2
  child_close_fds[n_child_close_fds++] = -1;
1329
1330
2
#ifdef POSIX_SPAWN_AVAILABLE
1331
2
  if (!intermediate_child && working_directory == NULL && !close_descriptors &&
1332
2
      !search_path_from_envp && child_setup == NULL)
1333
0
    {
1334
0
      g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1335
0
                    "GLib", "posix_spawn",
1336
0
                    "%s", argv[0]);
1337
1338
0
      status = do_posix_spawn (argv,
1339
0
                               envp,
1340
0
                               search_path,
1341
0
                               stdout_to_null,
1342
0
                               stderr_to_null,
1343
0
                               child_inherits_stdin,
1344
0
                               file_and_argv_zero,
1345
0
                               child_pid,
1346
0
                               child_close_fds,
1347
0
                               stdin_fd,
1348
0
                               stdout_fd,
1349
0
                               stderr_fd,
1350
0
                               source_fds,
1351
0
                               target_fds,
1352
0
                               n_fds);
1353
0
      if (status == 0)
1354
0
        goto success;
1355
1356
0
      if (status != ENOEXEC)
1357
0
        {
1358
0
          g_set_error (error,
1359
0
                       G_SPAWN_ERROR,
1360
0
                       G_SPAWN_ERROR_FAILED,
1361
0
                       _("Failed to spawn child process ā€œ%sā€ (%s)"),
1362
0
                       argv[0],
1363
0
                       g_strerror (status));
1364
0
          goto cleanup_and_fail;
1365
0
       }
1366
1367
      /* posix_spawn is not intended to support script execution. It does in
1368
       * some situations on some glibc versions, but that will be fixed.
1369
       * So if it fails with ENOEXEC, we fall through to the regular
1370
       * gspawn codepath so that script execution can be attempted,
1371
       * per standard gspawn behaviour. */
1372
0
      g_debug ("posix_spawn failed (ENOEXEC), fall back to regular gspawn");
1373
0
    }
1374
2
  else
1375
2
    {
1376
2
      g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1377
2
                    "GLib", "fork",
1378
2
                    "posix_spawn avoided %s%s%s%s%s",
1379
2
                    !intermediate_child ? "" : "(automatic reaping requested) ",
1380
2
                    working_directory == NULL ? "" : "(workdir specified) ",
1381
2
                    !close_descriptors ? "" : "(fd close requested) ",
1382
2
                    !search_path_from_envp ? "" : "(using envp for search path) ",
1383
2
                    child_setup == NULL ? "" : "(child_setup specified) ");
1384
2
    }
1385
2
#endif /* POSIX_SPAWN_AVAILABLE */
1386
1387
  /* Choose a search path. This has to be done before calling fork()
1388
   * as getenv() isn’t async-signal-safe (see `man 7 signal-safety`). */
1389
2
  chosen_search_path = NULL;
1390
2
  if (search_path_from_envp)
1391
0
    chosen_search_path = g_environ_getenv ((gchar **) envp, "PATH");
1392
2
  if (search_path && chosen_search_path == NULL)
1393
0
    chosen_search_path = g_getenv ("PATH");
1394
1395
2
  if ((search_path || search_path_from_envp) && chosen_search_path == NULL)
1396
0
    {
1397
      /* There is no 'PATH' in the environment.  The default
1398
       * * search path in libc is the current directory followed by
1399
       * * the path 'confstr' returns for '_CS_PATH'.
1400
       * */
1401
1402
      /* In GLib we put . last, for security, and don't use the
1403
       * * unportable confstr(); UNIX98 does not actually specify
1404
       * * what to search if PATH is unset. POSIX may, dunno.
1405
       * */
1406
1407
0
      chosen_search_path = "/bin:/usr/bin:.";
1408
0
    }
1409
1410
2
  if (search_path || search_path_from_envp)
1411
2
    g_assert (chosen_search_path != NULL);
1412
2
  else
1413
2
    g_assert (chosen_search_path == NULL);
1414
1415
  /* Allocate a buffer which the fork()ed child can use to assemble potential
1416
   * paths for the binary to exec(), combining the argv[0] and elements from
1417
   * the chosen_search_path. This can’t be done in the child because malloc()
1418
   * (or alloca()) are not async-signal-safe (see `man 7 signal-safety`).
1419
   *
1420
   * Add 2 for the nul terminator and a leading `/`. */
1421
2
  if (chosen_search_path != NULL)
1422
0
    {
1423
0
      search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2;
1424
0
      if (search_path_buffer_len < 4000)
1425
0
        {
1426
          /* Prefer small stack allocations to avoid valgrind leak warnings
1427
           * in forked child. The 4000B cutoff is arbitrary. */
1428
0
          search_path_buffer = g_alloca (search_path_buffer_len);
1429
0
        }
1430
0
      else
1431
0
        {
1432
0
          search_path_buffer_heap = g_malloc (search_path_buffer_len);
1433
0
          search_path_buffer = search_path_buffer_heap;
1434
0
        }
1435
0
    }
1436
1437
2
  if (search_path || search_path_from_envp)
1438
2
    g_assert (search_path_buffer != NULL);
1439
2
  else
1440
2
    g_assert (search_path_buffer == NULL);
1441
1442
  /* And allocate a buffer which is 2 elements longer than @argv, so that if
1443
   * script_execute() has to be called later on, it can build a wrapper argv
1444
   * array in this buffer. */
1445
2
  argv_buffer_len = g_strv_length ((gchar **) argv) + 2;
1446
2
  if (argv_buffer_len < 4000 / sizeof (gchar *))
1447
2
    {
1448
      /* Prefer small stack allocations to avoid valgrind leak warnings
1449
       * in forked child. The 4000B cutoff is arbitrary. */
1450
2
      argv_buffer = g_newa (gchar *, argv_buffer_len);
1451
2
    }
1452
0
  else
1453
0
    {
1454
0
      argv_buffer_heap = g_new (gchar *, argv_buffer_len);
1455
0
      argv_buffer = argv_buffer_heap;
1456
0
    }
1457
1458
  /* And one to hold a copy of @source_fds for later manipulation in do_exec(). */
1459
2
  source_fds_copy = g_new (int, n_fds);
1460
2
  if (n_fds > 0)
1461
0
    memcpy (source_fds_copy, source_fds, sizeof (*source_fds) * n_fds);
1462
1463
2
  if (!g_unix_pipe_open (&child_err_report_pipe, pipe_flags, error))
1464
0
    goto cleanup_and_fail;
1465
2
  if (source_fds_collide_with_pipe (&child_err_report_pipe, source_fds, n_fds, error))
1466
0
    goto cleanup_and_fail;
1467
1468
2
  if (intermediate_child)
1469
0
    {
1470
0
      if (!g_unix_pipe_open (&child_pid_report_pipe, pipe_flags, error))
1471
0
        goto cleanup_and_fail;
1472
0
      if (source_fds_collide_with_pipe (&child_pid_report_pipe, source_fds, n_fds, error))
1473
0
        goto cleanup_and_fail;
1474
0
    }
1475
  
1476
2
  pid = fork ();
1477
1478
2
  if (pid < 0)
1479
0
    {
1480
0
      int errsv = errno;
1481
1482
0
      g_set_error (error,
1483
0
                   G_SPAWN_ERROR,
1484
0
                   G_SPAWN_ERROR_FORK,
1485
0
                   _("Failed to fork (%s)"),
1486
0
                   g_strerror (errsv));
1487
1488
0
      goto cleanup_and_fail;
1489
0
    }
1490
2
  else if (pid == 0)
1491
0
    {
1492
      /* Immediate child. This may or may not be the child that
1493
       * actually execs the new process.
1494
       */
1495
1496
      /* Reset some signal handlers that we may use */
1497
0
      signal (SIGCHLD, SIG_DFL);
1498
0
      signal (SIGINT, SIG_DFL);
1499
0
      signal (SIGTERM, SIG_DFL);
1500
0
      signal (SIGHUP, SIG_DFL);
1501
      
1502
      /* Be sure we crash if the parent exits
1503
       * and we write to the err_report_pipe
1504
       */
1505
0
      signal (SIGPIPE, SIG_DFL);
1506
1507
      /* Close the parent's end of the pipes;
1508
       * not needed in the close_descriptors case,
1509
       * though
1510
       */
1511
0
      g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1512
0
      g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1513
0
      if (child_close_fds[0] != -1)
1514
0
        {
1515
0
           int i = -1;
1516
0
           while (child_close_fds[++i] != -1)
1517
0
             g_clear_fd (&child_close_fds[i], NULL);
1518
0
        }
1519
      
1520
0
      if (intermediate_child)
1521
0
        {
1522
          /* We need to fork an intermediate child that launches the
1523
           * final child. The purpose of the intermediate child
1524
           * is to exit, so we can waitpid() it immediately.
1525
           * Then the grandchild will not become a zombie.
1526
           */
1527
0
          GPid grandchild_pid;
1528
1529
0
          grandchild_pid = fork ();
1530
1531
0
          if (grandchild_pid < 0)
1532
0
            {
1533
              /* report -1 as child PID */
1534
0
              write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1535
0
                         &grandchild_pid, sizeof(grandchild_pid));
1536
              
1537
0
              write_err_and_exit (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1538
0
                                  CHILD_FORK_FAILED);              
1539
0
            }
1540
0
          else if (grandchild_pid == 0)
1541
0
            {
1542
0
              g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1543
0
              do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1544
0
                       stdin_fd,
1545
0
                       stdout_fd,
1546
0
                       stderr_fd,
1547
0
                       source_fds_copy,
1548
0
                       target_fds,
1549
0
                       n_fds,
1550
0
                       working_directory,
1551
0
                       argv,
1552
0
                       argv_buffer,
1553
0
                       argv_buffer_len,
1554
0
                       envp,
1555
0
                       close_descriptors,
1556
0
                       chosen_search_path,
1557
0
                       search_path_buffer,
1558
0
                       search_path_buffer_len,
1559
0
                       stdout_to_null,
1560
0
                       stderr_to_null,
1561
0
                       child_inherits_stdin,
1562
0
                       file_and_argv_zero,
1563
0
                       child_setup,
1564
0
                       user_data);
1565
0
            }
1566
0
          else
1567
0
            {
1568
0
              write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1569
0
                         &grandchild_pid, sizeof(grandchild_pid));
1570
0
              g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1571
              
1572
0
              _exit (0);
1573
0
            }
1574
0
        }
1575
0
      else
1576
0
        {
1577
          /* Just run the child.
1578
           */
1579
1580
0
          do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1581
0
                   stdin_fd,
1582
0
                   stdout_fd,
1583
0
                   stderr_fd,
1584
0
                   source_fds_copy,
1585
0
                   target_fds,
1586
0
                   n_fds,
1587
0
                   working_directory,
1588
0
                   argv,
1589
0
                   argv_buffer,
1590
0
                   argv_buffer_len,
1591
0
                   envp,
1592
0
                   close_descriptors,
1593
0
                   chosen_search_path,
1594
0
                   search_path_buffer,
1595
0
                   search_path_buffer_len,
1596
0
                   stdout_to_null,
1597
0
                   stderr_to_null,
1598
0
                   child_inherits_stdin,
1599
0
                   file_and_argv_zero,
1600
0
                   child_setup,
1601
0
                   user_data);
1602
0
        }
1603
0
    }
1604
2
  else
1605
2
    {
1606
      /* Parent */
1607
      
1608
2
      gint buf[2];
1609
2
      gint n_ints = 0;    
1610
1611
      /* Close the uncared-about ends of the pipes */
1612
2
      g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1613
2
      g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1614
1615
      /* If we had an intermediate child, reap it */
1616
2
      if (intermediate_child)
1617
0
        {
1618
0
        wait_again:
1619
0
          if (waitpid (pid, &status, 0) < 0)
1620
0
            {
1621
0
              if (errno == EINTR)
1622
0
                goto wait_again;
1623
0
              else if (errno == ECHILD)
1624
0
                ; /* do nothing, child already reaped */
1625
0
              else
1626
0
                g_warning ("waitpid() should not fail in 'fork_exec'");
1627
0
            }
1628
0
        }
1629
      
1630
1631
2
      if (!read_ints (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_READ),
1632
2
                      buf, 2, &n_ints,
1633
2
                      error))
1634
0
        goto cleanup_and_fail;
1635
        
1636
2
      if (n_ints >= 2)
1637
2
        {
1638
          /* Error from the child. */
1639
1640
2
          switch (buf[0])
1641
2
            {
1642
0
            case CHILD_CHDIR_FAILED:
1643
0
              g_set_error (error,
1644
0
                           G_SPAWN_ERROR,
1645
0
                           G_SPAWN_ERROR_CHDIR,
1646
0
                           _("Failed to change to directory ā€œ%sā€ (%s)"),
1647
0
                           working_directory,
1648
0
                           g_strerror (buf[1]));
1649
1650
0
              break;
1651
              
1652
2
            case CHILD_EXEC_FAILED:
1653
2
              g_set_error (error,
1654
2
                           G_SPAWN_ERROR,
1655
2
                           _g_spawn_exec_err_to_g_error (buf[1]),
1656
2
                           _("Failed to execute child process ā€œ%sā€ (%s)"),
1657
2
                           argv[0],
1658
2
                           g_strerror (buf[1]));
1659
1660
2
              break;
1661
1662
0
            case CHILD_OPEN_FAILED:
1663
0
              g_set_error (error,
1664
0
                           G_SPAWN_ERROR,
1665
0
                           G_SPAWN_ERROR_FAILED,
1666
0
                           _("Failed to open file to remap file descriptor (%s)"),
1667
0
                           g_strerror (buf[1]));
1668
0
              break;
1669
1670
0
            case CHILD_DUPFD_FAILED:
1671
0
              g_set_error (error,
1672
0
                           G_SPAWN_ERROR,
1673
0
                           G_SPAWN_ERROR_FAILED,
1674
0
                           _("Failed to duplicate file descriptor for child process (%s)"),
1675
0
                           g_strerror (buf[1]));
1676
1677
0
              break;
1678
1679
0
            case CHILD_FORK_FAILED:
1680
0
              g_set_error (error,
1681
0
                           G_SPAWN_ERROR,
1682
0
                           G_SPAWN_ERROR_FORK,
1683
0
                           _("Failed to fork child process (%s)"),
1684
0
                           g_strerror (buf[1]));
1685
0
              break;
1686
1687
0
            case CHILD_CLOSE_FAILED:
1688
0
              g_set_error (error,
1689
0
                           G_SPAWN_ERROR,
1690
0
                           G_SPAWN_ERROR_FAILED,
1691
0
                           _("Failed to close file descriptor for child process (%s)"),
1692
0
                           g_strerror (buf[1]));
1693
0
              break;
1694
1695
0
            default:
1696
0
              g_set_error (error,
1697
0
                           G_SPAWN_ERROR,
1698
0
                           G_SPAWN_ERROR_FAILED,
1699
0
                           _("Unknown error executing child process ā€œ%sā€"),
1700
0
                           argv[0]);
1701
0
              break;
1702
2
            }
1703
1704
2
          goto cleanup_and_fail;
1705
2
        }
1706
1707
      /* Get child pid from intermediate child pipe. */
1708
0
      if (intermediate_child)
1709
0
        {
1710
0
          n_ints = 0;
1711
          
1712
0
          if (!read_ints (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_READ),
1713
0
                          buf, 1, &n_ints, error))
1714
0
            goto cleanup_and_fail;
1715
1716
0
          if (n_ints < 1)
1717
0
            {
1718
0
              int errsv = errno;
1719
1720
0
              g_set_error (error,
1721
0
                           G_SPAWN_ERROR,
1722
0
                           G_SPAWN_ERROR_FAILED,
1723
0
                           _("Failed to read enough data from child pid pipe (%s)"),
1724
0
                           g_strerror (errsv));
1725
0
              goto cleanup_and_fail;
1726
0
            }
1727
0
          else
1728
0
            {
1729
              /* we have the child pid */
1730
0
              pid = buf[0];
1731
0
            }
1732
0
        }
1733
      
1734
      /* Success against all odds! return the information */
1735
0
      g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1736
0
      g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1737
1738
0
      g_free (search_path_buffer_heap);
1739
0
      g_free (argv_buffer_heap);
1740
0
      g_free (source_fds_copy);
1741
1742
0
      if (child_pid)
1743
0
        *child_pid = pid;
1744
1745
0
      goto success;
1746
0
    }
1747
1748
0
success:
1749
  /* Close the uncared-about ends of the pipes */
1750
0
  g_unix_pipe_close (&stdin_pipe, G_UNIX_PIPE_END_READ, NULL);
1751
0
  g_unix_pipe_close (&stdout_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1752
0
  g_unix_pipe_close (&stderr_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1753
1754
0
  if (stdin_pipe_out != NULL)
1755
0
    *stdin_pipe_out = g_unix_pipe_steal (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1756
1757
0
  if (stdout_pipe_out != NULL)
1758
0
    *stdout_pipe_out = g_unix_pipe_steal (&stdout_pipe, G_UNIX_PIPE_END_READ);
1759
1760
0
  if (stderr_pipe_out != NULL)
1761
0
    *stderr_pipe_out = g_unix_pipe_steal (&stderr_pipe, G_UNIX_PIPE_END_READ);
1762
1763
0
  return TRUE;
1764
1765
2
 cleanup_and_fail:
1766
1767
  /* There was an error from the Child, reap the child to avoid it being
1768
     a zombie.
1769
   */
1770
1771
2
  if (pid > 0)
1772
2
  {
1773
2
    wait_failed:
1774
2
     if (waitpid (pid, NULL, 0) < 0)
1775
0
       {
1776
0
          if (errno == EINTR)
1777
0
            goto wait_failed;
1778
0
          else if (errno == ECHILD)
1779
0
            ; /* do nothing, child already reaped */
1780
0
          else
1781
0
            g_warning ("waitpid() should not fail in 'fork_exec'");
1782
0
       }
1783
2
   }
1784
1785
2
  g_unix_pipe_clear (&stdin_pipe);
1786
2
  g_unix_pipe_clear (&stdout_pipe);
1787
2
  g_unix_pipe_clear (&stderr_pipe);
1788
2
  g_unix_pipe_clear (&child_err_report_pipe);
1789
2
  g_unix_pipe_clear (&child_pid_report_pipe);
1790
1791
2
  g_clear_pointer (&search_path_buffer_heap, g_free);
1792
2
  g_clear_pointer (&argv_buffer_heap, g_free);
1793
2
  g_clear_pointer (&source_fds_copy, g_free);
1794
1795
2
  return FALSE;
1796
2
}
1797
1798
/* Based on execvp from GNU C Library */
1799
1800
/* This function is called between fork() and exec() and hence must be
1801
 * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1802
static gboolean
1803
script_execute (const gchar *file,
1804
                gchar      **argv,
1805
                gchar      **argv_buffer,
1806
                gsize        argv_buffer_len,
1807
                gchar      **envp)
1808
0
{
1809
  /* Count the arguments.  */
1810
0
  gsize argc = 0;
1811
0
  while (argv[argc])
1812
0
    ++argc;
1813
1814
  /* Construct an argument list for the shell. */
1815
0
  if (argc + 2 > argv_buffer_len)
1816
0
    return FALSE;
1817
1818
0
  argv_buffer[0] = (char *) "/bin/sh";
1819
0
  argv_buffer[1] = (char *) file;
1820
0
  while (argc > 0)
1821
0
    {
1822
0
      argv_buffer[argc + 1] = argv[argc];
1823
0
      --argc;
1824
0
    }
1825
1826
  /* Execute the shell. */
1827
0
  if (envp)
1828
0
    execve (argv_buffer[0], argv_buffer, envp);
1829
0
  else
1830
0
    execv (argv_buffer[0], argv_buffer);
1831
1832
0
  return TRUE;
1833
0
}
1834
1835
/* This function is called between fork() and exec() and hence must be
1836
 * async-signal-safe (see signal-safety(7)). */
1837
static gchar*
1838
my_strchrnul (const gchar *str, gchar c)
1839
0
{
1840
0
  gchar *p = (gchar*) str;
1841
0
  while (*p && (*p != c))
1842
0
    ++p;
1843
1844
0
  return p;
1845
0
}
1846
1847
/* This function is called between fork() and exec() and hence must be
1848
 * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1849
static gint
1850
g_execute (const gchar  *file,
1851
           gchar       **argv,
1852
           gchar       **argv_buffer,
1853
           gsize         argv_buffer_len,
1854
           gchar       **envp,
1855
           const gchar  *search_path,
1856
           gchar        *search_path_buffer,
1857
           gsize         search_path_buffer_len)
1858
0
{
1859
0
  if (file == NULL || *file == '\0')
1860
0
    {
1861
      /* We check the simple case first. */
1862
0
      errno = ENOENT;
1863
0
      return -1;
1864
0
    }
1865
1866
0
  if (search_path == NULL || strchr (file, '/') != NULL)
1867
0
    {
1868
      /* Don't search when it contains a slash. */
1869
0
      if (envp)
1870
0
        execve (file, argv, envp);
1871
0
      else
1872
0
        execv (file, argv);
1873
      
1874
0
      if (errno == ENOEXEC &&
1875
0
          !script_execute (file, argv, argv_buffer, argv_buffer_len, envp))
1876
0
        {
1877
0
          errno = ENOMEM;
1878
0
          return -1;
1879
0
        }
1880
0
    }
1881
0
  else
1882
0
    {
1883
0
      gboolean got_eacces = 0;
1884
0
      const gchar *path, *p;
1885
0
      gchar *name;
1886
0
      gsize len;
1887
0
      gsize pathlen;
1888
1889
0
      path = search_path;
1890
0
      len = strlen (file) + 1;
1891
0
      pathlen = strlen (path);
1892
0
      name = search_path_buffer;
1893
1894
0
      if (search_path_buffer_len < pathlen + len + 1)
1895
0
        {
1896
0
          errno = ENOMEM;
1897
0
          return -1;
1898
0
        }
1899
1900
      /* Copy the file name at the top, including '\0'  */
1901
0
      memcpy (name + pathlen + 1, file, len);
1902
0
      name = name + pathlen;
1903
      /* And add the slash before the filename  */
1904
0
      *name = '/';
1905
1906
0
      p = path;
1907
0
      do
1908
0
  {
1909
0
    char *startp;
1910
1911
0
    path = p;
1912
0
    p = my_strchrnul (path, ':');
1913
1914
0
    if (p == path)
1915
      /* Two adjacent colons, or a colon at the beginning or the end
1916
             * of 'PATH' means to search the current directory.
1917
             */
1918
0
      startp = name + 1;
1919
0
    else
1920
0
      startp = memcpy (name - (p - path), path, p - path);
1921
1922
    /* Try to execute this name.  If it works, execv will not return.  */
1923
0
          if (envp)
1924
0
            execve (startp, argv, envp);
1925
0
          else
1926
0
            execv (startp, argv);
1927
          
1928
0
          if (errno == ENOEXEC &&
1929
0
              !script_execute (startp, argv, argv_buffer, argv_buffer_len, envp))
1930
0
            {
1931
0
              errno = ENOMEM;
1932
0
              return -1;
1933
0
            }
1934
1935
0
    switch (errno)
1936
0
      {
1937
0
      case EACCES:
1938
        /* Record the we got a 'Permission denied' error.  If we end
1939
               * up finding no executable we can use, we want to diagnose
1940
               * that we did find one but were denied access.
1941
               */
1942
0
        got_eacces = TRUE;
1943
1944
0
              G_GNUC_FALLTHROUGH;
1945
0
      case ENOENT:
1946
0
#ifdef ESTALE
1947
0
      case ESTALE:
1948
0
#endif
1949
0
#ifdef ENOTDIR
1950
0
      case ENOTDIR:
1951
0
#endif
1952
        /* Those errors indicate the file is missing or not executable
1953
               * by us, in which case we want to just try the next path
1954
               * directory.
1955
               */
1956
0
        break;
1957
1958
0
      case ENODEV:
1959
0
      case ETIMEDOUT:
1960
        /* Some strange filesystems like AFS return even
1961
         * stranger error numbers.  They cannot reasonably mean anything
1962
         * else so ignore those, too.
1963
         */
1964
0
        break;
1965
1966
0
      default:
1967
        /* Some other error means we found an executable file, but
1968
               * something went wrong executing it; return the error to our
1969
               * caller.
1970
               */
1971
0
        return -1;
1972
0
      }
1973
0
  }
1974
0
      while (*p++ != '\0');
1975
1976
      /* We tried every element and none of them worked.  */
1977
0
      if (got_eacces)
1978
  /* At least one failure was due to permissions, so report that
1979
         * error.
1980
         */
1981
0
        errno = EACCES;
1982
0
    }
1983
1984
  /* Return the error from the last attempt (probably ENOENT).  */
1985
0
  return -1;
1986
0
}
1987
1988
void
1989
g_spawn_close_pid_impl (GPid pid)
1990
0
{
1991
  /* no-op */
1992
0
}