]> git.ipfire.org Git - thirdparty/glibc.git/blame - posix/tst-vfork3.c
glob: Silence warning about void pointer arithmetic
[thirdparty/glibc.git] / posix / tst-vfork3.c
CommitLineData
df859a0c 1/* Test for vfork functions.
bfff8b1b 2 Copyright (C) 2007-2017 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>
ceaa9889 26#include <sys/stat.h>
df859a0c
UD
27#include <sys/wait.h>
28
29static int do_test (void);
30static void do_prepare (void);
31char *tmpdirname;
32
33#define TEST_FUNCTION do_test ()
34#define PREPARE(argc, argv) do_prepare ()
35#include "../test-skeleton.c"
36
8047e7cf
AZ
37static void
38run_script (const char *script, char *const argv[])
df859a0c 39{
8047e7cf 40 for (size_t i = 0; i < 5; i++)
df859a0c
UD
41 {
42 pid_t pid = vfork ();
43 if (pid < 0)
8047e7cf 44 FAIL_EXIT1 ("vfork failed: %m");
df859a0c
UD
45 else if (pid == 0)
46 {
8047e7cf 47 execvp (script, argv);
df859a0c
UD
48 _exit (errno);
49 }
8047e7cf 50
df859a0c
UD
51 int status;
52 if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
8047e7cf 53 FAIL_EXIT1 ("waitpid failed");
df859a0c
UD
54 else if (status != 0)
55 {
56 if (WIFEXITED (status))
8047e7cf
AZ
57 FAIL_EXIT1 ("%s failed with status %d\n", script,
58 WEXITSTATUS (status));
df859a0c 59 else
8047e7cf
AZ
60 FAIL_EXIT1 ("%s killed by signal %d\n", script,
61 WTERMSIG (status));
df859a0c
UD
62 }
63 }
8047e7cf
AZ
64}
65
66static int
67do_test (void)
68{
69 mtrace ();
df859a0c 70
8047e7cf
AZ
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)
df859a0c 77 {
8047e7cf
AZ
78 puts ("setenv failed");
79 return 1;
df859a0c
UD
80 }
81
8047e7cf
AZ
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++)
df859a0c
UD
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");
8047e7cf
AZ
124 char *argv4[] = { (char *) "echo", (char *) "script 4", NULL };
125 run_script ("echo", argv4);
df859a0c
UD
126
127 return 0;
128}
129
8047e7cf
AZ
130static void
131create_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
df859a0c
UD
141static void
142do_prepare (void)
143{
144 size_t len = strlen (test_dir) + sizeof ("/tst-vfork3.XXXXXX");
145 tmpdirname = malloc (len);
8047e7cf
AZ
146 if (tmpdirname == NULL)
147 FAIL_EXIT1 ("out of memory");
df859a0c
UD
148 strcpy (stpcpy (tmpdirname, test_dir), "/tst-vfork3.XXXXXX");
149
150 tmpdirname = mkdtemp (tmpdirname);
151 if (tmpdirname == NULL)
8047e7cf
AZ
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"];
df859a0c 157
8047e7cf 158 strcpy (stpcpy (script0, tmpdirname), "/script0.sh");
df859a0c
UD
159 strcpy (stpcpy (script1, tmpdirname), "/script1.sh");
160 strcpy (stpcpy (script2, tmpdirname), "/script2.sh");
161
c22553ef 162 add_temp_file (tmpdirname);
8047e7cf 163 add_temp_file (script0);
df859a0c 164 add_temp_file (script1);
df859a0c 165 add_temp_file (script2);
8047e7cf
AZ
166
167 const char content0[] = "#!/bin/sh\necho empty\n";
168 create_script (script0, content0, sizeof content0);
df859a0c
UD
169
170 const char content1[] = "#!/bin/sh\necho script $1\n";
8047e7cf 171 create_script (script1, content1, sizeof content1);
df859a0c
UD
172
173 const char content2[] = "echo script $1\n";
8047e7cf 174 create_script (script2, content2, sizeof content2);
df859a0c 175}