1 /* General tests for execpve.
2 Copyright (C) 2016-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <wait.h>
25
26
27 /* Nonzero if the program gets called via `exec'. */
28 static int restart;
29
30
31 #define CMDLINE_OPTIONS \
32 { "restart", no_argument, &restart, 1 },
33
34 /* Prototype for our test function. */
35 extern void do_prepare (int argc, char *argv[]);
36 extern int do_test (int argc, char *argv[]);
37
38 #include "../test-skeleton.c"
39
40 #define EXECVPE_KEY "EXECVPE_ENV"
41 #define EXECVPE_VALUE "execvpe_test"
42
43
44 static int
handle_restart(void)45 handle_restart (void)
46 {
47 /* First check if only one variable is passed on execvpe. */
48 int env_count = 0;
49 for (char **e = environ; *e != NULL; ++e)
50 if (++env_count == INT_MAX)
51 {
52 printf ("Environment variable number overflow");
53 exit (EXIT_FAILURE);
54 }
55 if (env_count != 1)
56 {
57 printf ("Wrong number of environment variables");
58 exit (EXIT_FAILURE);
59 }
60
61 /* Check if the combinarion os "EXECVPE_ENV=execvpe_test" */
62 const char *env = getenv (EXECVPE_KEY);
63 if (env == NULL)
64 {
65 printf ("Test environment variable not found");
66 exit (EXIT_FAILURE);
67 }
68
69 if (strncmp (env, EXECVPE_VALUE, sizeof (EXECVPE_VALUE)))
70 {
71 printf ("Test environment variable with wrong value");
72 exit (EXIT_FAILURE);
73 }
74
75 return 0;
76 }
77
78
79 int
do_test(int argc,char * argv[])80 do_test (int argc, char *argv[])
81 {
82 pid_t pid;
83 int status;
84
85 /* We must have
86 - one or four parameters left if called initially
87 + path for ld.so optional
88 + "--library-path" optional
89 + the library path optional
90 + the application name
91
92 if --enable-hardcoded-path-in-tests is used, just
93 + the application name
94 */
95
96 if (restart)
97 {
98 if (argc != 1)
99 {
100 printf ("Wrong number of arguments (%d) in restart\n", argc);
101 exit (EXIT_FAILURE);
102 }
103
104 return handle_restart ();
105 }
106
107 if (argc != 2 && argc != 5)
108 {
109 printf ("Wrong number of arguments (%d)\n", argc);
110 exit (EXIT_FAILURE);
111 }
112
113 /* We want to test the `execvpe' function. To do this we restart the
114 program with an additional parameter. */
115 pid = fork ();
116 if (pid == 0)
117 {
118 /* This is the child. Construct the command line. */
119
120 /* We cast here to char* because the test itself does not modify neither
121 the argument nor the environment list. */
122 char *envs[] = { (char*)(EXECVPE_KEY "=" EXECVPE_VALUE), NULL };
123 if (argc == 5)
124 {
125 char *args[] = { argv[1], argv[2], argv[3], argv[4],
126 (char *) "--direct", (char *) "--restart", NULL };
127 execvpe (args[0], args, envs);
128 }
129 else
130 {
131 char *args[] = { argv[0],
132 (char *) "--direct", (char *) "--restart", NULL };
133 execvpe (args[0], args, envs);
134 }
135
136 puts ("Cannot exec");
137 exit (EXIT_FAILURE);
138 }
139 else if (pid == (pid_t) -1)
140 {
141 puts ("Cannot fork");
142 return 1;
143 }
144
145 /* Wait for the child. */
146 if (waitpid (pid, &status, 0) != pid)
147 {
148 puts ("Wrong child");
149 return 1;
150 }
151
152 if (WTERMSIG (status) != 0)
153 {
154 puts ("Child terminated incorrectly");
155 return 1;
156 }
157 status = WEXITSTATUS (status);
158
159 return status;
160 }
161