root/maint/gnulib/tests/test-posix_spawn-dup2-stdin.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: writing to 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 <errno.h>
  24 #include <fcntl.h>
  25 #include <signal.h>
  26 #include <stdbool.h>
  27 #include <stdio.h>
  28 #include <stdlib.h>
  29 #include <string.h>
  30 #include <unistd.h>
  31 #include <sys/types.h>
  32 #include <sys/wait.h>
  33 
  34 #define CHILD_PROGRAM_FILENAME "test-posix_spawn-dup2-stdin.sh"
  35 
  36 static int
  37 fd_safer (int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39   if (0 <= fd && fd <= 2)
  40     {
  41       int f = fd_safer (dup (fd));
  42       int e = errno;
  43       close (fd);
  44       errno = e;
  45       fd = f;
  46     }
  47 
  48   return fd;
  49 }
  50 
  51 int
  52 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54   char *argv[3] = { (char *) BOURNE_SHELL, (char *) CHILD_PROGRAM_FILENAME, NULL };
  55   int ofd[2];
  56   sigset_t blocked_signals;
  57   sigset_t fatal_signal_set;
  58   posix_spawn_file_actions_t actions;
  59   bool actions_allocated;
  60   posix_spawnattr_t attrs;
  61   bool attrs_allocated;
  62   int err;
  63   pid_t child;
  64   int fd;
  65   FILE *fp;
  66   int written;
  67   int status;
  68   int exitstatus;
  69 
  70   if (pipe (ofd) < 0 || (ofd[1] = fd_safer (ofd[1])) < 0)
  71     {
  72       perror ("cannot create pipe");
  73       exit (1);
  74     }
  75   sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
  76   sigemptyset (&fatal_signal_set);
  77   sigaddset (&fatal_signal_set, SIGINT);
  78   sigaddset (&fatal_signal_set, SIGTERM);
  79   #ifdef SIGHUP
  80   sigaddset (&fatal_signal_set, SIGHUP);
  81   #endif
  82   #ifdef SIGPIPE
  83   sigaddset (&fatal_signal_set, SIGPIPE);
  84   #endif
  85   sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
  86   actions_allocated = false;
  87   attrs_allocated = false;
  88   if ((err = posix_spawn_file_actions_init (&actions)) != 0
  89       || (actions_allocated = true,
  90           (err = posix_spawn_file_actions_adddup2 (&actions, ofd[0], STDIN_FILENO)) != 0
  91           || (err = posix_spawn_file_actions_addclose (&actions, ofd[0])) != 0
  92           || (err = posix_spawn_file_actions_addclose (&actions, ofd[1])) != 0
  93           || (err = posix_spawnattr_init (&attrs)) != 0
  94           || (attrs_allocated = true,
  95               #if defined _WIN32 && !defined __CYGWIN__
  96               0
  97               #else
  98               (err = posix_spawnattr_setsigmask (&attrs, &blocked_signals)) != 0
  99               || (err = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_SETSIGMASK)) != 0
 100               #endif
 101              )
 102           || (err = posix_spawnp (&child, BOURNE_SHELL, &actions, &attrs, argv, environ)) != 0))
 103     {
 104       if (actions_allocated)
 105         posix_spawn_file_actions_destroy (&actions);
 106       if (attrs_allocated)
 107         posix_spawnattr_destroy (&attrs);
 108       sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
 109       errno = err;
 110       perror ("subprocess failed");
 111       exit (1);
 112     }
 113   posix_spawn_file_actions_destroy (&actions);
 114   posix_spawnattr_destroy (&attrs);
 115   sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
 116   close (ofd[0]);
 117   fd = ofd[1];
 118   fp = fdopen (fd, "w");
 119   if (fp == NULL)
 120     {
 121       fprintf (stderr, "fdopen() failed\n");
 122       exit (1);
 123     }
 124   written = fwrite ("Halle Potta\n", 1, 12, fp);
 125   if (written < 12)
 126     {
 127       fprintf (stderr, "could not write input\n");
 128       exit (1);
 129     }
 130   fclose (fp);
 131   status = 0;
 132   while (waitpid (child, &status, 0) != child)
 133     ;
 134   if (!WIFEXITED (status))
 135     {
 136       fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
 137       exit (1);
 138     }
 139   exitstatus = WEXITSTATUS (status);
 140   if (exitstatus != 0)
 141     {
 142       fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
 143       exit (1);
 144     }
 145   return 0;
 146 }

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