Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/tests/gen/posix_spawn_test.c
39491 views
1
/*-
2
* Copyright (c) 2011 Jilles Tjoelker
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
/*
28
* Test program for posix_spawn() and posix_spawnp() as specified by
29
* IEEE Std. 1003.1-2008.
30
*/
31
32
#include <sys/param.h>
33
#include <sys/stat.h>
34
#include <sys/wait.h>
35
#include <errno.h>
36
#include <fcntl.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <spawn.h>
41
42
#include <atf-c.h>
43
44
static const char true_script[] =
45
"#!/usr/bin/env\n"
46
"/usr/bin/true\n";
47
48
char *myenv[2] = { "answer=42", NULL };
49
50
ATF_TC_WITHOUT_HEAD(posix_spawn_simple_test);
51
ATF_TC_BODY(posix_spawn_simple_test, tc)
52
{
53
char *myargs[4];
54
int error, status;
55
pid_t pid, waitres;
56
57
/* Make sure we have no child processes. */
58
while (waitpid(-1, NULL, 0) != -1)
59
;
60
ATF_REQUIRE_MSG(errno == ECHILD, "errno was not ECHILD: %d", errno);
61
62
/* Simple test. */
63
myargs[0] = "sh";
64
myargs[1] = "-c";
65
myargs[2] = "exit $answer";
66
myargs[3] = NULL;
67
error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv);
68
ATF_REQUIRE(error == 0);
69
waitres = waitpid(pid, &status, 0);
70
ATF_REQUIRE(waitres == pid);
71
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
72
}
73
74
ATF_TC_WITHOUT_HEAD(posix_spawn_no_such_command_negative_test);
75
ATF_TC_BODY(posix_spawn_no_such_command_negative_test, tc)
76
{
77
char *myargs[4];
78
int error, status;
79
pid_t pid, waitres;
80
81
/*
82
* If the executable does not exist, the function shall either fail
83
* and not create a child process or succeed and create a child
84
* process that exits with status 127.
85
*/
86
myargs[0] = "/var/empty/nonexistent";
87
myargs[1] = NULL;
88
error = posix_spawn(&pid, myargs[0], NULL, NULL, myargs, myenv);
89
if (error == 0) {
90
waitres = waitpid(pid, &status, 0);
91
ATF_REQUIRE(waitres == pid);
92
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 127);
93
} else {
94
ATF_REQUIRE(error == ENOENT);
95
waitres = waitpid(-1, NULL, 0);
96
ATF_REQUIRE(waitres == -1 && errno == ECHILD);
97
}
98
}
99
100
ATF_TC_WITHOUT_HEAD(posix_spawnp_enoexec_fallback);
101
ATF_TC_BODY(posix_spawnp_enoexec_fallback, tc)
102
{
103
char buf[FILENAME_MAX];
104
char *myargs[2];
105
int error, status;
106
pid_t pid, waitres;
107
108
snprintf(buf, sizeof(buf), "%s/spawnp_enoexec.sh",
109
atf_tc_get_config_var(tc, "srcdir"));
110
myargs[0] = buf;
111
myargs[1] = NULL;
112
error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv);
113
ATF_REQUIRE(error == 0);
114
waitres = waitpid(pid, &status, 0);
115
ATF_REQUIRE(waitres == pid);
116
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
117
}
118
119
ATF_TC_WITHOUT_HEAD(posix_spawnp_enoexec_fallback_null_argv0);
120
ATF_TC_BODY(posix_spawnp_enoexec_fallback_null_argv0, tc)
121
{
122
char buf[FILENAME_MAX];
123
char *myargs[1];
124
int error;
125
pid_t pid;
126
127
snprintf(buf, sizeof(buf), "%s/spawnp_enoexec.sh",
128
atf_tc_get_config_var(tc, "srcdir"));
129
myargs[0] = NULL;
130
error = posix_spawnp(&pid, buf, NULL, NULL, myargs, myenv);
131
ATF_REQUIRE(error == EINVAL);
132
}
133
134
ATF_TC(posix_spawnp_eacces);
135
ATF_TC_HEAD(posix_spawnp_eacces, tc)
136
{
137
atf_tc_set_md_var(tc, "descr", "Verify EACCES behavior in posix_spawnp");
138
atf_tc_set_md_var(tc, "require.user", "unprivileged");
139
}
140
ATF_TC_BODY(posix_spawnp_eacces, tc)
141
{
142
const struct spawnp_eacces_tc {
143
const char *pathvar;
144
int error_expected;
145
} spawnp_eacces_tests[] = {
146
{ ".", EACCES }, /* File exists, but not +x */
147
{ "unsearchable", ENOENT }, /* File exists, dir not +x */
148
};
149
char *myargs[2] = { "eacces", NULL };
150
int error;
151
152
error = mkdir("unsearchable", 0755);
153
ATF_REQUIRE(error == 0);
154
error = symlink("/usr/bin/true", "unsearchable/eacces");
155
ATF_REQUIRE(error == 0);
156
157
(void)chmod("unsearchable", 0444);
158
159
/* this will create a non-executable file */
160
atf_utils_create_file("eacces", true_script);
161
162
for (size_t i = 0; i < nitems(spawnp_eacces_tests); i++) {
163
const struct spawnp_eacces_tc *tc = &spawnp_eacces_tests[i];
164
pid_t pid;
165
166
error = setenv("PATH", tc->pathvar, 1);
167
ATF_REQUIRE_EQ(0, error);
168
169
error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs,
170
myenv);
171
ATF_CHECK_INTEQ_MSG(tc->error_expected, error,
172
"path '%s'", tc->pathvar);
173
}
174
}
175
176
ATF_TP_ADD_TCS(tp)
177
{
178
179
ATF_TP_ADD_TC(tp, posix_spawn_simple_test);
180
ATF_TP_ADD_TC(tp, posix_spawn_no_such_command_negative_test);
181
ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback);
182
ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback_null_argv0);
183
ATF_TP_ADD_TC(tp, posix_spawnp_eacces);
184
185
return (atf_no_error());
186
}
187
188