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