1 /* Test of posix_spawn() function.
2 Copyright (C) 2020-2024 Free Software Foundation, Inc.
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)
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.
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/>. */
26 #include <sys/types.h>
31 #define DATA_FILENAME "test-posix_spawn-script.tmp"
36 unlink (DATA_FILENAME
);
38 /* Check an invocation of an executable script.
39 This should only be supported if the script has a '#!' marker; otherwise
40 it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
41 POSIX says that the execlp() and execvp() functions support executing
43 <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
44 but this is considered an antiquated feature. */
47 posix_spawn_file_actions_t actions
;
48 ASSERT (posix_spawn_file_actions_init (&actions
) == 0);
49 ASSERT (posix_spawn_file_actions_addopen (&actions
, STDOUT_FILENO
,
51 O_RDWR
| O_CREAT
| O_TRUNC
, 0600)
57 for (i
= 0; i
< 2; i
++)
59 const char *prog_path
=
60 (i
== 0 ? SRCDIR
"executable-script" : SRCDIR
"executable-script.sh");
61 const char *prog_argv
[2] = { prog_path
, NULL
};
63 int err
= posix_spawn (&child
, prog_path
, &actions
, NULL
,
64 (char **) prog_argv
, environ
);
70 perror ("posix_spawn");
76 while (waitpid (child
, &status
, 0) != child
)
78 if (!WIFEXITED (status
))
80 fprintf (stderr
, "subprocess terminated with unexpected wait status %d\n", status
);
83 int exitstatus
= WEXITSTATUS (status
);
84 if (exitstatus
!= 127)
86 fprintf (stderr
, "subprocess terminated with unexpected exit status %d\n", exitstatus
);
93 #if defined _WIN32 && !defined __CYGWIN__
94 /* On native Windows, scripts - even with '#!' marker - are not executable.
95 Only .bat and .cmd files are. */
96 if (test_exit_status
!= EXIT_SUCCESS
)
97 return test_exit_status
;
98 fprintf (stderr
, "Skipping test: scripts are not executable on this platform.\n");
102 const char *prog_path
= SRCDIR
"executable-shell-script";
103 const char *prog_argv
[2] = { prog_path
, NULL
};
105 int err
= posix_spawn (&child
, prog_path
, &actions
, NULL
,
106 (char **) prog_argv
, environ
);
110 perror ("posix_spawn");
114 posix_spawn_file_actions_destroy (&actions
);
116 /* Wait for child. */
118 while (waitpid (child
, &status
, 0) != child
)
120 if (!WIFEXITED (status
))
122 fprintf (stderr
, "subprocess terminated with unexpected wait status %d\n", status
);
125 int exitstatus
= WEXITSTATUS (status
);
128 fprintf (stderr
, "subprocess terminated with unexpected exit status %d\n", exitstatus
);
132 /* Check the contents of the data file. */
133 FILE *fp
= fopen (DATA_FILENAME
, "rb");
136 perror ("cannot open data file");
140 int nread
= fread (buf
, 1, sizeof (buf
), fp
);
141 if (!(nread
== 11 && memcmp (buf
, "Halle Potta", 11) == 0))
143 fprintf (stderr
, "data file wrong: has %d bytes, expected %d bytes\n", nread
, 11);
148 perror ("cannot close data file");
154 /* Clean up data file. */
155 unlink (DATA_FILENAME
);
157 return test_exit_status
;