(root)/
gettext-0.22.4/
gettext-tools/
gnulib-tests/
test-execute-child.c
       1  /* Child program invoked by test-execute-main.
       2     Copyright (C) 2009-2023 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 close
      61  #undef fcntl
      62  #undef fflush
      63  #undef fgetc
      64  #undef fprintf
      65  #undef fputs
      66  #undef getcwd
      67  #undef isatty
      68  #undef open
      69  #undef raise
      70  #undef read
      71  #undef sprintf
      72  #undef strcasestr
      73  #undef strcmp
      74  #undef strlen
      75  #undef strstr
      76  #undef write
      77  
      78  #include "qemu.h"
      79  
      80  #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
      81  static void __cdecl
      82  gl_msvc_invalid_parameter_handler (const wchar_t *expression,
      83                                     const wchar_t *function,
      84                                     const wchar_t *file,
      85                                     unsigned int line,
      86                                     uintptr_t dummy)
      87  {
      88  }
      89  #endif
      90  
      91  /* Return non-zero if FD is open.  */
      92  static int
      93  is_open (int fd)
      94  {
      95  #if defined _WIN32 && ! defined __CYGWIN__
      96    /* On native Windows, the initial state of unassigned standard file
      97       descriptors is that they are open but point to an
      98       INVALID_HANDLE_VALUE, and there is no fcntl.  */
      99    return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
     100  #else
     101  # ifndef F_GETFL
     102  #  error Please port fcntl to your platform
     103  # endif
     104    return 0 <= fcntl (fd, F_GETFL);
     105  #endif
     106  }
     107  
     108  int
     109  main (int argc, char *argv[])
     110  {
     111    if (argc == 1)
     112      /* Check an invocation without arguments.  Check the exit code.  */
     113      return 40;
     114  
     115    int test = atoi (argv[1]);
     116    switch (test)
     117      {
     118      case 2:
     119        /* Check argument passing.  */
     120        return !(argc == 12
     121                 && strcmp (argv[2], "abc def") == 0
     122                 && strcmp (argv[3], "abc\"def\"ghi") == 0
     123                 && strcmp (argv[4], "xyz\"") == 0
     124                 && strcmp (argv[5], "abc\\def\\ghi") == 0
     125                 && strcmp (argv[6], "xyz\\") == 0
     126                 && strcmp (argv[7], "???") == 0
     127                 && strcmp (argv[8], "***") == 0
     128                 && strcmp (argv[9], "") == 0
     129                 && strcmp (argv[10], "foo") == 0
     130                 && strcmp (argv[11], "") == 0);
     131      #if !(defined _WIN32 && !defined __CYGWIN__)
     132      case 3:
     133        /* Check SIGPIPE handling with ignore_sigpipe = false.  */
     134      case 4:
     135        /* Check SIGPIPE handling with ignore_sigpipe = true.  */
     136        raise (SIGPIPE);
     137        return 71;
     138      #endif
     139      case 5:
     140        /* Check other signal.  */
     141        raise (SIGINT);
     142        return 71;
     143      case 6:
     144        /* Check stdin is inherited.  */
     145        return !(fgetc (stdin) == 'F' && fgetc (stdin) == 'o');
     146      case 7:
     147        /* Check null_stdin = true.  */
     148        return !(fgetc (stdin) == EOF);
     149      case 8:
     150        /* Check stdout is inherited, part 1 (regular file).  */
     151        return !(fputs ("bar", stdout) != EOF && fflush (stdout) == 0);
     152      case 9:
     153        /* Check stdout is inherited, part 2 (device).  */
     154      case 10:
     155        /* Check null_stdout = true.  */
     156        return !is_device (STDOUT_FILENO);
     157      case 11:
     158        /* Check stderr is inherited, part 1 (regular file).  */
     159        return !(fputs ("bar", stderr) != EOF && fflush (stderr) == 0);
     160      case 12:
     161        /* Check stderr is inherited, part 2 (device).  */
     162      case 13:
     163        /* Check null_stderr = true.  */
     164        return !is_device (STDERR_FILENO);
     165      case 14:
     166      case 15:
     167        /* Check file descriptors >= 3 can be inherited.  */
     168      case 16:
     169        /* Check file descriptors >= 3 with O_CLOEXEC bit are not inherited.  */
     170        #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
     171        /* Avoid exceptions from within _get_osfhandle.  */
     172        _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler);
     173        #endif
     174        {
     175          /* QEMU 6.1 in user-mode passes an open fd = 3, that references
     176             /dev/urandom.  We need to ignore this fd.  */
     177          bool is_qemu = is_running_under_qemu_user ();
     178          char buf[300];
     179          buf[0] = '\0';
     180          char *p = buf;
     181          int fd;
     182          for (fd = 0; fd < 20; fd++)
     183            if (is_open (fd) && !(is_qemu && fd == 3))
     184              {
     185                sprintf (p, "%d ", fd);
     186                p += strlen (p);
     187              }
     188          const char *expected = (test < 16 ? "0 1 2 10 " : "0 1 2 ");
     189          if (strcmp (buf, expected) == 0)
     190            return 0;
     191          else
     192            {
     193              fprintf (stderr, "Test case %d: %s\n", test, buf); fflush (stderr);
     194              return 1;
     195            }
     196        }
     197      case 17:
     198        /* Check that file descriptors >= 3, open for reading, can be inherited,
     199           including the file position.  */
     200        {
     201          char buf[6];
     202          int n = read (10, buf, sizeof (buf));
     203          return !(n == 4 && memcmp (buf, "obar", 4) == 0);
     204        }
     205      case 18:
     206        /* Check that file descriptors >= 3, open for writing, can be inherited,
     207           including the file position.  */
     208        {
     209          int n = write (10, "bar", 3);
     210          return !(n == 3);
     211        }
     212      case 19:
     213        /* Check that file descriptors >= 3, when inherited, preserve their
     214           isatty() property, part 1 (regular file).  */
     215      case 20:
     216        /* Check that file descriptors >= 3, when inherited, preserve their
     217           isatty() property, part 2 (character devices).  */
     218        {
     219          #if defined _WIN32 && ! defined __CYGWIN__
     220          return 4 + 2 * (_isatty (10) != 0) + (_isatty (11) != 0);
     221          #else
     222          return 4 + 2 * (isatty (10) != 0) + (isatty (11) != 0);
     223          #endif
     224        }
     225      case 21:
     226        /* Check execution in a different directory.  */
     227        {
     228          char cwd[1024];
     229          #if defined _WIN32 && ! defined __CYGWIN__
     230          if (_chdir ("..") != 0)
     231            return 1;
     232          if (_getcwd (cwd, sizeof (cwd)) == NULL)
     233            return 2;
     234          #else
     235          if (chdir ("..") != 0)
     236            return 1;
     237          if (getcwd (cwd, sizeof (cwd)) == NULL)
     238            return 2;
     239          #endif
     240          return (argc == 3 && strcmp (argv[2], cwd) == 0 ? 0 : 3);
     241        }
     242      default:
     243        abort ();
     244      }
     245  }