root/maint/gnulib/tests/test-posix_spawn-dup2-stdout.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fd_safer
  2. main

   1 /* Test of posix_spawn() function: reading from a subprocess.
   2    Copyright (C) 2008-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Bruno Haible <bruno@clisp.org>, 2008.  */
  18 
  19 #include <config.h>
  20 
  21 #include <spawn.h>
  22 
  23 #include "signature.h"
  24 SIGNATURE_CHECK (posix_spawnp, int, (pid_t *, char const *,
  25                                      posix_spawn_file_actions_t const *,
  26                                      posix_spawnattr_t const *,
  27                                      char *const[], char *const[]));
  28 SIGNATURE_CHECK (posix_spawnattr_init, int, (posix_spawnattr_t *));
  29 SIGNATURE_CHECK (posix_spawnattr_destroy, int, (posix_spawnattr_t *));
  30 SIGNATURE_CHECK (posix_spawnattr_setsigmask, int, (posix_spawnattr_t *,
  31                                                    sigset_t const *));
  32 SIGNATURE_CHECK (posix_spawnattr_setflags, int, (posix_spawnattr_t *, short));
  33 SIGNATURE_CHECK (posix_spawn_file_actions_init, int,
  34                  (posix_spawn_file_actions_t *));
  35 SIGNATURE_CHECK (posix_spawn_file_actions_destroy, int,
  36                  (posix_spawn_file_actions_t *));
  37 SIGNATURE_CHECK (posix_spawn_file_actions_addclose, int,
  38                  (posix_spawn_file_actions_t *, int));
  39 SIGNATURE_CHECK (posix_spawn_file_actions_addopen, int,
  40                  (posix_spawn_file_actions_t *, int, char const *, int,
  41                   mode_t));
  42 SIGNATURE_CHECK (posix_spawn_file_actions_adddup2, int,
  43                  (posix_spawn_file_actions_t *, int, int));
  44 
  45 #include <errno.h>
  46 #include <fcntl.h>
  47 #include <signal.h>
  48 #include <stdbool.h>
  49 #include <stdio.h>
  50 #include <stdlib.h>
  51 #include <string.h>
  52 #include <unistd.h>
  53 #include <sys/types.h>
  54 #include <sys/wait.h>
  55 
  56 #define CHILD_PROGRAM_FILENAME "test-posix_spawn-dup2-stdout.sh"
  57 
  58 static int
  59 fd_safer (int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61   if (0 <= fd && fd <= 2)
  62     {
  63       int f = fd_safer (dup (fd));
  64       int e = errno;
  65       close (fd);
  66       errno = e;
  67       fd = f;
  68     }
  69 
  70   return fd;
  71 }
  72 
  73 int
  74 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76   char *argv[3] = { (char *) BOURNE_SHELL, (char *) CHILD_PROGRAM_FILENAME, NULL };
  77   int ifd[2];
  78   sigset_t blocked_signals;
  79   sigset_t fatal_signal_set;
  80   posix_spawn_file_actions_t actions;
  81   bool actions_allocated;
  82   posix_spawnattr_t attrs;
  83   bool attrs_allocated;
  84   int err;
  85   pid_t child;
  86   int fd;
  87   FILE *fp;
  88   char line[80];
  89   int status;
  90   int exitstatus;
  91 
  92   if (pipe (ifd) < 0 || (ifd[0] = fd_safer (ifd[0])) < 0)
  93     {
  94       perror ("cannot create pipe");
  95       exit (1);
  96     }
  97   sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
  98   sigemptyset (&fatal_signal_set);
  99   sigaddset (&fatal_signal_set, SIGINT);
 100   sigaddset (&fatal_signal_set, SIGTERM);
 101   #ifdef SIGHUP
 102   sigaddset (&fatal_signal_set, SIGHUP);
 103   #endif
 104   #ifdef SIGPIPE
 105   sigaddset (&fatal_signal_set, SIGPIPE);
 106   #endif
 107   sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
 108   actions_allocated = false;
 109   attrs_allocated = false;
 110   if ((err = posix_spawn_file_actions_init (&actions)) != 0
 111       || (actions_allocated = true,
 112           (err = posix_spawn_file_actions_adddup2 (&actions, ifd[1], STDOUT_FILENO)) != 0
 113           || (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) != 0
 114           || (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) != 0
 115           || (err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO, "/dev/null", O_RDONLY, 0)) != 0
 116           || (err = posix_spawnattr_init (&attrs)) != 0
 117           || (attrs_allocated = true,
 118               #if defined _WIN32 && !defined __CYGWIN__
 119               0
 120               #else
 121               (err = posix_spawnattr_setsigmask (&attrs, &blocked_signals)) != 0
 122               || (err = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_SETSIGMASK)) != 0
 123               #endif
 124              )
 125           || (err = posix_spawnp (&child, BOURNE_SHELL, &actions, &attrs, argv, environ)) != 0))
 126     {
 127       if (actions_allocated)
 128         posix_spawn_file_actions_destroy (&actions);
 129       if (attrs_allocated)
 130         posix_spawnattr_destroy (&attrs);
 131       sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
 132       errno = err;
 133       perror ("subprocess failed");
 134       exit (1);
 135     }
 136   posix_spawn_file_actions_destroy (&actions);
 137   posix_spawnattr_destroy (&attrs);
 138   sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
 139   close (ifd[1]);
 140   fd = ifd[0];
 141   fp = fdopen (fd, "r");
 142   if (fp == NULL)
 143     {
 144       fprintf (stderr, "fdopen() failed\n");
 145       exit (1);
 146     }
 147   if (fread (line, 1, 80, fp) < 12)
 148     {
 149       fprintf (stderr, "could not read expected output\n");
 150       exit (1);
 151     }
 152   if (memcmp (line, "Halle Potta", 11) != 0)
 153     {
 154       fprintf (stderr, "read output is not the expected output\n");
 155       exit (1);
 156     }
 157   fclose (fp);
 158   status = 0;
 159   while (waitpid (child, &status, 0) != child)
 160     ;
 161   if (!WIFEXITED (status))
 162     {
 163       fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
 164       exit (1);
 165     }
 166   exitstatus = WEXITSTATUS (status);
 167   if (exitstatus != 0)
 168     {
 169       fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
 170       exit (1);
 171     }
 172   return 0;
 173 }

/* [previous][next][first][last][top][bottom][index][help] */