1 /*-
2 * Copyright (c) 2003 Tim J. Robbins
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 wordexp() and wordfree() as specified by
29 * IEEE Std. 1003.1-2001.
30 */
31
32 #include <sys/cdefs.h>
33 #include <sys/wait.h>
34 #include <errno.h>
35 #include <signal.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <wordexp.h>
40
41 #include <atf-c.h>
42
43 static void
chld_handler(int x)44 chld_handler(int x)
45 {
46 int status, serrno;
47
48 (void)x;
49 serrno = errno;
50 while (waitpid(-1, &status, WNOHANG) > 0)
51 ;
52 errno = serrno;
53 }
54
55 ATF_TC_WITHOUT_HEAD(simple_test);
ATF_TC_BODY(simple_test,tc)56 ATF_TC_BODY(simple_test, tc)
57 {
58 wordexp_t we;
59 int r;
60
61 /* Test that the macros are there. */
62 (void)(WRDE_APPEND + WRDE_DOOFFS + WRDE_NOCMD + WRDE_REUSE +
63 WRDE_SHOWERR + WRDE_UNDEF);
64 (void)(WRDE_BADCHAR + WRDE_BADVAL + WRDE_CMDSUB + WRDE_NOSPACE +
65 WRDE_SYNTAX);
66
67 /* Simple test. */
68 r = wordexp("hello world", &we, 0);
69 ATF_REQUIRE(r == 0);
70 ATF_REQUIRE(we.we_wordc == 2);
71 ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
72 ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
73 ATF_REQUIRE(we.we_wordv[2] == NULL);
74 wordfree(&we);
75 }
76
77 ATF_TC_WITHOUT_HEAD(long_output_test);
ATF_TC_BODY(long_output_test,tc)78 ATF_TC_BODY(long_output_test, tc)
79 {
80 char longdata[6 * 10000 + 1];
81 wordexp_t we;
82 int i, r;
83
84 /* Long output. */
85 for (i = 0; i < 10000; i++)
86 snprintf(longdata + 6 * i, 7, "%05d ", i);
87 r = wordexp(longdata, &we, 0);
88 ATF_REQUIRE(r == 0);
89 ATF_REQUIRE(we.we_wordc == 10000);
90 ATF_REQUIRE(we.we_wordv[10000] == NULL);
91 wordfree(&we);
92 }
93
94 ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS_test);
ATF_TC_BODY(WRDE_DOOFFS_test,tc)95 ATF_TC_BODY(WRDE_DOOFFS_test, tc)
96 {
97 wordexp_t we;
98 int r;
99
100 we.we_offs = 3;
101 r = wordexp("hello world", &we, WRDE_DOOFFS);
102 ATF_REQUIRE(r == 0);
103 ATF_REQUIRE(we.we_wordc == 2);
104 ATF_REQUIRE(we.we_wordv[0] == NULL);
105 ATF_REQUIRE(we.we_wordv[1] == NULL);
106 ATF_REQUIRE(we.we_wordv[2] == NULL);
107 ATF_REQUIRE(strcmp(we.we_wordv[3], "hello") == 0);
108 ATF_REQUIRE(strcmp(we.we_wordv[4], "world") == 0);
109 ATF_REQUIRE(we.we_wordv[5] == NULL);
110 wordfree(&we);
111 }
112
113 ATF_TC_WITHOUT_HEAD(WRDE_REUSE_test);
ATF_TC_BODY(WRDE_REUSE_test,tc)114 ATF_TC_BODY(WRDE_REUSE_test, tc)
115 {
116 wordexp_t we;
117 int r;
118
119 r = wordexp("hello world", &we, 0);
120 r = wordexp("hello world", &we, WRDE_REUSE);
121 ATF_REQUIRE(r == 0);
122 ATF_REQUIRE(we.we_wordc == 2);
123 ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
124 ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
125 ATF_REQUIRE(we.we_wordv[2] == NULL);
126 wordfree(&we);
127 }
128
129 ATF_TC_WITHOUT_HEAD(WRDE_APPEND_test);
ATF_TC_BODY(WRDE_APPEND_test,tc)130 ATF_TC_BODY(WRDE_APPEND_test, tc)
131 {
132 wordexp_t we;
133 int r;
134
135 r = wordexp("this is", &we, 0);
136 ATF_REQUIRE(r == 0);
137 r = wordexp("a test", &we, WRDE_APPEND);
138 ATF_REQUIRE(r == 0);
139 ATF_REQUIRE(we.we_wordc == 4);
140 ATF_REQUIRE(strcmp(we.we_wordv[0], "this") == 0);
141 ATF_REQUIRE(strcmp(we.we_wordv[1], "is") == 0);
142 ATF_REQUIRE(strcmp(we.we_wordv[2], "a") == 0);
143 ATF_REQUIRE(strcmp(we.we_wordv[3], "test") == 0);
144 ATF_REQUIRE(we.we_wordv[4] == NULL);
145 wordfree(&we);
146 }
147
148 ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS__WRDE_APPEND_test);
ATF_TC_BODY(WRDE_DOOFFS__WRDE_APPEND_test,tc)149 ATF_TC_BODY(WRDE_DOOFFS__WRDE_APPEND_test, tc)
150 {
151 wordexp_t we;
152 int r;
153
154 we.we_offs = 2;
155 r = wordexp("this is", &we, WRDE_DOOFFS);
156 ATF_REQUIRE(r == 0);
157 r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFFS);
158 ATF_REQUIRE(r == 0);
159 r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFFS);
160 ATF_REQUIRE(r == 0);
161 ATF_REQUIRE(we.we_wordc == 6);
162 ATF_REQUIRE(we.we_wordv[0] == NULL);
163 ATF_REQUIRE(we.we_wordv[1] == NULL);
164 ATF_REQUIRE(strcmp(we.we_wordv[2], "this") == 0);
165 ATF_REQUIRE(strcmp(we.we_wordv[3], "is") == 0);
166 ATF_REQUIRE(strcmp(we.we_wordv[4], "a") == 0);
167 ATF_REQUIRE(strcmp(we.we_wordv[5], "test") == 0);
168 ATF_REQUIRE(strcmp(we.we_wordv[6], "of") == 0);
169 ATF_REQUIRE(strcmp(we.we_wordv[7], "wordexp") == 0);
170 ATF_REQUIRE(we.we_wordv[8] == NULL);
171 wordfree(&we);
172 }
173
174 ATF_TC_WITHOUT_HEAD(WRDE_UNDEF_test);
ATF_TC_BODY(WRDE_UNDEF_test,tc)175 ATF_TC_BODY(WRDE_UNDEF_test, tc)
176 {
177 wordexp_t we;
178 int r;
179
180 r = wordexp("${dont_set_me}", &we, WRDE_UNDEF);
181 ATF_REQUIRE(r == WRDE_BADVAL);
182 }
183
184 ATF_TC_WITHOUT_HEAD(WRDE_NOCMD_test);
ATF_TC_BODY(WRDE_NOCMD_test,tc)185 ATF_TC_BODY(WRDE_NOCMD_test, tc)
186 {
187 wordexp_t we;
188 int r;
189
190 r = wordexp("`date`", &we, WRDE_NOCMD);
191 ATF_REQUIRE(r == WRDE_CMDSUB);
192 r = wordexp("\"`date`\"", &we, WRDE_NOCMD);
193 ATF_REQUIRE(r == WRDE_CMDSUB);
194 r = wordexp("$(date)", &we, WRDE_NOCMD);
195 ATF_REQUIRE(r == WRDE_CMDSUB);
196 r = wordexp("\"$(date)\"", &we, WRDE_NOCMD);
197 ATF_REQUIRE(r == WRDE_CMDSUB);
198 r = wordexp("$((3+5))", &we, WRDE_NOCMD);
199 ATF_REQUIRE(r == 0);
200 r = wordexp("\\$\\(date\\)", &we, WRDE_NOCMD|WRDE_REUSE);
201 ATF_REQUIRE(r == 0);
202 r = wordexp("'`date`'", &we, WRDE_NOCMD|WRDE_REUSE);
203 ATF_REQUIRE(r == 0);
204 r = wordexp("'$(date)'", &we, WRDE_NOCMD|WRDE_REUSE);
205 ATF_REQUIRE(r == 0);
206 wordfree(&we);
207 }
208
209 ATF_TC_WITHOUT_HEAD(WRDE_BADCHAR_test);
ATF_TC_BODY(WRDE_BADCHAR_test,tc)210 ATF_TC_BODY(WRDE_BADCHAR_test, tc)
211 {
212 wordexp_t we;
213 int r;
214
215 r = wordexp("'\n|&;<>(){}'", &we, 0);
216 ATF_REQUIRE(r == 0);
217 r = wordexp("\"\n|&;<>(){}\"", &we, WRDE_REUSE);
218 ATF_REQUIRE(r == 0);
219 r = wordexp("\\\n\\|\\&\\;\\<\\>\\(\\)\\{\\}", &we, WRDE_REUSE);
220 ATF_REQUIRE(r == 0);
221 wordfree(&we);
222 r = wordexp("test \n test", &we, 0);
223 ATF_REQUIRE(r == WRDE_BADCHAR);
224 r = wordexp("test | test", &we, 0);
225 ATF_REQUIRE(r == WRDE_BADCHAR);
226 r = wordexp("test & test", &we, 0);
227 ATF_REQUIRE(r == WRDE_BADCHAR);
228 r = wordexp("test ; test", &we, 0);
229 ATF_REQUIRE(r == WRDE_BADCHAR);
230 r = wordexp("test > test", &we, 0);
231 ATF_REQUIRE(r == WRDE_BADCHAR);
232 r = wordexp("test < test", &we, 0);
233 ATF_REQUIRE(r == WRDE_BADCHAR);
234 r = wordexp("test ( test", &we, 0);
235 ATF_REQUIRE(r == WRDE_BADCHAR);
236 r = wordexp("test ) test", &we, 0);
237 ATF_REQUIRE(r == WRDE_BADCHAR);
238 r = wordexp("test { test", &we, 0);
239 ATF_REQUIRE(r == WRDE_BADCHAR);
240 r = wordexp("test } test", &we, 0);
241 ATF_REQUIRE(r == WRDE_BADCHAR);
242 }
243
244 ATF_TC_WITHOUT_HEAD(WRDE_SYNTAX_test);
ATF_TC_BODY(WRDE_SYNTAX_test,tc)245 ATF_TC_BODY(WRDE_SYNTAX_test, tc)
246 {
247 wordexp_t we;
248 int r;
249
250 r = wordexp("'", &we, 0);
251 ATF_REQUIRE(r == WRDE_SYNTAX);
252 r = wordexp("'", &we, WRDE_UNDEF);
253 ATF_REQUIRE(r == WRDE_SYNTAX);
254 r = wordexp("'\\'", &we, 0);
255 ATF_REQUIRE(r == 0);
256 ATF_REQUIRE(we.we_wordc == 1);
257 ATF_REQUIRE(strcmp(we.we_wordv[0], "\\") == 0);
258 ATF_REQUIRE(we.we_wordv[1] == NULL);
259 wordfree(&we);
260 /* Two syntax errors that are not detected by the current we_check(). */
261 r = wordexp("${IFS:+'}", &we, 0);
262 ATF_REQUIRE(r == WRDE_SYNTAX);
263 r = wordexp("${IFS:+'}", &we, WRDE_UNDEF);
264 ATF_REQUIRE(r == WRDE_SYNTAX);
265 r = wordexp("$(case)", &we, 0);
266 ATF_REQUIRE(r == WRDE_SYNTAX);
267 r = wordexp("$(case)", &we, WRDE_UNDEF);
268 ATF_REQUIRE(r == WRDE_SYNTAX);
269 }
270
271 ATF_TC_WITHOUT_HEAD(with_SIGCHILD_handler_test);
ATF_TC_BODY(with_SIGCHILD_handler_test,tc)272 ATF_TC_BODY(with_SIGCHILD_handler_test, tc)
273 {
274 struct sigaction sa;
275 wordexp_t we;
276 int r;
277
278 /* With a SIGCHLD handler that reaps all zombies. */
279 sa.sa_flags = 0;
280 sigemptyset(&sa.sa_mask);
281 sa.sa_handler = chld_handler;
282 r = sigaction(SIGCHLD, &sa, NULL);
283 ATF_REQUIRE(r == 0);
284 r = wordexp("hello world", &we, 0);
285 ATF_REQUIRE(r == 0);
286 ATF_REQUIRE(we.we_wordc == 2);
287 ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
288 ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
289 ATF_REQUIRE(we.we_wordv[2] == NULL);
290 wordfree(&we);
291 sa.sa_handler = SIG_DFL;
292 r = sigaction(SIGCHLD, &sa, NULL);
293 ATF_REQUIRE(r == 0);
294 }
295
296 ATF_TC_WITHOUT_HEAD(with_unused_non_default_IFS_test);
ATF_TC_BODY(with_unused_non_default_IFS_test,tc)297 ATF_TC_BODY(with_unused_non_default_IFS_test, tc)
298 {
299 wordexp_t we;
300 int r;
301
302 /*
303 * With IFS set to a non-default value (without depending on whether
304 * IFS is inherited or not).
305 */
306 r = setenv("IFS", ":", 1);
307 ATF_REQUIRE(r == 0);
308 r = wordexp("hello world", &we, 0);
309 ATF_REQUIRE(r == 0);
310 ATF_REQUIRE(we.we_wordc == 2);
311 ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
312 ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
313 ATF_REQUIRE(we.we_wordv[2] == NULL);
314 wordfree(&we);
315 r = unsetenv("IFS");
316 ATF_REQUIRE(r == 0);
317 }
318
319 ATF_TC_WITHOUT_HEAD(with_used_non_default_IFS_test);
ATF_TC_BODY(with_used_non_default_IFS_test,tc)320 ATF_TC_BODY(with_used_non_default_IFS_test, tc)
321 {
322 wordexp_t we;
323 int r;
324
325 /*
326 * With IFS set to a non-default value, and using it.
327 */
328 r = setenv("IFS", ":", 1);
329 ATF_REQUIRE(r == 0);
330 r = wordexp("${IFS+hello:world}", &we, 0);
331 ATF_REQUIRE(r == 0);
332 ATF_REQUIRE(we.we_wordc == 2);
333 ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
334 ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
335 ATF_REQUIRE(we.we_wordv[2] == NULL);
336 wordfree(&we);
337 r = unsetenv("IFS");
338 ATF_REQUIRE(r == 0);
339 }
340
ATF_TP_ADD_TCS(tp)341 ATF_TP_ADD_TCS(tp)
342 {
343 ATF_TP_ADD_TC(tp, simple_test);
344 ATF_TP_ADD_TC(tp, long_output_test);
345 ATF_TP_ADD_TC(tp, WRDE_DOOFFS_test);
346 ATF_TP_ADD_TC(tp, WRDE_REUSE_test);
347 ATF_TP_ADD_TC(tp, WRDE_APPEND_test);
348 ATF_TP_ADD_TC(tp, WRDE_DOOFFS__WRDE_APPEND_test);
349 ATF_TP_ADD_TC(tp, WRDE_UNDEF_test);
350 ATF_TP_ADD_TC(tp, WRDE_NOCMD_test);
351 ATF_TP_ADD_TC(tp, WRDE_BADCHAR_test);
352 ATF_TP_ADD_TC(tp, WRDE_SYNTAX_test);
353 ATF_TP_ADD_TC(tp, with_SIGCHILD_handler_test);
354 ATF_TP_ADD_TC(tp, with_unused_non_default_IFS_test);
355 ATF_TP_ADD_TC(tp, with_used_non_default_IFS_test);
356
357 return (atf_no_error());
358 }
359