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