Coverage Report

Created: 2025-12-28 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gstreamer/subprojects/glib-2.86.3/glib/gspawn-posix.c
Line
Count
Source
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
  close (fd);
551
  
552
0
  _exit (1);
553
0
}
554
555
/* This function is called between fork() and exec() and hence must be
556
 * async-signal-safe (see signal-safety(7)). */
557
static void
558
set_cloexec (int fd)
559
0
{
560
0
  fcntl (fd, F_SETFD, FD_CLOEXEC);
561
0
}
562
563
/* This function is called between fork() and exec() and hence must be
564
 * async-signal-safe (see signal-safety(7)). */
565
static void
566
unset_cloexec (int fd)
567
0
{
568
0
  int flags;
569
0
  int result;
570
571
0
  flags = fcntl (fd, F_GETFD, 0);
572
573
0
  if (flags != -1)
574
0
    {
575
0
      int errsv;
576
0
      flags &= (~FD_CLOEXEC);
577
0
      do
578
0
        {
579
0
          result = fcntl (fd, F_SETFD, flags);
580
0
          errsv = errno;
581
0
        }
582
0
      while (result == -1 && errsv == EINTR);
583
0
    }
584
0
}
585
586
/* This function is called between fork() and exec() and hence must be
587
 * async-signal-safe (see signal-safety(7)). */
588
static int
589
dupfd_cloexec (int old_fd, int new_fd_min)
590
0
{
591
0
  int fd, errsv;
592
0
#ifdef F_DUPFD_CLOEXEC
593
0
  do
594
0
    {
595
0
      fd = fcntl (old_fd, F_DUPFD_CLOEXEC, new_fd_min);
596
0
      errsv = errno;
597
0
    }
598
0
  while (fd == -1 && errsv == EINTR);
599
#else
600
  /* OS X Snow Lion and earlier don't have F_DUPFD_CLOEXEC:
601
   * https://bugzilla.gnome.org/show_bug.cgi?id=710962
602
   */
603
  int result, flags;
604
  do
605
    {
606
      fd = fcntl (old_fd, F_DUPFD, new_fd_min);
607
      errsv = errno;
608
    }
609
  while (fd == -1 && errsv == EINTR);
610
  flags = fcntl (fd, F_GETFD, 0);
611
  if (flags != -1)
612
    {
613
      flags |= FD_CLOEXEC;
614
      do
615
        {
616
          result = fcntl (fd, F_SETFD, flags);
617
          errsv = errno;
618
        }
619
      while (result == -1 && errsv == EINTR);
620
    }
621
#endif
622
0
  return fd;
623
0
}
624
625
/* This function is called between fork() and exec() and hence must be
626
 * async-signal-safe (see signal-safety(7)). */
627
static gint
628
safe_dup2 (gint fd1, gint fd2)
629
0
{
630
0
  gint ret;
631
632
0
  do
633
0
    ret = dup2 (fd1, fd2);
634
0
  while (ret < 0 && (errno == EINTR || errno == EBUSY));
635
636
0
  return ret;
637
0
}
638
639
/* This function is called between fork() and exec() and hence must be
640
 * async-signal-safe (see signal-safety(7)). */
641
static gboolean
642
relocate_fd_out_of_standard_range (gint *fd)
643
0
{
644
0
  gint ret = -1;
645
0
  const int min_fileno = STDERR_FILENO + 1;
646
647
0
  do
648
0
    ret = fcntl (*fd, F_DUPFD, min_fileno);
649
0
  while (ret < 0 && errno == EINTR);
650
651
  /* Note we don't need to close the old fd, because the caller is expected
652
   * to close fds in the standard range itself.
653
   */
654
0
  if (ret >= min_fileno)
655
0
    {
656
0
      *fd = ret;
657
0
      return TRUE;
658
0
    }
659
660
0
  return FALSE;
661
0
}
662
663
/* This function is called between fork() and exec() and hence must be
664
 * async-signal-safe (see signal-safety(7)). */
665
static gint
666
safe_open (const char *path, gint mode)
667
0
{
668
0
  gint ret;
669
670
0
  do
671
0
    ret = open (path, mode);
672
0
  while (ret < 0 && errno == EINTR);
673
674
0
  return ret;
675
0
}
676
677
enum
678
{
679
  CHILD_CHDIR_FAILED,
680
  CHILD_EXEC_FAILED,
681
  CHILD_OPEN_FAILED,
682
  CHILD_DUPFD_FAILED,
683
  CHILD_FORK_FAILED,
684
  CHILD_CLOSE_FAILED,
685
};
686
687
/* This function is called between fork() and exec() and hence must be
688
 * async-signal-safe (see signal-safety(7)) until it calls exec().
689
 *
690
 * All callers must guarantee that @argv and @argv[0] are non-NULL. */
691
static void
692
do_exec (gint                  child_err_report_fd,
693
         gint                  stdin_fd,
694
         gint                  stdout_fd,
695
         gint                  stderr_fd,
696
         gint                 *source_fds,
697
         const gint           *target_fds,
698
         gsize                 n_fds,
699
         const gchar          *working_directory,
700
         const gchar * const  *argv,
701
         gchar               **argv_buffer,
702
         gsize                 argv_buffer_len,
703
         const gchar * const  *envp,
704
         gboolean              close_descriptors,
705
         const gchar          *search_path,
706
         gchar                *search_path_buffer,
707
         gsize                 search_path_buffer_len,
708
         gboolean              stdout_to_null,
709
         gboolean              stderr_to_null,
710
         gboolean              child_inherits_stdin,
711
         gboolean              file_and_argv_zero,
712
         GSpawnChildSetupFunc  child_setup,
713
         gpointer              user_data)
714
0
{
715
0
  gsize i;
716
0
  gint max_target_fd = 0;
717
718
0
  if (working_directory && chdir (working_directory) < 0)
719
0
    write_err_and_exit (child_err_report_fd,
720
0
                        CHILD_CHDIR_FAILED);
721
722
  /* It's possible the caller assigned stdin to an fd with a
723
   * file number that is supposed to be reserved for
724
   * stdout or stderr.
725
   *
726
   * If so, move it up out of the standard range, so it doesn't
727
   * cause a conflict.
728
   */
729
0
  if (IS_STD_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
730
0
    {
731
0
      int old_fd = stdin_fd;
732
733
0
      if (!relocate_fd_out_of_standard_range (&stdin_fd))
734
0
        write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
735
736
0
      if (stdout_fd == old_fd)
737
0
        stdout_fd = stdin_fd;
738
739
0
      if (stderr_fd == old_fd)
740
0
        stderr_fd = stdin_fd;
741
0
    }
742
743
  /* Redirect pipes as required
744
   *
745
   * There are two cases where we don't need to do the redirection
746
   * 1. Where the associated file descriptor is cleared/invalid
747
   * 2. When the associated file descriptor is already given the
748
   * correct file number.
749
   */
750
0
  if (IS_VALID_FILENO (stdin_fd) && stdin_fd != STDIN_FILENO)
751
0
    {
752
0
      if (safe_dup2 (stdin_fd, 0) < 0)
753
0
        write_err_and_exit (child_err_report_fd,
754
0
                            CHILD_DUPFD_FAILED);
755
756
0
      set_cloexec (stdin_fd);
757
0
    }
758
0
  else if (!child_inherits_stdin)
759
0
    {
760
      /* Keep process from blocking on a read of stdin */
761
0
      gint read_null = safe_open ("/dev/null", O_RDONLY);
762
0
      if (read_null < 0)
763
0
        write_err_and_exit (child_err_report_fd,
764
0
                            CHILD_OPEN_FAILED);
765
0
      if (safe_dup2 (read_null, 0) < 0)
766
0
        write_err_and_exit (child_err_report_fd,
767
0
                            CHILD_DUPFD_FAILED);
768
0
      g_clear_fd (&read_null, NULL);
769
0
    }
770
771
  /* Like with stdin above, it's possible the caller assigned
772
   * stdout to an fd with a file number that's intruding on the
773
   * standard range.
774
   *
775
   * If so, move it out of the way, too.
776
   */
777
0
  if (IS_STD_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
778
0
    {
779
0
      int old_fd = stdout_fd;
780
781
0
      if (!relocate_fd_out_of_standard_range (&stdout_fd))
782
0
        write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
783
784
0
      if (stderr_fd == old_fd)
785
0
        stderr_fd = stdout_fd;
786
0
    }
787
788
0
  if (IS_VALID_FILENO (stdout_fd) && stdout_fd != STDOUT_FILENO)
789
0
    {
790
0
      if (safe_dup2 (stdout_fd, 1) < 0)
791
0
        write_err_and_exit (child_err_report_fd,
792
0
                            CHILD_DUPFD_FAILED);
793
794
0
      set_cloexec (stdout_fd);
795
0
    }
796
0
  else if (stdout_to_null)
797
0
    {
798
0
      gint write_null = safe_open ("/dev/null", O_WRONLY);
799
0
      if (write_null < 0)
800
0
        write_err_and_exit (child_err_report_fd,
801
0
                            CHILD_OPEN_FAILED);
802
0
      if (safe_dup2 (write_null, 1) < 0)
803
0
        write_err_and_exit (child_err_report_fd,
804
0
                            CHILD_DUPFD_FAILED);
805
0
      g_clear_fd (&write_null, NULL);
806
0
    }
807
808
0
  if (IS_STD_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
809
0
    {
810
0
      if (!relocate_fd_out_of_standard_range (&stderr_fd))
811
0
        write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
812
0
    }
813
814
  /* Like with stdin/stdout above, it's possible the caller assigned
815
   * stderr to an fd with a file number that's intruding on the
816
   * standard range.
817
   *
818
   * Make sure it's out of the way, also.
819
   */
820
0
  if (IS_VALID_FILENO (stderr_fd) && stderr_fd != STDERR_FILENO)
821
0
    {
822
0
      if (safe_dup2 (stderr_fd, 2) < 0)
823
0
        write_err_and_exit (child_err_report_fd,
824
0
                            CHILD_DUPFD_FAILED);
825
826
0
      set_cloexec (stderr_fd);
827
0
    }
828
0
  else if (stderr_to_null)
829
0
    {
830
0
      gint write_null = safe_open ("/dev/null", O_WRONLY);
831
0
      if (write_null < 0)
832
0
        write_err_and_exit (child_err_report_fd,
833
0
                            CHILD_OPEN_FAILED);
834
0
      if (safe_dup2 (write_null, 2) < 0)
835
0
        write_err_and_exit (child_err_report_fd,
836
0
                            CHILD_DUPFD_FAILED);
837
0
      g_clear_fd (&write_null, NULL);
838
0
    }
839
840
  /* Close all file descriptors but stdin, stdout and stderr, and any of source_fds,
841
   * before we exec. Note that this includes
842
   * child_err_report_fd, which keeps the parent from blocking
843
   * forever on the other end of that pipe.
844
   */
845
0
  if (close_descriptors)
846
0
    {
847
0
      if (child_setup == NULL && n_fds == 0)
848
0
        {
849
0
          if (safe_dup2 (child_err_report_fd, 3) < 0)
850
0
            write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
851
0
          set_cloexec (3);
852
0
          if (g_closefrom (4) < 0)
853
0
            write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
854
0
          child_err_report_fd = 3;
855
0
        }
856
0
      else
857
0
        {
858
0
          if (g_fdwalk_set_cloexec (3) < 0)
859
0
            write_err_and_exit (child_err_report_fd, CHILD_CLOSE_FAILED);
860
0
        }
861
0
    }
862
0
  else
863
0
    {
864
      /* We need to do child_err_report_fd anyway */
865
0
      set_cloexec (child_err_report_fd);
866
0
    }
867
868
  /*
869
   * Work through the @source_fds and @target_fds mapping.
870
   *
871
   * Based on code originally derived from
872
   * gnome-terminal:src/terminal-screen.c:terminal_screen_child_setup(),
873
   * used under the LGPLv2+ with permission from author. (The code has
874
   * since migrated to vte:src/spawn.cc:SpawnContext::exec and is no longer
875
   * terribly similar to what we have here.)
876
   */
877
878
0
  if (n_fds > 0)
879
0
    {
880
0
      for (i = 0; i < n_fds; i++)
881
0
        max_target_fd = MAX (max_target_fd, target_fds[i]);
882
883
0
      if (max_target_fd == G_MAXINT)
884
0
        {
885
0
          errno = EINVAL;
886
0
          write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
887
0
        }
888
889
      /* If we're doing remapping fd assignments, we need to handle
890
       * the case where the user has specified e.g. 5 -> 4, 4 -> 6.
891
       * We do this by duping all source fds, taking care to ensure the new
892
       * fds are larger than any target fd to avoid introducing new conflicts.
893
       */
894
0
      for (i = 0; i < n_fds; i++)
895
0
        {
896
0
          if (source_fds[i] != target_fds[i])
897
0
            {
898
0
              source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
899
0
              if (source_fds[i] < 0)
900
0
                write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
901
0
            }
902
0
        }
903
904
0
      for (i = 0; i < n_fds; i++)
905
0
        {
906
          /* For basic fd assignments (where source == target), we can just
907
           * unset FD_CLOEXEC.
908
           */
909
0
          if (source_fds[i] == target_fds[i])
910
0
            {
911
0
              unset_cloexec (source_fds[i]);
912
0
            }
913
0
          else
914
0
            {
915
              /* If any of the @target_fds conflict with @child_err_report_fd,
916
               * dup it so it doesn’t get conflated.
917
               */
918
0
              if (target_fds[i] == child_err_report_fd)
919
0
                {
920
0
                  child_err_report_fd = dupfd_cloexec (child_err_report_fd, max_target_fd + 1);
921
0
                  if (child_err_report_fd < 0)
922
0
                    write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
923
0
                }
924
925
0
              if (safe_dup2 (source_fds[i], target_fds[i]) < 0)
926
0
                write_err_and_exit (child_err_report_fd, CHILD_DUPFD_FAILED);
927
928
0
              g_clear_fd (&source_fds[i], NULL);
929
0
            }
930
0
        }
931
0
    }
932
933
  /* Call user function just before we exec */
934
0
  if (child_setup)
935
0
    {
936
0
      (* child_setup) (user_data);
937
0
    }
938
939
0
  g_execute (argv[0],
940
0
             (gchar **) (file_and_argv_zero ? argv + 1 : argv),
941
0
             argv_buffer, argv_buffer_len,
942
0
             (gchar **) envp, search_path, search_path_buffer, search_path_buffer_len);
943
944
  /* Exec failed */
945
0
  write_err_and_exit (child_err_report_fd,
946
0
                      CHILD_EXEC_FAILED);
947
0
}
948
949
static gboolean
950
read_ints (int      fd,
951
           gint*    buf,
952
           gint     n_ints_in_buf,    
953
           gint    *n_ints_read,      
954
           GError **error)
955
2
{
956
2
  gsize bytes = 0;    
957
  
958
4
  while (TRUE)
959
4
    {
960
4
      gssize chunk;    
961
962
4
      if (bytes >= sizeof(gint)*2)
963
2
        break; /* give up, who knows what happened, should not be
964
                * possible.
965
                */
966
          
967
2
    again:
968
2
      chunk = read (fd,
969
2
                    ((gchar*)buf) + bytes,
970
2
                    sizeof(gint) * n_ints_in_buf - bytes);
971
2
      if (chunk < 0 && errno == EINTR)
972
0
        goto again;
973
          
974
2
      if (chunk < 0)
975
0
        {
976
0
          int errsv = errno;
977
978
          /* Some weird shit happened, bail out */
979
0
          g_set_error (error,
980
0
                       G_SPAWN_ERROR,
981
0
                       G_SPAWN_ERROR_FAILED,
982
0
                       _("Failed to read from child pipe (%s)"),
983
0
                       g_strerror (errsv));
984
985
0
          return FALSE;
986
0
        }
987
2
      else if (chunk == 0)
988
0
        break; /* EOF */
989
2
      else /* chunk > 0 */
990
2
  bytes += chunk;
991
2
    }
992
993
2
  *n_ints_read = (gint)(bytes / sizeof(gint));
994
995
2
  return TRUE;
996
2
}
997
998
#ifdef POSIX_SPAWN_AVAILABLE
999
static gboolean
1000
do_posix_spawn (const gchar * const *argv,
1001
                const gchar * const *envp,
1002
                gboolean    search_path,
1003
                gboolean    stdout_to_null,
1004
                gboolean    stderr_to_null,
1005
                gboolean    child_inherits_stdin,
1006
                gboolean    file_and_argv_zero,
1007
                GPid       *child_pid,
1008
                gint       *child_close_fds,
1009
                gint        stdin_fd,
1010
                gint        stdout_fd,
1011
                gint        stderr_fd,
1012
                const gint *source_fds,
1013
                const gint *target_fds,
1014
                gsize       n_fds)
1015
0
{
1016
0
  pid_t pid;
1017
0
  gint *duped_source_fds = NULL;
1018
0
  gint max_target_fd = 0;
1019
0
  const gchar * const *argv_pass;
1020
0
  posix_spawnattr_t attr;
1021
0
  posix_spawn_file_actions_t file_actions;
1022
0
  gint parent_close_fds[3];
1023
0
  gsize num_parent_close_fds = 0;
1024
0
  GSList *child_close = NULL;
1025
0
  GSList *elem;
1026
0
  sigset_t mask;
1027
0
  gsize i;
1028
0
  int r;
1029
1030
0
  g_assert (argv != NULL && argv[0] != NULL);
1031
1032
0
  if (*argv[0] == '\0')
1033
0
    {
1034
      /* We check the simple case first. */
1035
0
      return ENOENT;
1036
0
    }
1037
1038
0
  r = posix_spawnattr_init (&attr);
1039
0
  if (r != 0)
1040
0
    return r;
1041
1042
0
  if (child_close_fds)
1043
0
    {
1044
0
      int i = -1;
1045
0
      while (child_close_fds[++i] != -1)
1046
0
        child_close = g_slist_prepend (child_close,
1047
0
                                       GINT_TO_POINTER (child_close_fds[i]));
1048
0
    }
1049
1050
0
  r = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF);
1051
0
  if (r != 0)
1052
0
    goto out_free_spawnattr;
1053
1054
  /* Reset some signal handlers that we may use */
1055
0
  sigemptyset (&mask);
1056
0
  sigaddset (&mask, SIGCHLD);
1057
0
  sigaddset (&mask, SIGINT);
1058
0
  sigaddset (&mask, SIGTERM);
1059
0
  sigaddset (&mask, SIGHUP);
1060
1061
0
  r = posix_spawnattr_setsigdefault (&attr, &mask);
1062
0
  if (r != 0)
1063
0
    goto out_free_spawnattr;
1064
1065
0
  r = posix_spawn_file_actions_init (&file_actions);
1066
0
  if (r != 0)
1067
0
    goto out_free_spawnattr;
1068
1069
  /* Redirect pipes as required */
1070
1071
0
  if (stdin_fd >= 0)
1072
0
    {
1073
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, stdin_fd, 0);
1074
0
      if (r != 0)
1075
0
        goto out_close_fds;
1076
1077
0
      if (!g_slist_find (child_close, GINT_TO_POINTER (stdin_fd)))
1078
0
        child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdin_fd));
1079
0
    }
1080
0
  else if (!child_inherits_stdin)
1081
0
    {
1082
      /* Keep process from blocking on a read of stdin */
1083
0
      gint read_null = safe_open ("/dev/null", O_RDONLY | O_CLOEXEC);
1084
0
      g_assert (read_null != -1);
1085
0
      parent_close_fds[num_parent_close_fds++] = read_null;
1086
1087
#ifndef HAVE_O_CLOEXEC
1088
      fcntl (read_null, F_SETFD, FD_CLOEXEC);
1089
#endif
1090
1091
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, read_null, 0);
1092
0
      if (r != 0)
1093
0
        goto out_close_fds;
1094
0
    }
1095
1096
0
  if (stdout_fd >= 0)
1097
0
    {
1098
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, stdout_fd, 1);
1099
0
      if (r != 0)
1100
0
        goto out_close_fds;
1101
1102
0
      if (!g_slist_find (child_close, GINT_TO_POINTER (stdout_fd)))
1103
0
        child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stdout_fd));
1104
0
    }
1105
0
  else if (stdout_to_null)
1106
0
    {
1107
0
      gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1108
0
      g_assert (write_null != -1);
1109
0
      parent_close_fds[num_parent_close_fds++] = write_null;
1110
1111
#ifndef HAVE_O_CLOEXEC
1112
      fcntl (write_null, F_SETFD, FD_CLOEXEC);
1113
#endif
1114
1115
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 1);
1116
0
      if (r != 0)
1117
0
        goto out_close_fds;
1118
0
    }
1119
1120
0
  if (stderr_fd >= 0)
1121
0
    {
1122
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, stderr_fd, 2);
1123
0
      if (r != 0)
1124
0
        goto out_close_fds;
1125
1126
0
      if (!g_slist_find (child_close, GINT_TO_POINTER (stderr_fd)))
1127
0
        child_close = g_slist_prepend (child_close, GINT_TO_POINTER (stderr_fd));
1128
0
    }
1129
0
  else if (stderr_to_null)
1130
0
    {
1131
0
      gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC);
1132
0
      g_assert (write_null != -1);
1133
0
      parent_close_fds[num_parent_close_fds++] = write_null;
1134
1135
#ifndef HAVE_O_CLOEXEC
1136
      fcntl (write_null, F_SETFD, FD_CLOEXEC);
1137
#endif
1138
1139
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, write_null, 2);
1140
0
      if (r != 0)
1141
0
        goto out_close_fds;
1142
0
    }
1143
1144
  /* If source_fds[i] != target_fds[i], we need to handle the case
1145
   * where the user has specified, e.g., 5 -> 4, 4 -> 6. We do this
1146
   * by duping the source fds, taking care to ensure the new fds are
1147
   * larger than any target fd to avoid introducing new conflicts.
1148
   *
1149
   * If source_fds[i] == target_fds[i], then we just need to leak
1150
   * the fd into the child process, which we *could* do by temporarily
1151
   * unsetting CLOEXEC and then setting it again after we spawn if
1152
   * it was originally set. POSIX requires that the addup2 action unset
1153
   * CLOEXEC if source and target are identical, so you'd think doing it
1154
   * manually wouldn't be needed, but unfortunately as of 2021 many
1155
   * libcs still don't do so. Example nonconforming libcs:
1156
   *  Bionic: https://android.googlesource.com/platform/bionic/+/f6e5b582604715729b09db3e36a7aeb8c24b36a4/libc/bionic/spawn.cpp#71
1157
   *  uclibc-ng: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/librt/spawn.c?id=7c36bcae09d66bbaa35cbb02253ae0556f42677e#n88
1158
   *
1159
   * Anyway, unsetting CLOEXEC ourselves would open a small race window
1160
   * where the fd could be inherited into a child process if another
1161
   * thread spawns something at the same time, because we have not
1162
   * called fork() and are multithreaded here. This race is avoidable by
1163
   * using dupfd_cloexec, which we already have to do to handle the
1164
   * source_fds[i] != target_fds[i] case. So let's always do it!
1165
   */
1166
1167
0
  for (i = 0; i < n_fds; i++)
1168
0
    max_target_fd = MAX (max_target_fd, target_fds[i]);
1169
1170
0
  if (max_target_fd == G_MAXINT)
1171
0
    goto out_close_fds;
1172
1173
0
  duped_source_fds = g_new (gint, n_fds);
1174
0
  for (i = 0; i < n_fds; i++)
1175
0
    duped_source_fds[i] = -1;  /* initialise in case dupfd_cloexec() fails below */
1176
0
  for (i = 0; i < n_fds; i++)
1177
0
    {
1178
0
      duped_source_fds[i] = dupfd_cloexec (source_fds[i], max_target_fd + 1);
1179
0
      if (duped_source_fds[i] < 0)
1180
0
        goto out_close_fds;
1181
0
    }
1182
1183
0
  for (i = 0; i < n_fds; i++)
1184
0
    {
1185
0
      r = posix_spawn_file_actions_adddup2 (&file_actions, duped_source_fds[i], target_fds[i]);
1186
0
      if (r != 0)
1187
0
        goto out_close_fds;
1188
0
    }
1189
1190
  /* Intentionally close the fds in the child as the last file action,
1191
   * having been careful not to add the same fd to this list twice.
1192
   *
1193
   * This is important to allow (e.g.) for the same fd to be passed as stdout
1194
   * and stderr (we must not close it before we have dupped it in both places,
1195
   * and we must not attempt to close it twice).
1196
   */
1197
0
  for (elem = child_close; elem != NULL; elem = elem->next)
1198
0
    {
1199
0
      r = posix_spawn_file_actions_addclose (&file_actions,
1200
0
                                             GPOINTER_TO_INT (elem->data));
1201
0
      if (r != 0)
1202
0
        goto out_close_fds;
1203
0
    }
1204
1205
0
  argv_pass = file_and_argv_zero ? argv + 1 : argv;
1206
0
  if (envp == NULL)
1207
0
    envp = (const gchar * const *) environ;
1208
1209
  /* Don't search when it contains a slash. */
1210
0
  if (!search_path || strchr (argv[0], '/') != NULL)
1211
0
    r = posix_spawn (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1212
0
  else
1213
0
    r = posix_spawnp (&pid, argv[0], &file_actions, &attr, (char * const *) argv_pass, (char * const *) envp);
1214
1215
0
  if (r == 0 && child_pid != NULL)
1216
0
    *child_pid = pid;
1217
1218
0
out_close_fds:
1219
0
  for (i = 0; i < num_parent_close_fds; i++)
1220
0
    g_clear_fd (&parent_close_fds[i], NULL);
1221
1222
0
  if (duped_source_fds != NULL)
1223
0
    {
1224
0
      for (i = 0; i < n_fds; i++)
1225
0
        g_clear_fd (&duped_source_fds[i], NULL);
1226
0
      g_free (duped_source_fds);
1227
0
    }
1228
1229
0
  posix_spawn_file_actions_destroy (&file_actions);
1230
0
out_free_spawnattr:
1231
0
  posix_spawnattr_destroy (&attr);
1232
0
  g_slist_free (child_close);
1233
1234
0
  return r;
1235
0
}
1236
#endif /* POSIX_SPAWN_AVAILABLE */
1237
1238
static gboolean
1239
source_fds_collide_with_pipe (const GUnixPipe  *pipefd,
1240
                              const int        *source_fds,
1241
                              gsize             n_fds,
1242
                              GError          **error)
1243
6
{
1244
6
  return (_g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_READ], source_fds, n_fds, error) ||
1245
6
          _g_spawn_invalid_source_fd (pipefd->fds[G_UNIX_PIPE_END_WRITE], source_fds, n_fds, error));
1246
6
}
1247
1248
static gboolean
1249
fork_exec (gboolean              intermediate_child,
1250
           const gchar          *working_directory,
1251
           const gchar * const  *argv,
1252
           const gchar * const  *envp,
1253
           gboolean              close_descriptors,
1254
           gboolean              search_path,
1255
           gboolean              search_path_from_envp,
1256
           gboolean              stdout_to_null,
1257
           gboolean              stderr_to_null,
1258
           gboolean              child_inherits_stdin,
1259
           gboolean              file_and_argv_zero,
1260
           gboolean              cloexec_pipes,
1261
           GSpawnChildSetupFunc  child_setup,
1262
           gpointer              user_data,
1263
           GPid                 *child_pid,
1264
           gint                 *stdin_pipe_out,
1265
           gint                 *stdout_pipe_out,
1266
           gint                 *stderr_pipe_out,
1267
           gint                  stdin_fd,
1268
           gint                  stdout_fd,
1269
           gint                  stderr_fd,
1270
           const gint           *source_fds,
1271
           const gint           *target_fds,
1272
           gsize                 n_fds,
1273
           GError              **error)
1274
2
{
1275
2
  GPid pid = -1;
1276
2
  GUnixPipe child_err_report_pipe = G_UNIX_PIPE_INIT;
1277
2
  GUnixPipe child_pid_report_pipe = G_UNIX_PIPE_INIT;
1278
2
  guint pipe_flags = cloexec_pipes ? O_CLOEXEC : 0;
1279
2
  gint status;
1280
2
  const gchar *chosen_search_path;
1281
2
  gchar *search_path_buffer = NULL;
1282
2
  gchar *search_path_buffer_heap = NULL;
1283
2
  gsize search_path_buffer_len = 0;
1284
2
  gchar **argv_buffer = NULL;
1285
2
  gchar **argv_buffer_heap = NULL;
1286
2
  gsize argv_buffer_len = 0;
1287
2
  GUnixPipe stdin_pipe = G_UNIX_PIPE_INIT;
1288
2
  GUnixPipe stdout_pipe = G_UNIX_PIPE_INIT;
1289
2
  GUnixPipe stderr_pipe = G_UNIX_PIPE_INIT;
1290
2
  gint child_close_fds[4] = { -1, -1, -1, -1 };
1291
2
  gint n_child_close_fds = 0;
1292
2
  gint *source_fds_copy = NULL;
1293
1294
2
  g_assert (argv != NULL && argv[0] != NULL);
1295
2
  g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
1296
2
  g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
1297
2
  g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
1298
1299
  /* If pipes have been requested, open them */
1300
2
  if (stdin_pipe_out != NULL)
1301
2
    {
1302
2
      if (!g_unix_pipe_open (&stdin_pipe, pipe_flags, error))
1303
0
        goto cleanup_and_fail;
1304
2
      if (source_fds_collide_with_pipe (&stdin_pipe, source_fds, n_fds, error))
1305
0
        goto cleanup_and_fail;
1306
2
      child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1307
2
      stdin_fd = g_unix_pipe_get (&stdin_pipe, G_UNIX_PIPE_END_READ);
1308
2
    }
1309
1310
2
  if (stdout_pipe_out != NULL)
1311
2
    {
1312
2
      if (!g_unix_pipe_open (&stdout_pipe, pipe_flags, error))
1313
0
        goto cleanup_and_fail;
1314
2
      if (source_fds_collide_with_pipe (&stdout_pipe, source_fds, n_fds, error))
1315
0
        goto cleanup_and_fail;
1316
2
      child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_READ);
1317
2
      stdout_fd = g_unix_pipe_get (&stdout_pipe, G_UNIX_PIPE_END_WRITE);
1318
2
    }
1319
1320
2
  if (stderr_pipe_out != NULL)
1321
0
    {
1322
0
      if (!g_unix_pipe_open (&stderr_pipe, pipe_flags, error))
1323
0
        goto cleanup_and_fail;
1324
0
      if (source_fds_collide_with_pipe (&stderr_pipe, source_fds, n_fds, error))
1325
0
        goto cleanup_and_fail;
1326
0
      child_close_fds[n_child_close_fds++] = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_READ);
1327
0
      stderr_fd = g_unix_pipe_get (&stderr_pipe, G_UNIX_PIPE_END_WRITE);
1328
0
    }
1329
1330
2
  child_close_fds[n_child_close_fds++] = -1;
1331
1332
2
#ifdef POSIX_SPAWN_AVAILABLE
1333
2
  if (!intermediate_child && working_directory == NULL && !close_descriptors &&
1334
0
      !search_path_from_envp && child_setup == NULL)
1335
0
    {
1336
0
      g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1337
0
                    "GLib", "posix_spawn",
1338
0
                    "%s", argv[0]);
1339
1340
0
      status = do_posix_spawn (argv,
1341
0
                               envp,
1342
0
                               search_path,
1343
0
                               stdout_to_null,
1344
0
                               stderr_to_null,
1345
0
                               child_inherits_stdin,
1346
0
                               file_and_argv_zero,
1347
0
                               child_pid,
1348
0
                               child_close_fds,
1349
0
                               stdin_fd,
1350
0
                               stdout_fd,
1351
0
                               stderr_fd,
1352
0
                               source_fds,
1353
0
                               target_fds,
1354
0
                               n_fds);
1355
0
      if (status == 0)
1356
0
        goto success;
1357
1358
0
      if (status != ENOEXEC)
1359
0
        {
1360
0
          g_set_error (error,
1361
0
                       G_SPAWN_ERROR,
1362
0
                       G_SPAWN_ERROR_FAILED,
1363
0
                       _("Failed to spawn child process ā€œ%sā€ (%s)"),
1364
0
                       argv[0],
1365
0
                       g_strerror (status));
1366
0
          goto cleanup_and_fail;
1367
0
       }
1368
1369
      /* posix_spawn is not intended to support script execution. It does in
1370
       * some situations on some glibc versions, but that will be fixed.
1371
       * So if it fails with ENOEXEC, we fall through to the regular
1372
       * gspawn codepath so that script execution can be attempted,
1373
       * per standard gspawn behaviour. */
1374
0
      g_debug ("posix_spawn failed (ENOEXEC), fall back to regular gspawn");
1375
0
    }
1376
2
  else
1377
2
    {
1378
2
      g_trace_mark (G_TRACE_CURRENT_TIME, 0,
1379
2
                    "GLib", "fork",
1380
2
                    "posix_spawn avoided %s%s%s%s%s",
1381
2
                    !intermediate_child ? "" : "(automatic reaping requested) ",
1382
2
                    working_directory == NULL ? "" : "(workdir specified) ",
1383
2
                    !close_descriptors ? "" : "(fd close requested) ",
1384
2
                    !search_path_from_envp ? "" : "(using envp for search path) ",
1385
2
                    child_setup == NULL ? "" : "(child_setup specified) ");
1386
2
    }
1387
2
#endif /* POSIX_SPAWN_AVAILABLE */
1388
1389
  /* Choose a search path. This has to be done before calling fork()
1390
   * as getenv() isn’t async-signal-safe (see `man 7 signal-safety`). */
1391
2
  chosen_search_path = NULL;
1392
2
  if (search_path_from_envp)
1393
0
    chosen_search_path = g_environ_getenv ((gchar **) envp, "PATH");
1394
2
  if (search_path && chosen_search_path == NULL)
1395
0
    chosen_search_path = g_getenv ("PATH");
1396
1397
2
  if ((search_path || search_path_from_envp) && chosen_search_path == NULL)
1398
0
    {
1399
      /* There is no 'PATH' in the environment.  The default
1400
       * * search path in libc is the current directory followed by
1401
       * * the path 'confstr' returns for '_CS_PATH'.
1402
       * */
1403
1404
      /* In GLib we put . last, for security, and don't use the
1405
       * * unportable confstr(); UNIX98 does not actually specify
1406
       * * what to search if PATH is unset. POSIX may, dunno.
1407
       * */
1408
1409
0
      chosen_search_path = "/bin:/usr/bin:.";
1410
0
    }
1411
1412
2
  if (search_path || search_path_from_envp)
1413
2
    g_assert (chosen_search_path != NULL);
1414
2
  else
1415
2
    g_assert (chosen_search_path == NULL);
1416
1417
  /* Allocate a buffer which the fork()ed child can use to assemble potential
1418
   * paths for the binary to exec(), combining the argv[0] and elements from
1419
   * the chosen_search_path. This can’t be done in the child because malloc()
1420
   * (or alloca()) are not async-signal-safe (see `man 7 signal-safety`).
1421
   *
1422
   * Add 2 for the nul terminator and a leading `/`. */
1423
2
  if (chosen_search_path != NULL)
1424
0
    {
1425
0
      search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2;
1426
0
      if (search_path_buffer_len < 4000)
1427
0
        {
1428
          /* Prefer small stack allocations to avoid valgrind leak warnings
1429
           * in forked child. The 4000B cutoff is arbitrary. */
1430
0
          search_path_buffer = g_alloca (search_path_buffer_len);
1431
0
        }
1432
0
      else
1433
0
        {
1434
0
          search_path_buffer_heap = g_malloc (search_path_buffer_len);
1435
0
          search_path_buffer = search_path_buffer_heap;
1436
0
        }
1437
0
    }
1438
1439
2
  if (search_path || search_path_from_envp)
1440
2
    g_assert (search_path_buffer != NULL);
1441
2
  else
1442
2
    g_assert (search_path_buffer == NULL);
1443
1444
  /* And allocate a buffer which is 2 elements longer than @argv, so that if
1445
   * script_execute() has to be called later on, it can build a wrapper argv
1446
   * array in this buffer. */
1447
2
  argv_buffer_len = g_strv_length ((gchar **) argv) + 2;
1448
2
  if (argv_buffer_len < 4000 / sizeof (gchar *))
1449
2
    {
1450
      /* Prefer small stack allocations to avoid valgrind leak warnings
1451
       * in forked child. The 4000B cutoff is arbitrary. */
1452
2
      argv_buffer = g_newa (gchar *, argv_buffer_len);
1453
2
    }
1454
0
  else
1455
0
    {
1456
0
      argv_buffer_heap = g_new (gchar *, argv_buffer_len);
1457
0
      argv_buffer = argv_buffer_heap;
1458
0
    }
1459
1460
  /* And one to hold a copy of @source_fds for later manipulation in do_exec(). */
1461
2
  source_fds_copy = g_new (int, n_fds);
1462
2
  if (n_fds > 0)
1463
0
    memcpy (source_fds_copy, source_fds, sizeof (*source_fds) * n_fds);
1464
1465
2
  if (!g_unix_pipe_open (&child_err_report_pipe, pipe_flags, error))
1466
0
    goto cleanup_and_fail;
1467
2
  if (source_fds_collide_with_pipe (&child_err_report_pipe, source_fds, n_fds, error))
1468
0
    goto cleanup_and_fail;
1469
1470
2
  if (intermediate_child)
1471
0
    {
1472
0
      if (!g_unix_pipe_open (&child_pid_report_pipe, pipe_flags, error))
1473
0
        goto cleanup_and_fail;
1474
0
      if (source_fds_collide_with_pipe (&child_pid_report_pipe, source_fds, n_fds, error))
1475
0
        goto cleanup_and_fail;
1476
0
    }
1477
  
1478
2
  pid = fork ();
1479
1480
2
  if (pid < 0)
1481
0
    {
1482
0
      int errsv = errno;
1483
1484
0
      g_set_error (error,
1485
0
                   G_SPAWN_ERROR,
1486
0
                   G_SPAWN_ERROR_FORK,
1487
0
                   _("Failed to fork (%s)"),
1488
0
                   g_strerror (errsv));
1489
1490
0
      goto cleanup_and_fail;
1491
0
    }
1492
2
  else if (pid == 0)
1493
0
    {
1494
      /* Immediate child. This may or may not be the child that
1495
       * actually execs the new process.
1496
       */
1497
1498
      /* Reset some signal handlers that we may use */
1499
0
      signal (SIGCHLD, SIG_DFL);
1500
0
      signal (SIGINT, SIG_DFL);
1501
0
      signal (SIGTERM, SIG_DFL);
1502
0
      signal (SIGHUP, SIG_DFL);
1503
      
1504
      /* Be sure we crash if the parent exits
1505
       * and we write to the err_report_pipe
1506
       */
1507
0
      signal (SIGPIPE, SIG_DFL);
1508
1509
      /* Close the parent's end of the pipes;
1510
       * not needed in the close_descriptors case,
1511
       * though
1512
       */
1513
0
      g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1514
0
      g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1515
0
      if (child_close_fds[0] != -1)
1516
0
        {
1517
0
           int i = -1;
1518
0
           while (child_close_fds[++i] != -1)
1519
0
             g_clear_fd (&child_close_fds[i], NULL);
1520
0
        }
1521
      
1522
0
      if (intermediate_child)
1523
0
        {
1524
          /* We need to fork an intermediate child that launches the
1525
           * final child. The purpose of the intermediate child
1526
           * is to exit, so we can waitpid() it immediately.
1527
           * Then the grandchild will not become a zombie.
1528
           */
1529
0
          GPid grandchild_pid;
1530
1531
0
          grandchild_pid = fork ();
1532
1533
0
          if (grandchild_pid < 0)
1534
0
            {
1535
              /* report -1 as child PID */
1536
0
              write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1537
0
                         &grandchild_pid, sizeof(grandchild_pid));
1538
              
1539
0
              write_err_and_exit (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1540
0
                                  CHILD_FORK_FAILED);              
1541
0
            }
1542
0
          else if (grandchild_pid == 0)
1543
0
            {
1544
0
              g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1545
0
              do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1546
0
                       stdin_fd,
1547
0
                       stdout_fd,
1548
0
                       stderr_fd,
1549
0
                       source_fds_copy,
1550
0
                       target_fds,
1551
0
                       n_fds,
1552
0
                       working_directory,
1553
0
                       argv,
1554
0
                       argv_buffer,
1555
0
                       argv_buffer_len,
1556
0
                       envp,
1557
0
                       close_descriptors,
1558
0
                       chosen_search_path,
1559
0
                       search_path_buffer,
1560
0
                       search_path_buffer_len,
1561
0
                       stdout_to_null,
1562
0
                       stderr_to_null,
1563
0
                       child_inherits_stdin,
1564
0
                       file_and_argv_zero,
1565
0
                       child_setup,
1566
0
                       user_data);
1567
0
            }
1568
0
          else
1569
0
            {
1570
0
              write_all (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE),
1571
0
                         &grandchild_pid, sizeof(grandchild_pid));
1572
0
              g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1573
              
1574
0
              _exit (0);
1575
0
            }
1576
0
        }
1577
0
      else
1578
0
        {
1579
          /* Just run the child.
1580
           */
1581
1582
0
          do_exec (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE),
1583
0
                   stdin_fd,
1584
0
                   stdout_fd,
1585
0
                   stderr_fd,
1586
0
                   source_fds_copy,
1587
0
                   target_fds,
1588
0
                   n_fds,
1589
0
                   working_directory,
1590
0
                   argv,
1591
0
                   argv_buffer,
1592
0
                   argv_buffer_len,
1593
0
                   envp,
1594
0
                   close_descriptors,
1595
0
                   chosen_search_path,
1596
0
                   search_path_buffer,
1597
0
                   search_path_buffer_len,
1598
0
                   stdout_to_null,
1599
0
                   stderr_to_null,
1600
0
                   child_inherits_stdin,
1601
0
                   file_and_argv_zero,
1602
0
                   child_setup,
1603
0
                   user_data);
1604
0
        }
1605
0
    }
1606
2
  else
1607
2
    {
1608
      /* Parent */
1609
      
1610
2
      gint buf[2];
1611
2
      gint n_ints = 0;    
1612
1613
      /* Close the uncared-about ends of the pipes */
1614
2
      g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1615
2
      g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1616
1617
      /* If we had an intermediate child, reap it */
1618
2
      if (intermediate_child)
1619
0
        {
1620
0
        wait_again:
1621
0
          if (waitpid (pid, &status, 0) < 0)
1622
0
            {
1623
0
              if (errno == EINTR)
1624
0
                goto wait_again;
1625
0
              else if (errno == ECHILD)
1626
0
                ; /* do nothing, child already reaped */
1627
0
              else
1628
0
                g_warning ("waitpid() should not fail in 'fork_exec'");
1629
0
            }
1630
0
        }
1631
      
1632
1633
2
      if (!read_ints (g_unix_pipe_get (&child_err_report_pipe, G_UNIX_PIPE_END_READ),
1634
2
                      buf, 2, &n_ints,
1635
2
                      error))
1636
0
        goto cleanup_and_fail;
1637
        
1638
2
      if (n_ints >= 2)
1639
2
        {
1640
          /* Error from the child. */
1641
1642
2
          switch (buf[0])
1643
2
            {
1644
0
            case CHILD_CHDIR_FAILED:
1645
0
              g_set_error (error,
1646
0
                           G_SPAWN_ERROR,
1647
0
                           G_SPAWN_ERROR_CHDIR,
1648
0
                           _("Failed to change to directory ā€œ%sā€ (%s)"),
1649
0
                           working_directory,
1650
0
                           g_strerror (buf[1]));
1651
1652
0
              break;
1653
              
1654
2
            case CHILD_EXEC_FAILED:
1655
2
              g_set_error (error,
1656
2
                           G_SPAWN_ERROR,
1657
2
                           _g_spawn_exec_err_to_g_error (buf[1]),
1658
2
                           _("Failed to execute child process ā€œ%sā€ (%s)"),
1659
2
                           argv[0],
1660
2
                           g_strerror (buf[1]));
1661
1662
2
              break;
1663
1664
0
            case CHILD_OPEN_FAILED:
1665
0
              g_set_error (error,
1666
0
                           G_SPAWN_ERROR,
1667
0
                           G_SPAWN_ERROR_FAILED,
1668
0
                           _("Failed to open file to remap file descriptor (%s)"),
1669
0
                           g_strerror (buf[1]));
1670
0
              break;
1671
1672
0
            case CHILD_DUPFD_FAILED:
1673
0
              g_set_error (error,
1674
0
                           G_SPAWN_ERROR,
1675
0
                           G_SPAWN_ERROR_FAILED,
1676
0
                           _("Failed to duplicate file descriptor for child process (%s)"),
1677
0
                           g_strerror (buf[1]));
1678
1679
0
              break;
1680
1681
0
            case CHILD_FORK_FAILED:
1682
0
              g_set_error (error,
1683
0
                           G_SPAWN_ERROR,
1684
0
                           G_SPAWN_ERROR_FORK,
1685
0
                           _("Failed to fork child process (%s)"),
1686
0
                           g_strerror (buf[1]));
1687
0
              break;
1688
1689
0
            case CHILD_CLOSE_FAILED:
1690
0
              g_set_error (error,
1691
0
                           G_SPAWN_ERROR,
1692
0
                           G_SPAWN_ERROR_FAILED,
1693
0
                           _("Failed to close file descriptor for child process (%s)"),
1694
0
                           g_strerror (buf[1]));
1695
0
              break;
1696
1697
0
            default:
1698
0
              g_set_error (error,
1699
0
                           G_SPAWN_ERROR,
1700
0
                           G_SPAWN_ERROR_FAILED,
1701
0
                           _("Unknown error executing child process ā€œ%sā€"),
1702
0
                           argv[0]);
1703
0
              break;
1704
2
            }
1705
1706
2
          goto cleanup_and_fail;
1707
2
        }
1708
1709
      /* Get child pid from intermediate child pipe. */
1710
0
      if (intermediate_child)
1711
0
        {
1712
0
          n_ints = 0;
1713
          
1714
0
          if (!read_ints (g_unix_pipe_get (&child_pid_report_pipe, G_UNIX_PIPE_END_READ),
1715
0
                          buf, 1, &n_ints, error))
1716
0
            goto cleanup_and_fail;
1717
1718
0
          if (n_ints < 1)
1719
0
            {
1720
0
              int errsv = errno;
1721
1722
0
              g_set_error (error,
1723
0
                           G_SPAWN_ERROR,
1724
0
                           G_SPAWN_ERROR_FAILED,
1725
0
                           _("Failed to read enough data from child pid pipe (%s)"),
1726
0
                           g_strerror (errsv));
1727
0
              goto cleanup_and_fail;
1728
0
            }
1729
0
          else
1730
0
            {
1731
              /* we have the child pid */
1732
0
              pid = buf[0];
1733
0
            }
1734
0
        }
1735
      
1736
      /* Success against all odds! return the information */
1737
0
      g_unix_pipe_close (&child_err_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1738
0
      g_unix_pipe_close (&child_pid_report_pipe, G_UNIX_PIPE_END_READ, NULL);
1739
1740
0
      g_free (search_path_buffer_heap);
1741
0
      g_free (argv_buffer_heap);
1742
0
      g_free (source_fds_copy);
1743
1744
0
      if (child_pid)
1745
0
        *child_pid = pid;
1746
1747
0
      goto success;
1748
0
    }
1749
1750
0
success:
1751
  /* Close the uncared-about ends of the pipes */
1752
0
  g_unix_pipe_close (&stdin_pipe, G_UNIX_PIPE_END_READ, NULL);
1753
0
  g_unix_pipe_close (&stdout_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1754
0
  g_unix_pipe_close (&stderr_pipe, G_UNIX_PIPE_END_WRITE, NULL);
1755
1756
0
  if (stdin_pipe_out != NULL)
1757
0
    *stdin_pipe_out = g_unix_pipe_steal (&stdin_pipe, G_UNIX_PIPE_END_WRITE);
1758
1759
0
  if (stdout_pipe_out != NULL)
1760
0
    *stdout_pipe_out = g_unix_pipe_steal (&stdout_pipe, G_UNIX_PIPE_END_READ);
1761
1762
0
  if (stderr_pipe_out != NULL)
1763
0
    *stderr_pipe_out = g_unix_pipe_steal (&stderr_pipe, G_UNIX_PIPE_END_READ);
1764
1765
0
  return TRUE;
1766
1767
2
 cleanup_and_fail:
1768
1769
  /* There was an error from the Child, reap the child to avoid it being
1770
     a zombie.
1771
   */
1772
1773
2
  if (pid > 0)
1774
2
  {
1775
2
    wait_failed:
1776
2
     if (waitpid (pid, NULL, 0) < 0)
1777
0
       {
1778
0
          if (errno == EINTR)
1779
0
            goto wait_failed;
1780
0
          else if (errno == ECHILD)
1781
0
            ; /* do nothing, child already reaped */
1782
0
          else
1783
0
            g_warning ("waitpid() should not fail in 'fork_exec'");
1784
0
       }
1785
2
   }
1786
1787
2
  g_unix_pipe_clear (&stdin_pipe);
1788
2
  g_unix_pipe_clear (&stdout_pipe);
1789
2
  g_unix_pipe_clear (&stderr_pipe);
1790
2
  g_unix_pipe_clear (&child_err_report_pipe);
1791
2
  g_unix_pipe_clear (&child_pid_report_pipe);
1792
1793
2
  g_clear_pointer (&search_path_buffer_heap, g_free);
1794
2
  g_clear_pointer (&argv_buffer_heap, g_free);
1795
2
  g_clear_pointer (&source_fds_copy, g_free);
1796
1797
2
  return FALSE;
1798
2
}
1799
1800
/* Based on execvp from GNU C Library */
1801
1802
/* This function is called between fork() and exec() and hence must be
1803
 * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1804
static gboolean
1805
script_execute (const gchar *file,
1806
                gchar      **argv,
1807
                gchar      **argv_buffer,
1808
                gsize        argv_buffer_len,
1809
                gchar      **envp)
1810
0
{
1811
  /* Count the arguments.  */
1812
0
  gsize argc = 0;
1813
0
  while (argv[argc])
1814
0
    ++argc;
1815
1816
  /* Construct an argument list for the shell. */
1817
0
  if (argc + 2 > argv_buffer_len)
1818
0
    return FALSE;
1819
1820
0
  argv_buffer[0] = (char *) "/bin/sh";
1821
0
  argv_buffer[1] = (char *) file;
1822
0
  while (argc > 0)
1823
0
    {
1824
0
      argv_buffer[argc + 1] = argv[argc];
1825
0
      --argc;
1826
0
    }
1827
1828
  /* Execute the shell. */
1829
0
  if (envp)
1830
0
    execve (argv_buffer[0], argv_buffer, envp);
1831
0
  else
1832
0
    execv (argv_buffer[0], argv_buffer);
1833
1834
0
  return TRUE;
1835
0
}
1836
1837
/* This function is called between fork() and exec() and hence must be
1838
 * async-signal-safe (see signal-safety(7)). */
1839
static gchar*
1840
my_strchrnul (const gchar *str, gchar c)
1841
0
{
1842
0
  gchar *p = (gchar*) str;
1843
0
  while (*p && (*p != c))
1844
0
    ++p;
1845
1846
0
  return p;
1847
0
}
1848
1849
/* This function is called between fork() and exec() and hence must be
1850
 * async-signal-safe (see signal-safety(7)) until it calls exec(). */
1851
static gint
1852
g_execute (const gchar  *file,
1853
           gchar       **argv,
1854
           gchar       **argv_buffer,
1855
           gsize         argv_buffer_len,
1856
           gchar       **envp,
1857
           const gchar  *search_path,
1858
           gchar        *search_path_buffer,
1859
           gsize         search_path_buffer_len)
1860
0
{
1861
0
  if (file == NULL || *file == '\0')
1862
0
    {
1863
      /* We check the simple case first. */
1864
0
      errno = ENOENT;
1865
0
      return -1;
1866
0
    }
1867
1868
0
  if (search_path == NULL || strchr (file, '/') != NULL)
1869
0
    {
1870
      /* Don't search when it contains a slash. */
1871
0
      if (envp)
1872
0
        execve (file, argv, envp);
1873
0
      else
1874
0
        execv (file, argv);
1875
      
1876
0
      if (errno == ENOEXEC &&
1877
0
          !script_execute (file, argv, argv_buffer, argv_buffer_len, envp))
1878
0
        {
1879
0
          errno = ENOMEM;
1880
0
          return -1;
1881
0
        }
1882
0
    }
1883
0
  else
1884
0
    {
1885
0
      gboolean got_eacces = 0;
1886
0
      const gchar *path, *p;
1887
0
      gchar *name;
1888
0
      gsize len;
1889
0
      gsize pathlen;
1890
1891
0
      path = search_path;
1892
0
      len = strlen (file) + 1;
1893
0
      pathlen = strlen (path);
1894
0
      name = search_path_buffer;
1895
1896
0
      if (search_path_buffer_len < pathlen + len + 1)
1897
0
        {
1898
0
          errno = ENOMEM;
1899
0
          return -1;
1900
0
        }
1901
1902
      /* Copy the file name at the top, including '\0'  */
1903
0
      memcpy (name + pathlen + 1, file, len);
1904
0
      name = name + pathlen;
1905
      /* And add the slash before the filename  */
1906
0
      *name = '/';
1907
1908
0
      p = path;
1909
0
      do
1910
0
  {
1911
0
    char *startp;
1912
1913
0
    path = p;
1914
0
    p = my_strchrnul (path, ':');
1915
1916
0
    if (p == path)
1917
      /* Two adjacent colons, or a colon at the beginning or the end
1918
             * of 'PATH' means to search the current directory.
1919
             */
1920
0
      startp = name + 1;
1921
0
    else
1922
0
      startp = memcpy (name - (p - path), path, p - path);
1923
1924
    /* Try to execute this name.  If it works, execv will not return.  */
1925
0
          if (envp)
1926
0
            execve (startp, argv, envp);
1927
0
          else
1928
0
            execv (startp, argv);
1929
          
1930
0
          if (errno == ENOEXEC &&
1931
0
              !script_execute (startp, argv, argv_buffer, argv_buffer_len, envp))
1932
0
            {
1933
0
              errno = ENOMEM;
1934
0
              return -1;
1935
0
            }
1936
1937
0
    switch (errno)
1938
0
      {
1939
0
      case EACCES:
1940
        /* Record the we got a 'Permission denied' error.  If we end
1941
               * up finding no executable we can use, we want to diagnose
1942
               * that we did find one but were denied access.
1943
               */
1944
0
        got_eacces = TRUE;
1945
1946
0
              G_GNUC_FALLTHROUGH;
1947
0
      case ENOENT:
1948
0
#ifdef ESTALE
1949
0
      case ESTALE:
1950
0
#endif
1951
0
#ifdef ENOTDIR
1952
0
      case ENOTDIR:
1953
0
#endif
1954
        /* Those errors indicate the file is missing or not executable
1955
               * by us, in which case we want to just try the next path
1956
               * directory.
1957
               */
1958
0
        break;
1959
1960
0
      case ENODEV:
1961
0
      case ETIMEDOUT:
1962
        /* Some strange filesystems like AFS return even
1963
         * stranger error numbers.  They cannot reasonably mean anything
1964
         * else so ignore those, too.
1965
         */
1966
0
        break;
1967
1968
0
      default:
1969
        /* Some other error means we found an executable file, but
1970
               * something went wrong executing it; return the error to our
1971
               * caller.
1972
               */
1973
0
        return -1;
1974
0
      }
1975
0
  }
1976
0
      while (*p++ != '\0');
1977
1978
      /* We tried every element and none of them worked.  */
1979
0
      if (got_eacces)
1980
  /* At least one failure was due to permissions, so report that
1981
         * error.
1982
         */
1983
0
        errno = EACCES;
1984
0
    }
1985
1986
  /* Return the error from the last attempt (probably ENOENT).  */
1987
0
  return -1;
1988
0
}
1989
1990
void
1991
g_spawn_close_pid_impl (GPid pid)
1992
0
{
1993
  /* no-op */
1994
0
}