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 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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 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