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