]>
Commit | Line | Data |
---|---|---|
df859a0c | 1 | /* Test for vfork functions. |
f7a9f785 | 2 | Copyright (C) 2007-2016 Free Software Foundation, Inc. |
df859a0c UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Jakub Jelinek <jakub@redhat.com>, 2007. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Lesser General Public | |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
df859a0c UD |
19 | |
20 | #include <errno.h> | |
21 | #include <fcntl.h> | |
22 | #include <mcheck.h> | |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | #include <unistd.h> | |
26 | #include <sys/wait.h> | |
27 | ||
28 | static int do_test (void); | |
29 | static void do_prepare (void); | |
30 | char *tmpdirname; | |
31 | ||
32 | #define TEST_FUNCTION do_test () | |
33 | #define PREPARE(argc, argv) do_prepare () | |
34 | #include "../test-skeleton.c" | |
35 | ||
36 | static int | |
37 | do_test (void) | |
38 | { | |
39 | mtrace (); | |
40 | ||
41 | const char *path = getenv ("PATH"); | |
42 | if (path == NULL) | |
43 | path = "/bin"; | |
44 | char pathbuf[strlen (tmpdirname) + 1 + strlen (path) + 1]; | |
45 | strcpy (stpcpy (stpcpy (pathbuf, tmpdirname), ":"), path); | |
46 | if (setenv ("PATH", pathbuf, 1) < 0) | |
47 | { | |
48 | puts ("setenv failed"); | |
49 | return 1; | |
50 | } | |
51 | ||
52 | size_t i; | |
53 | char *argv[3] = { (char *) "script1.sh", (char *) "1", NULL }; | |
54 | for (i = 0; i < 5; i++) | |
55 | { | |
56 | pid_t pid = vfork (); | |
57 | if (pid < 0) | |
58 | { | |
59 | printf ("vfork failed: %m\n"); | |
60 | return 1; | |
61 | } | |
62 | else if (pid == 0) | |
63 | { | |
64 | execvp ("script1.sh", argv); | |
65 | _exit (errno); | |
66 | } | |
67 | int status; | |
68 | if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) | |
69 | { | |
70 | puts ("waitpid failed"); | |
71 | return 1; | |
72 | } | |
73 | else if (status != 0) | |
74 | { | |
75 | if (WIFEXITED (status)) | |
76 | printf ("script1.sh failed with status %d\n", | |
77 | WEXITSTATUS (status)); | |
78 | else | |
79 | printf ("script1.sh kill by signal %d\n", | |
80 | WTERMSIG (status)); | |
81 | return 1; | |
82 | } | |
83 | } | |
84 | ||
85 | argv[0] = (char *) "script2.sh"; | |
86 | argv[1] = (char *) "2"; | |
87 | for (i = 0; i < 5; i++) | |
88 | { | |
89 | pid_t pid = vfork (); | |
90 | if (pid < 0) | |
91 | { | |
92 | printf ("vfork failed: %m\n"); | |
93 | return 1; | |
94 | } | |
95 | else if (pid == 0) | |
96 | { | |
97 | execvp ("script2.sh", argv); | |
98 | _exit (errno); | |
99 | } | |
100 | int status; | |
101 | if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) | |
102 | { | |
103 | puts ("waitpid failed"); | |
104 | return 1; | |
105 | } | |
106 | else if (status != 0) | |
107 | { | |
108 | printf ("script2.sh failed with status %d\n", status); | |
109 | return 1; | |
110 | } | |
111 | } | |
112 | ||
113 | for (i = 0; i < 5; i++) | |
114 | { | |
115 | pid_t pid = vfork (); | |
116 | if (pid < 0) | |
117 | { | |
118 | printf ("vfork failed: %m\n"); | |
119 | return 1; | |
120 | } | |
121 | else if (pid == 0) | |
122 | { | |
123 | execlp ("script2.sh", "script2.sh", "3", NULL); | |
124 | _exit (errno); | |
125 | } | |
126 | int status; | |
127 | if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) | |
128 | { | |
129 | puts ("waitpid failed"); | |
130 | return 1; | |
131 | } | |
132 | else if (status != 0) | |
133 | { | |
134 | printf ("script2.sh failed with status %d\n", status); | |
135 | return 1; | |
136 | } | |
137 | } | |
138 | ||
139 | unsetenv ("PATH"); | |
140 | argv[0] = (char *) "echo"; | |
141 | argv[1] = (char *) "script 4"; | |
142 | for (i = 0; i < 5; i++) | |
143 | { | |
144 | pid_t pid = vfork (); | |
145 | if (pid < 0) | |
146 | { | |
147 | printf ("vfork failed: %m\n"); | |
148 | return 1; | |
149 | } | |
150 | else if (pid == 0) | |
151 | { | |
152 | execvp ("echo", argv); | |
153 | _exit (errno); | |
154 | } | |
155 | int status; | |
156 | if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) | |
157 | { | |
158 | puts ("waitpid failed"); | |
159 | return 1; | |
160 | } | |
161 | else if (status != 0) | |
162 | { | |
163 | printf ("echo failed with status %d\n", status); | |
164 | return 1; | |
165 | } | |
166 | } | |
167 | ||
168 | return 0; | |
169 | } | |
170 | ||
171 | static void | |
172 | do_prepare (void) | |
173 | { | |
174 | size_t len = strlen (test_dir) + sizeof ("/tst-vfork3.XXXXXX"); | |
175 | tmpdirname = malloc (len); | |
176 | char *script1 = malloc (len + sizeof "/script1.sh"); | |
177 | char *script2 = malloc (len + sizeof "/script2.sh"); | |
178 | if (tmpdirname == NULL || script1 == NULL || script2 == NULL) | |
179 | { | |
180 | puts ("out of memory"); | |
181 | exit (1); | |
182 | } | |
183 | strcpy (stpcpy (tmpdirname, test_dir), "/tst-vfork3.XXXXXX"); | |
184 | ||
185 | tmpdirname = mkdtemp (tmpdirname); | |
186 | if (tmpdirname == NULL) | |
187 | { | |
188 | puts ("could not create temporary directory"); | |
189 | exit (1); | |
190 | } | |
191 | ||
192 | strcpy (stpcpy (script1, tmpdirname), "/script1.sh"); | |
193 | strcpy (stpcpy (script2, tmpdirname), "/script2.sh"); | |
194 | ||
195 | /* Need to make sure tmpdirname is at the end of the linked list. */ | |
196 | add_temp_file (script1); | |
197 | add_temp_file (tmpdirname); | |
198 | add_temp_file (script2); | |
199 | ||
200 | const char content1[] = "#!/bin/sh\necho script $1\n"; | |
201 | int fd = open (script1, O_WRONLY | O_CREAT, 0700); | |
202 | if (fd < 0 | |
203 | || TEMP_FAILURE_RETRY (write (fd, content1, sizeof content1)) | |
204 | != sizeof content1 | |
205 | || fchmod (fd, S_IRUSR | S_IXUSR) < 0) | |
206 | { | |
207 | printf ("Could not write %s\n", script1); | |
208 | exit (1); | |
209 | } | |
210 | close (fd); | |
211 | ||
212 | const char content2[] = "echo script $1\n"; | |
213 | fd = open (script2, O_WRONLY | O_CREAT, 0700); | |
214 | if (fd < 0 | |
215 | || TEMP_FAILURE_RETRY (write (fd, content2, sizeof content2)) | |
216 | != sizeof content2 | |
217 | || fchmod (fd, S_IRUSR | S_IXUSR) < 0) | |
218 | { | |
219 | printf ("Could not write %s\n", script2); | |
220 | exit (1); | |
221 | } | |
222 | close (fd); | |
223 | } |