(root)/
m4-1.4.19/
tests/
test-posix_spawn-open1.c
       1  /* Test of posix_spawn() function with 'open' action.
       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  /* Test whether posix_spawn_file_actions_addopen supports filename arguments
      20     that contain special characters such as '*'.  */
      21  
      22  #include <config.h>
      23  
      24  #include <spawn.h>
      25  
      26  #include "signature.h"
      27  SIGNATURE_CHECK (posix_spawn, int, (pid_t *, char const *,
      28                                      posix_spawn_file_actions_t const *,
      29                                      posix_spawnattr_t const *,
      30                                      char *const[], char *const[]));
      31  #include <errno.h>
      32  #include <fcntl.h>
      33  #include <signal.h>
      34  #include <stdbool.h>
      35  #include <stdio.h>
      36  #include <string.h>
      37  #include <unistd.h>
      38  #include <sys/types.h>
      39  #include <sys/wait.h>
      40  
      41  #define CHILD_PROGRAM_FILENAME "test-posix_spawn-open1"
      42  #define DATA_FILENAME "t!#$%&'()*+,-;=?@[\\]^_`{|}~.tmp"
      43  /* On Windows (including Cygwin), '*' '?' '\\' '|' cannot be used in file
      44     names.  */
      45  #if defined _WIN32 || defined __CYGWIN__
      46  # undef DATA_FILENAME
      47  # define DATA_FILENAME "t!#$%&'()+,-;=@[]^_`{}~.tmp"
      48  #endif
      49  
      50  static int
      51  parent_main (void)
      52  {
      53    FILE *fp;
      54    char *argv[3] = { CHILD_PROGRAM_FILENAME, "-child", NULL };
      55    posix_spawn_file_actions_t actions;
      56    bool actions_allocated;
      57    int err;
      58    pid_t child;
      59    int status;
      60    int exitstatus;
      61  
      62    /* Create a data file with specific contents.  */
      63    fp = fopen (DATA_FILENAME, "wb");
      64    if (fp == NULL)
      65      {
      66        perror ("cannot create data file");
      67        return 1;
      68      }
      69    fwrite ("Halle Potta", 1, 11, fp);
      70    if (fflush (fp) || fclose (fp))
      71      {
      72        perror ("cannot prepare data file");
      73        return 1;
      74      }
      75  
      76    /* Avoid reading from our stdin, as it could block.  */
      77    if (freopen ("/dev/null", "rb", stdin) == NULL)
      78      {
      79        perror ("cannot redirect stdin");
      80        return 1;
      81      }
      82  
      83    /* Test whether posix_spawn_file_actions_addopen with this file name
      84       actually works, by spawning a child that reads from this file.  */
      85    actions_allocated = false;
      86    if ((err = posix_spawn_file_actions_init (&actions)) != 0
      87        || (actions_allocated = true,
      88            (err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO, DATA_FILENAME, O_RDONLY, 0600)) != 0
      89            || (err = posix_spawn (&child, CHILD_PROGRAM_FILENAME, &actions, NULL, argv, environ)) != 0))
      90      {
      91        if (actions_allocated)
      92          posix_spawn_file_actions_destroy (&actions);
      93        errno = err;
      94        perror ("subprocess failed");
      95        return 1;
      96      }
      97    posix_spawn_file_actions_destroy (&actions);
      98    status = 0;
      99    while (waitpid (child, &status, 0) != child)
     100      ;
     101    if (!WIFEXITED (status))
     102      {
     103        fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
     104        return 1;
     105      }
     106    exitstatus = WEXITSTATUS (status);
     107    if (exitstatus != 0)
     108      {
     109        fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
     110        return 1;
     111      }
     112    return 0;
     113  }
     114  
     115  static int
     116  child_main (void)
     117  {
     118    char buf[1024];
     119  
     120    /* See if reading from STDIN_FILENO yields the expected contents.  */
     121    if (fread (buf, 1, sizeof (buf), stdin) == 11
     122        && memcmp (buf, "Halle Potta", 11) == 0)
     123      return 0;
     124    else
     125      return 2;
     126  }
     127  
     128  static void
     129  cleanup_then_die (int sig)
     130  {
     131    /* Clean up data file.  */
     132    unlink (DATA_FILENAME);
     133  
     134    /* Re-raise the signal and die from it.  */
     135    signal (sig, SIG_DFL);
     136    raise (sig);
     137  }
     138  
     139  int
     140  main (int argc, char *argv[])
     141  {
     142    int exitstatus;
     143  
     144    if (!(argc > 1 && strcmp (argv[1], "-child") == 0))
     145      {
     146        /* This is the parent process.  */
     147        signal (SIGINT, cleanup_then_die);
     148        signal (SIGTERM, cleanup_then_die);
     149        #ifdef SIGHUP
     150        signal (SIGHUP, cleanup_then_die);
     151        #endif
     152  
     153        exitstatus = parent_main ();
     154      }
     155    else
     156      {
     157        /* This is the child process.  */
     158  
     159        exitstatus = child_main ();
     160      }
     161    unlink (DATA_FILENAME);
     162    return exitstatus;
     163  }