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