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 * $FreeBSD: head/tools/regression/lib/libc/gen/test-wordexp.c 286941 2015-08-19 20:31:03Z jilles $
27 */
28
29 /*
30 * Test program for wordexp() and wordfree() as specified by
31 * IEEE Std. 1003.1-2001.
32 */
33
34 #include <sys/wait.h>
35
36 #include <assert.h>
37 #include <errno.h>
38 #include <signal.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <wordexp.h>
43
44 static void
chld_handler(int x)45 chld_handler(int x)
46 {
47 int status, serrno;
48
49 (void)x;
50 serrno = errno;
51 while (waitpid(-1, &status, WNOHANG) > 0)
52 ;
53 errno = serrno;
54 }
55
56 int
main(int argc,char * argv[])57 main(int argc, char *argv[])
58 {
59 struct sigaction sa;
60 wordexp_t we;
61 int r;
62 int i;
63 char longdata[6 * 10000 + 1];
64
65 /* Test that the macros are there. */
66 (void)(WRDE_APPEND + WRDE_DOOFFS + WRDE_NOCMD + WRDE_REUSE +
67 WRDE_SHOWERR + WRDE_UNDEF);
68 (void)(WRDE_BADCHAR + WRDE_BADVAL + WRDE_CMDSUB + WRDE_NOSPACE +
69 WRDE_SYNTAX);
70
71 /* Simple test. */
72 r = wordexp("hello world", &we, 0);
73 assert(r == 0);
74 assert(we.we_wordc == 2);
75 assert(strcmp(we.we_wordv[0], "hello") == 0);
76 assert(strcmp(we.we_wordv[1], "world") == 0);
77 assert(we.we_wordv[2] == NULL);
78 wordfree(&we);
79
80 /* Long output. */
81 for (i = 0; i < 10000; i++)
82 snprintf(longdata + 6 * i, 7, "%05d ", i);
83 r = wordexp(longdata, &we, 0);
84 assert(r == 0);
85 assert(we.we_wordc == 10000);
86 assert(we.we_wordv[10000] == NULL);
87 wordfree(&we);
88
89 /* WRDE_DOOFFS */
90 we.we_offs = 3;
91 r = wordexp("hello world", &we, WRDE_DOOFFS);
92 assert(r == 0);
93 assert(we.we_wordc == 2);
94 assert(we.we_wordv[0] == NULL);
95 assert(we.we_wordv[1] == NULL);
96 assert(we.we_wordv[2] == NULL);
97 assert(strcmp(we.we_wordv[3], "hello") == 0);
98 assert(strcmp(we.we_wordv[4], "world") == 0);
99 assert(we.we_wordv[5] == NULL);
100 wordfree(&we);
101
102 /* WRDE_REUSE */
103 r = wordexp("hello world", &we, 0);
104 r = wordexp("hello world", &we, WRDE_REUSE);
105 assert(r == 0);
106 assert(we.we_wordc == 2);
107 assert(strcmp(we.we_wordv[0], "hello") == 0);
108 assert(strcmp(we.we_wordv[1], "world") == 0);
109 assert(we.we_wordv[2] == NULL);
110 wordfree(&we);
111
112 /* WRDE_APPEND */
113 r = wordexp("this is", &we, 0);
114 assert(r == 0);
115 r = wordexp("a test", &we, WRDE_APPEND);
116 assert(r == 0);
117 assert(we.we_wordc == 4);
118 assert(strcmp(we.we_wordv[0], "this") == 0);
119 assert(strcmp(we.we_wordv[1], "is") == 0);
120 assert(strcmp(we.we_wordv[2], "a") == 0);
121 assert(strcmp(we.we_wordv[3], "test") == 0);
122 assert(we.we_wordv[4] == NULL);
123 wordfree(&we);
124
125 /* WRDE_DOOFFS + WRDE_APPEND */
126 we.we_offs = 2;
127 r = wordexp("this is", &we, WRDE_DOOFFS);
128 assert(r == 0);
129 r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFFS);
130 assert(r == 0);
131 r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFFS);
132 assert(r == 0);
133 assert(we.we_wordc == 6);
134 assert(we.we_wordv[0] == NULL);
135 assert(we.we_wordv[1] == NULL);
136 assert(strcmp(we.we_wordv[2], "this") == 0);
137 assert(strcmp(we.we_wordv[3], "is") == 0);
138 assert(strcmp(we.we_wordv[4], "a") == 0);
139 assert(strcmp(we.we_wordv[5], "test") == 0);
140 assert(strcmp(we.we_wordv[6], "of") == 0);
141 assert(strcmp(we.we_wordv[7], "wordexp") == 0);
142 assert(we.we_wordv[8] == NULL);
143 wordfree(&we);
144
145 /* WRDE_UNDEF */
146 r = wordexp("${dont_set_me}", &we, WRDE_UNDEF);
147 assert(r == WRDE_BADVAL);
148
149 /* WRDE_NOCMD */
150 r = wordexp("`date`", &we, WRDE_NOCMD);
151 assert(r == WRDE_CMDSUB);
152 r = wordexp("\"`date`\"", &we, WRDE_NOCMD);
153 assert(r == WRDE_CMDSUB);
154 r = wordexp("$(date)", &we, WRDE_NOCMD);
155 assert(r == WRDE_CMDSUB);
156 r = wordexp("\"$(date)\"", &we, WRDE_NOCMD);
157 assert(r == WRDE_CMDSUB);
158 r = wordexp("$((3+5))", &we, WRDE_NOCMD);
159 assert(r == 0);
160 r = wordexp("\\$\\(date\\)", &we, WRDE_NOCMD|WRDE_REUSE);
161 assert(r == 0);
162 r = wordexp("'`date`'", &we, WRDE_NOCMD|WRDE_REUSE);
163 assert(r == 0);
164 r = wordexp("'$(date)'", &we, WRDE_NOCMD|WRDE_REUSE);
165 assert(r == 0);
166 wordfree(&we);
167
168 /* WRDE_BADCHAR */
169 r = wordexp("'\n|&;<>(){}'", &we, 0);
170 assert(r == 0);
171 r = wordexp("\"\n|&;<>(){}\"", &we, WRDE_REUSE);
172 assert(r == 0);
173 r = wordexp("\\\n\\|\\&\\;\\<\\>\\(\\)\\{\\}", &we, WRDE_REUSE);
174 assert(r == 0);
175 wordfree(&we);
176 r = wordexp("test \n test", &we, 0);
177 assert(r == WRDE_BADCHAR);
178 r = wordexp("test | test", &we, 0);
179 assert(r == WRDE_BADCHAR);
180 r = wordexp("test & test", &we, 0);
181 assert(r == WRDE_BADCHAR);
182 r = wordexp("test ; test", &we, 0);
183 assert(r == WRDE_BADCHAR);
184 r = wordexp("test > test", &we, 0);
185 assert(r == WRDE_BADCHAR);
186 r = wordexp("test < test", &we, 0);
187 assert(r == WRDE_BADCHAR);
188 r = wordexp("test ( test", &we, 0);
189 assert(r == WRDE_BADCHAR);
190 r = wordexp("test ) test", &we, 0);
191 assert(r == WRDE_BADCHAR);
192 r = wordexp("test { test", &we, 0);
193 assert(r == WRDE_BADCHAR);
194 r = wordexp("test } test", &we, 0);
195 assert(r == WRDE_BADCHAR);
196
197 /* WRDE_SYNTAX */
198 r = wordexp("'", &we, 0);
199 assert(r == WRDE_SYNTAX);
200 r = wordexp("'", &we, WRDE_UNDEF);
201 assert(r == WRDE_SYNTAX);
202 r = wordexp("'\\'", &we, 0);
203 assert(r == 0);
204 assert(we.we_wordc == 1);
205 assert(strcmp(we.we_wordv[0], "\\") == 0);
206 assert(we.we_wordv[1] == NULL);
207 wordfree(&we);
208 /* Two syntax errors that are not detected by the current we_check(). */
209 r = wordexp("${IFS:+'}", &we, 0);
210 assert(r == WRDE_SYNTAX);
211 r = wordexp("${IFS:+'}", &we, WRDE_UNDEF);
212 assert(r == WRDE_SYNTAX);
213 r = wordexp("$(case)", &we, 0);
214 assert(r == WRDE_SYNTAX);
215 r = wordexp("$(case)", &we, WRDE_UNDEF);
216 assert(r == WRDE_SYNTAX);
217
218 /* With a SIGCHLD handler that reaps all zombies. */
219 sa.sa_flags = 0;
220 sigemptyset(&sa.sa_mask);
221 sa.sa_handler = chld_handler;
222 r = sigaction(SIGCHLD, &sa, NULL);
223 assert(r == 0);
224 r = wordexp("hello world", &we, 0);
225 assert(r == 0);
226 assert(we.we_wordc == 2);
227 assert(strcmp(we.we_wordv[0], "hello") == 0);
228 assert(strcmp(we.we_wordv[1], "world") == 0);
229 assert(we.we_wordv[2] == NULL);
230 wordfree(&we);
231 sa.sa_handler = SIG_DFL;
232 r = sigaction(SIGCHLD, &sa, NULL);
233 assert(r == 0);
234
235 /*
236 * With IFS set to a non-default value (without depending on whether
237 * IFS is inherited or not).
238 */
239 r = setenv("IFS", ":", 1);
240 assert(r == 0);
241 r = wordexp("hello world", &we, 0);
242 assert(r == 0);
243 assert(we.we_wordc == 2);
244 assert(strcmp(we.we_wordv[0], "hello") == 0);
245 assert(strcmp(we.we_wordv[1], "world") == 0);
246 assert(we.we_wordv[2] == NULL);
247 wordfree(&we);
248 r = unsetenv("IFS");
249 assert(r == 0);
250
251 /*
252 * With IFS set to a non-default value, and using it.
253 */
254 r = setenv("IFS", ":", 1);
255 assert(r == 0);
256 r = wordexp("${IFS+hello:world}", &we, 0);
257 assert(r == 0);
258 assert(we.we_wordc == 2);
259 assert(strcmp(we.we_wordv[0], "hello") == 0);
260 assert(strcmp(we.we_wordv[1], "world") == 0);
261 assert(we.we_wordv[2] == NULL);
262 wordfree(&we);
263 r = unsetenv("IFS");
264 assert(r == 0);
265
266 printf("PASS wordexp()\n");
267 printf("PASS wordfree()\n");
268
269 return (0);
270 }
271