Bump to m4 1.4.19
[platform/upstream/m4.git] / 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 }