(root)/
m4-1.4.19/
tests/
test-spawn-pipe-child.c
       1  /* Child program invoked by test-spawn-pipe-main.
       2     Copyright (C) 2009-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, or (at your option)
       7     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  #include <config.h>
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <stdint.h>
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <unistd.h>
      25  
      26  #if defined _WIN32 && ! defined __CYGWIN__
      27  /* Get declarations of the native Windows API functions.  */
      28  # define WIN32_LEAN_AND_MEAN
      29  # include <windows.h>
      30  #endif
      31  
      32  /* Depending on arguments, this test intentionally closes stderr or
      33     starts life with stderr closed.  So, we arrange to have fd 10
      34     (outside the range of interesting fd's during the test) set up to
      35     duplicate the original stderr.  */
      36  
      37  #define BACKUP_STDERR_FILENO 10
      38  #define ASSERT_STREAM myerr
      39  #include "macros.h"
      40  
      41  static FILE *myerr;
      42  
      43  /* In this file, we use only system functions, no overrides from gnulib.  */
      44  #undef atoi
      45  #undef close
      46  #undef fcntl
      47  #undef fdopen
      48  #undef fflush
      49  #undef fprintf
      50  #undef read
      51  #undef write
      52  #if defined _WIN32 && !defined __CYGWIN__
      53  # define fdopen _fdopen
      54  #endif
      55  
      56  #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
      57  static void __cdecl
      58  gl_msvc_invalid_parameter_handler (const wchar_t *expression,
      59                                     const wchar_t *function,
      60                                     const wchar_t *file,
      61                                     unsigned int line,
      62                                     uintptr_t dummy)
      63  {
      64  }
      65  #endif
      66  
      67  /* Return non-zero if FD is open.  */
      68  static int
      69  is_open (int fd)
      70  {
      71  #if defined _WIN32 && ! defined __CYGWIN__
      72    /* On native Windows, the initial state of unassigned standard file
      73       descriptors is that they are open but point to an
      74       INVALID_HANDLE_VALUE, and there is no fcntl.  */
      75    return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
      76  #else
      77  # ifndef F_GETFL
      78  #  error Please port fcntl to your platform
      79  # endif
      80    return 0 <= fcntl (fd, F_GETFL);
      81  #endif
      82  }
      83  
      84  int
      85  main (int argc, char *argv[])
      86  {
      87    /* fd 2 might be closed, but fd BACKUP_STDERR_FILENO is the original
      88       stderr.  */
      89    myerr = fdopen (BACKUP_STDERR_FILENO, "w");
      90    if (!myerr)
      91      return 2;
      92  
      93    ASSERT (argc == 2);
      94  
      95  #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
      96    /* Avoid exceptions from within _get_osfhandle.  */
      97    _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler);
      98  #endif
      99  
     100    /* Read one byte from fd 0, and write its value plus one to fd 1.
     101       fd 2 should be closed iff the argument is 1.  Check that no other file
     102       descriptors leaked.  */
     103  
     104    char buffer[2] = { 's', 't' };
     105  
     106    ASSERT (read (STDIN_FILENO, buffer, 2) == 1);
     107  
     108    buffer[0]++;
     109    ASSERT (write (STDOUT_FILENO, buffer, 1) == 1);
     110  
     111    switch (atoi (argv[1]))
     112      {
     113      case 0:
     114        /* Expect fd 2 is open.  */
     115        ASSERT (is_open (STDERR_FILENO));
     116        break;
     117      case 1:
     118        /* Expect fd 2 is closed.
     119           But on HP-UX 11, fd 2 gets automatically re-opened to /dev/null if it
     120           was closed.  Similarly on native Windows.  Future POSIX will allow
     121           this, see <http://austingroupbugs.net/view.php?id=173>.  */
     122  #if !(defined __hpux || (defined _WIN32 && ! defined __CYGWIN__))
     123        ASSERT (! is_open (STDERR_FILENO));
     124  #endif
     125        break;
     126      default:
     127        ASSERT (0);
     128      }
     129  
     130    int fd;
     131    for (fd = 3; fd < 7; fd++)
     132      {
     133        errno = 0;
     134        ASSERT (close (fd) == -1);
     135        ASSERT (errno == EBADF);
     136      }
     137  
     138    return 0;
     139  }