]> git.ipfire.org Git - thirdparty/glibc.git/blob - posix/tst-vfork3.c
8335594bed778eaf0efa420eb25aaa6635dc4124
[thirdparty/glibc.git] / posix / tst-vfork3.c
1 /* Test for vfork functions.
2 Copyright (C) 2007-2019 Free Software Foundation, Inc.
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
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
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/stat.h>
27 #include <sys/wait.h>
28
29 static int do_test (void);
30 static void do_prepare (void);
31 char *tmpdirname;
32
33 #define TEST_FUNCTION do_test ()
34 #define PREPARE(argc, argv) do_prepare ()
35 #include "../test-skeleton.c"
36
37 static void
38 run_script (const char *script, char *const argv[])
39 {
40 for (size_t i = 0; i < 5; i++)
41 {
42 pid_t pid = vfork ();
43 if (pid < 0)
44 FAIL_EXIT1 ("vfork failed: %m");
45 else if (pid == 0)
46 {
47 execvp (script, argv);
48 _exit (errno);
49 }
50
51 int status;
52 if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
53 FAIL_EXIT1 ("waitpid failed");
54 else if (status != 0)
55 {
56 if (WIFEXITED (status))
57 FAIL_EXIT1 ("%s failed with status %d\n", script,
58 WEXITSTATUS (status));
59 else
60 FAIL_EXIT1 ("%s killed by signal %d\n", script,
61 WTERMSIG (status));
62 }
63 }
64 }
65
66 static int
67 do_test (void)
68 {
69 mtrace ();
70
71 const char *path = getenv ("PATH");
72 if (path == NULL)
73 path = "/bin";
74 char pathbuf[strlen (tmpdirname) + 1 + strlen (path) + 1];
75 strcpy (stpcpy (stpcpy (pathbuf, tmpdirname), ":"), path);
76 if (setenv ("PATH", pathbuf, 1) < 0)
77 {
78 puts ("setenv failed");
79 return 1;
80 }
81
82 /* Although manual states first argument should be the script name itself,
83 current execv{p,e} implementation allows it. */
84 char *argv00[] = { NULL };
85 run_script ("script0.sh", argv00);
86
87 char *argv01[] = { (char*) "script0.sh", NULL };
88 run_script ("script0.sh", argv01);
89
90 char *argv1[] = { (char *) "script1.sh", (char *) "1", NULL };
91 run_script ("script1.sh", argv1);
92
93 char *argv2[] = { (char *) "script2.sh", (char *) "2", NULL };
94 run_script ("script2.sh", argv2);
95
96 /* Same as before but with execlp. */
97 for (size_t i = 0; i < 5; i++)
98 {
99 pid_t pid = vfork ();
100 if (pid < 0)
101 {
102 printf ("vfork failed: %m\n");
103 return 1;
104 }
105 else if (pid == 0)
106 {
107 execlp ("script2.sh", "script2.sh", "3", NULL);
108 _exit (errno);
109 }
110 int status;
111 if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
112 {
113 puts ("waitpid failed");
114 return 1;
115 }
116 else if (status != 0)
117 {
118 printf ("script2.sh failed with status %d\n", status);
119 return 1;
120 }
121 }
122
123 unsetenv ("PATH");
124 char *argv4[] = { (char *) "echo", (char *) "script 4", NULL };
125 run_script ("echo", argv4);
126
127 return 0;
128 }
129
130 static void
131 create_script (const char *script, const char *contents, size_t size)
132 {
133 int fd = open (script, O_WRONLY | O_CREAT, 0700);
134 if (fd < 0
135 || TEMP_FAILURE_RETRY (write (fd, contents, size)) != size
136 || fchmod (fd, S_IRUSR | S_IXUSR) < 0)
137 FAIL_EXIT1 ("could not write %s\n", script);
138 close (fd);
139 }
140
141 static void
142 do_prepare (void)
143 {
144 size_t len = strlen (test_dir) + sizeof ("/tst-vfork3.XXXXXX");
145 tmpdirname = malloc (len);
146 if (tmpdirname == NULL)
147 FAIL_EXIT1 ("out of memory");
148 strcpy (stpcpy (tmpdirname, test_dir), "/tst-vfork3.XXXXXX");
149
150 tmpdirname = mkdtemp (tmpdirname);
151 if (tmpdirname == NULL)
152 FAIL_EXIT1 ("could not create temporary directory");
153
154 char script0[len + sizeof "/script0.sh"];
155 char script1[len + sizeof "/script1.sh"];
156 char script2[len + sizeof "/script2.sh"];
157
158 strcpy (stpcpy (script0, tmpdirname), "/script0.sh");
159 strcpy (stpcpy (script1, tmpdirname), "/script1.sh");
160 strcpy (stpcpy (script2, tmpdirname), "/script2.sh");
161
162 add_temp_file (tmpdirname);
163 add_temp_file (script0);
164 add_temp_file (script1);
165 add_temp_file (script2);
166
167 const char content0[] = "#!/bin/sh\necho empty\n";
168 create_script (script0, content0, sizeof content0);
169
170 const char content1[] = "#!/bin/sh\necho script $1\n";
171 create_script (script1, content1, sizeof content1);
172
173 const char content2[] = "echo script $1\n";
174 create_script (script2, content2, sizeof content2);
175 }