(root)/
m4-1.4.19/
tests/
test-execute-child.c
       1  /* Child program invoked by test-execute-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  /* If the user's config.h happens to include <sys/stat.h>, let it include only
      18     the system's <sys/stat.h> here.  */
      19  #define __need_system_sys_stat_h
      20  #include <config.h>
      21  
      22  /* Get the original definition of fstat.  It might be defined as a macro.
      23     Also, 'stat' might be defined as a macro.  */
      24  #include <sys/types.h>
      25  #include <sys/stat.h>
      26  #undef __need_system_sys_stat_h
      27  
      28  /* Return non-zero if FD is opened to a device.  */
      29  static int
      30  is_device (int fd)
      31  {
      32  #if defined _WIN32 && ! defined __CYGWIN__
      33    struct _stat st;
      34    return _fstat (fd, &st) >= 0 && !((st.st_mode & S_IFMT) == S_IFREG);
      35  #else
      36    struct stat st;
      37    return fstat (fd, &st) >= 0 && !S_ISREG (st.st_mode);
      38  #endif
      39  }
      40  
      41  /* Now include the other header files.  */
      42  #include <fcntl.h>
      43  #include <signal.h>
      44  #include <stdint.h>
      45  #include <stdio.h>
      46  #include <stdlib.h>
      47  #include <string.h>
      48  #include <unistd.h>
      49  
      50  #if defined _WIN32 && ! defined __CYGWIN__
      51  /* Get declarations of the native Windows API functions.  */
      52  # define WIN32_LEAN_AND_MEAN
      53  # include <windows.h>
      54  /* Get _get_osfhandle, _isatty, _chdir, _getcwd.  */
      55  # include <io.h>
      56  #endif
      57  
      58  /* In this file, we use only system functions, no overrides from gnulib.  */
      59  #undef atoi
      60  #undef fcntl
      61  #undef fflush
      62  #undef fgetc
      63  #undef fprintf
      64  #undef fputs
      65  #undef getcwd
      66  #undef isatty
      67  #undef raise
      68  #undef read
      69  #undef sprintf
      70  #undef strcmp
      71  #undef strlen
      72  #undef write
      73  
      74  #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
      75  static void __cdecl
      76  gl_msvc_invalid_parameter_handler (const wchar_t *expression,
      77                                     const wchar_t *function,
      78                                     const wchar_t *file,
      79                                     unsigned int line,
      80                                     uintptr_t dummy)
      81  {
      82  }
      83  #endif
      84  
      85  /* Return non-zero if FD is open.  */
      86  static int
      87  is_open (int fd)
      88  {
      89  #if defined _WIN32 && ! defined __CYGWIN__
      90    /* On native Windows, the initial state of unassigned standard file
      91       descriptors is that they are open but point to an
      92       INVALID_HANDLE_VALUE, and there is no fcntl.  */
      93    return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
      94  #else
      95  # ifndef F_GETFL
      96  #  error Please port fcntl to your platform
      97  # endif
      98    return 0 <= fcntl (fd, F_GETFL);
      99  #endif
     100  }
     101  
     102  int
     103  main (int argc, char *argv[])
     104  {
     105    if (argc == 1)
     106      /* Check an invocation without arguments.  Check the exit code.  */
     107      return 40;
     108  
     109    int test = atoi (argv[1]);
     110    switch (test)
     111      {
     112      case 2:
     113        /* Check argument passing.  */
     114        return !(argc == 12
     115                 && strcmp (argv[2], "abc def") == 0
     116                 && strcmp (argv[3], "abc\"def\"ghi") == 0
     117                 && strcmp (argv[4], "xyz\"") == 0
     118                 && strcmp (argv[5], "abc\\def\\ghi") == 0
     119                 && strcmp (argv[6], "xyz\\") == 0
     120                 && strcmp (argv[7], "???") == 0
     121                 && strcmp (argv[8], "***") == 0
     122                 && strcmp (argv[9], "") == 0
     123                 && strcmp (argv[10], "foo") == 0
     124                 && strcmp (argv[11], "") == 0);
     125      #if !(defined _WIN32 && !defined __CYGWIN__)
     126      case 3:
     127        /* Check SIGPIPE handling with ignore_sigpipe = false.  */
     128      case 4:
     129        /* Check SIGPIPE handling with ignore_sigpipe = true.  */
     130        raise (SIGPIPE);
     131        return 71;
     132      #endif
     133      case 5:
     134        /* Check other signal.  */
     135        raise (SIGINT);
     136        return 71;
     137      case 6:
     138        /* Check stdin is inherited.  */
     139        return !(fgetc (stdin) == 'F' && fgetc (stdin) == 'o');
     140      case 7:
     141        /* Check null_stdin = true.  */
     142        return !(fgetc (stdin) == EOF);
     143      case 8:
     144        /* Check stdout is inherited, part 1 (regular file).  */
     145        return !(fputs ("bar", stdout) != EOF && fflush (stdout) == 0);
     146      case 9:
     147        /* Check stdout is inherited, part 2 (device).  */
     148      case 10:
     149        /* Check null_stdout = true.  */
     150        return !is_device (STDOUT_FILENO);
     151      case 11:
     152        /* Check stderr is inherited, part 1 (regular file).  */
     153        return !(fputs ("bar", stderr) != EOF && fflush (stderr) == 0);
     154      case 12:
     155        /* Check stderr is inherited, part 2 (device).  */
     156      case 13:
     157        /* Check null_stderr = true.  */
     158        return !is_device (STDERR_FILENO);
     159      case 14:
     160      case 15:
     161        /* Check file descriptors >= 3 can be inherited.  */
     162      case 16:
     163        /* Check file descriptors >= 3 with O_CLOEXEC bit are not inherited.  */
     164        #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
     165        /* Avoid exceptions from within _get_osfhandle.  */
     166        _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler);
     167        #endif
     168        {
     169          char buf[300];
     170          buf[0] = '\0';
     171          char *p = buf;
     172          int fd;
     173          for (fd = 0; fd < 20; fd++)
     174            if (is_open (fd))
     175              {
     176                sprintf (p, "%d ", fd);
     177                p += strlen (p);
     178              }
     179          const char *expected = (test < 16 ? "0 1 2 10 " : "0 1 2 ");
     180          if (strcmp (buf, expected) == 0)
     181            return 0;
     182          else
     183            {
     184              fprintf (stderr, "Test case %d: %s\n", test, buf); fflush (stderr);
     185              return 1;
     186            }
     187        }
     188      case 17:
     189        /* Check that file descriptors >= 3, open for reading, can be inherited,
     190           including the file position.  */
     191        {
     192          char buf[6];
     193          int n = read (10, buf, sizeof (buf));
     194          return !(n == 4 && memcmp (buf, "obar", 4) == 0);
     195        }
     196      case 18:
     197        /* Check that file descriptors >= 3, open for writing, can be inherited,
     198           including the file position.  */
     199        {
     200          int n = write (10, "bar", 3);
     201          return !(n == 3);
     202        }
     203      case 19:
     204        /* Check that file descriptors >= 3, when inherited, preserve their
     205           isatty() property, part 1 (regular file).  */
     206      case 20:
     207        /* Check that file descriptors >= 3, when inherited, preserve their
     208           isatty() property, part 2 (character devices).  */
     209        {
     210          #if defined _WIN32 && ! defined __CYGWIN__
     211          return 4 + 2 * (_isatty (10) != 0) + (_isatty (11) != 0);
     212          #else
     213          return 4 + 2 * (isatty (10) != 0) + (isatty (11) != 0);
     214          #endif
     215        }
     216      case 21:
     217        /* Check execution in a different directory.  */
     218        {
     219          char cwd[1024];
     220          #if defined _WIN32 && ! defined __CYGWIN__
     221          if (_chdir ("..") != 0)
     222            return 1;
     223          if (_getcwd (cwd, sizeof (cwd)) == NULL)
     224            return 2;
     225          #else
     226          if (chdir ("..") != 0)
     227            return 1;
     228          if (getcwd (cwd, sizeof (cwd)) == NULL)
     229            return 2;
     230          #endif
     231          return (argc == 3 && strcmp (argv[2], cwd) == 0 ? 0 : 3);
     232        }
     233      default:
     234        abort ();
     235      }
     236  }