(root)/
m4-1.4.19/
tests/
test-posix_spawn-dup2-stdin.c
       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)
      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 ()
      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  }