1 /* Test of create_pipe_in/wait_subprocess.
2 Copyright (C) 2020-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 #include <config.h>
18
19 #include "spawn-pipe.h"
20 #include "wait-process.h"
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "macros.h"
28
29 int
30 main ()
31 {
32 /* Check an invocation of an executable script.
33 This should only be supported if the script has a '#!' marker; otherwise
34 it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
35 POSIX says that the execlp() and execvp() functions support executing
36 shell scripts
37 <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
38 but this is considered an antiquated feature. */
39 int fd[1];
40 pid_t pid;
41
42 {
43 size_t i;
44
45 for (i = 0; i < 2; i++)
46 {
47 const char *progname =
48 (i == 0 ? "executable-script" : "executable-script.sh");
49 const char *prog_path =
50 (i == 0 ? SRCDIR "executable-script" : SRCDIR "executable-script.sh");
51 const char *prog_argv[2] = { prog_path, NULL };
52
53 pid = create_pipe_in (progname, prog_argv[0], prog_argv, NULL,
54 NULL, false, true, false, fd);
55 if (pid >= 0)
56 {
57 /* Wait for child. */
58 ASSERT (wait_subprocess (pid, progname, true, true, true, false,
59 NULL)
60 == 127);
61 }
62 else
63 {
64 ASSERT (pid == -1);
65 ASSERT (errno == ENOEXEC);
66 }
67 }
68 }
69
70 #if defined _WIN32 && !defined __CYGWIN__
71 /* On native Windows, scripts - even with '#!' marker - are not executable.
72 Only .bat and .cmd files are. */
73 fprintf (stderr, "Skipping test: scripts are not executable on this platform.\n");
74 return 77;
75 #else
76 {
77 const char *progname = "executable-shell-script";
78 const char *prog_path = SRCDIR "executable-shell-script";
79 const char *prog_argv[2] = { prog_path, NULL };
80
81 pid = create_pipe_in (progname, prog_argv[0], prog_argv, NULL,
82 NULL, false, true, false, fd);
83 ASSERT (pid >= 0);
84 ASSERT (fd[0] > STDERR_FILENO);
85
86 /* Get child's output. */
87 char buffer[1024];
88 FILE *fp = fdopen (fd[0], "r");
89 ASSERT (fp != NULL);
90 ASSERT (fread (buffer, 1, sizeof (buffer), fp) == 11);
91
92 /* Check the result. */
93 ASSERT (memcmp (buffer, "Halle Potta", 11) == 0);
94
95 /* Wait for child. */
96 ASSERT (wait_subprocess (pid, progname, true, false, true, true, NULL) == 0);
97
98 ASSERT (fclose (fp) == 0);
99 }
100
101 return 0;
102 #endif
103 }