1 1.1 christos /* Pexecute test program, 2 1.1.1.6 christos Copyright (C) 2005-2024 Free Software Foundation, Inc. 3 1.1 christos Written by Ian Lance Taylor <ian (at) airs.com>. 4 1.1 christos 5 1.1 christos This file is part of GNU libiberty. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 2 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program; if not, write to the Free Software 19 1.1 christos Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 1.1 christos */ 21 1.1 christos 22 1.1 christos #ifdef HAVE_CONFIG_H 23 1.1 christos #include "config.h" 24 1.1 christos #endif 25 1.1 christos #include "ansidecl.h" 26 1.1 christos #include "libiberty.h" 27 1.1 christos #include <stdio.h> 28 1.1 christos #include <signal.h> 29 1.1 christos #include <errno.h> 30 1.1 christos #ifdef HAVE_STRING_H 31 1.1 christos #include <string.h> 32 1.1 christos #endif 33 1.1 christos #include <sys/types.h> 34 1.1 christos #ifdef HAVE_STDLIB_H 35 1.1 christos #include <stdlib.h> 36 1.1 christos #endif 37 1.1 christos #ifdef HAVE_UNISTD_H 38 1.1 christos #include <unistd.h> 39 1.1 christos #endif 40 1.1 christos #ifdef HAVE_SYS_WAIT_H 41 1.1 christos #include <sys/wait.h> 42 1.1 christos #endif 43 1.1 christos #ifdef HAVE_SYS_TIME_H 44 1.1 christos #include <sys/time.h> 45 1.1 christos #endif 46 1.1 christos #ifdef HAVE_SYS_RESOURCE_H 47 1.1 christos #include <sys/resource.h> 48 1.1 christos #endif 49 1.1 christos 50 1.1 christos #ifndef WIFSIGNALED 51 1.1 christos #define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f) 52 1.1 christos #endif 53 1.1 christos #ifndef WTERMSIG 54 1.1 christos #define WTERMSIG(S) ((S) & 0x7f) 55 1.1 christos #endif 56 1.1 christos #ifndef WIFEXITED 57 1.1 christos #define WIFEXITED(S) (((S) & 0xff) == 0) 58 1.1 christos #endif 59 1.1 christos #ifndef WEXITSTATUS 60 1.1 christos #define WEXITSTATUS(S) (((S) & 0xff00) >> 8) 61 1.1 christos #endif 62 1.1 christos #ifndef WSTOPSIG 63 1.1 christos #define WSTOPSIG WEXITSTATUS 64 1.1 christos #endif 65 1.1 christos #ifndef WCOREDUMP 66 1.1 christos #define WCOREDUMP(S) ((S) & WCOREFLG) 67 1.1 christos #endif 68 1.1 christos #ifndef WCOREFLG 69 1.1 christos #define WCOREFLG 0200 70 1.1 christos #endif 71 1.1 christos 72 1.1 christos #ifndef EXIT_SUCCESS 73 1.1 christos #define EXIT_SUCCESS 0 74 1.1 christos #endif 75 1.1 christos 76 1.1 christos #ifndef EXIT_FAILURE 77 1.1 christos #define EXIT_FAILURE 1 78 1.1 christos #endif 79 1.1 christos 80 1.1 christos /* When this program is run with no arguments, it runs some tests of 81 1.1 christos the libiberty pexecute functions. As a test program, it simply 82 1.1 christos invokes itself with various arguments. 83 1.1 christos 84 1.1 christos argv[1]: 85 1.1 christos *empty string* Run tests, exit with success status 86 1.1 christos exit Exit success 87 1.1 christos error Exit error 88 1.1 christos abort Abort 89 1.1 christos echo Echo remaining arguments, exit success 90 1.1 christos echoerr Echo next arg to stdout, next to stderr, repeat 91 1.1 christos copy Copy stdin to stdout 92 1.1 christos write Write stdin to file named in next argument 93 1.1 christos */ 94 1.1 christos 95 1.1 christos static void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN; 96 1.1 christos static void error (int, const char *); 97 1.1 christos static void check_line (int, FILE *, const char *); 98 1.1 christos static void do_cmd (int, char **) ATTRIBUTE_NORETURN; 99 1.1 christos 100 1.1 christos /* The number of errors we have seen. */ 101 1.1 christos 102 1.1 christos static int error_count; 103 1.1 christos 104 1.1 christos /* Print a fatal error and exit. LINE is the line number where we 105 1.1 christos detected the error, ERRMSG is the error message to print, and ERR 106 1.1 christos is 0 or an errno value to print. */ 107 1.1 christos 108 1.1 christos static void 109 1.1 christos fatal_error (int line, const char *errmsg, int err) 110 1.1 christos { 111 1.1 christos fprintf (stderr, "test-pexecute:%d: %s", line, errmsg); 112 1.1 christos if (errno != 0) 113 1.1 christos fprintf (stderr, ": %s", xstrerror (err)); 114 1.1 christos fprintf (stderr, "\n"); 115 1.1 christos exit (EXIT_FAILURE); 116 1.1 christos } 117 1.1 christos 118 1.1 christos #define FATAL_ERROR(ERRMSG, ERR) fatal_error (__LINE__, ERRMSG, ERR) 119 1.1 christos 120 1.1 christos /* Print an error message and bump the error count. LINE is the line 121 1.1 christos number where we detected the error, ERRMSG is the error to 122 1.1 christos print. */ 123 1.1 christos 124 1.1 christos static void 125 1.1 christos error (int line, const char *errmsg) 126 1.1 christos { 127 1.1 christos fprintf (stderr, "test-pexecute:%d: %s\n", line, errmsg); 128 1.1 christos ++error_count; 129 1.1 christos } 130 1.1 christos 131 1.1 christos #define ERROR(ERRMSG) error (__LINE__, ERRMSG) 132 1.1 christos 133 1.1 christos /* Check a line in a file. */ 134 1.1 christos 135 1.1 christos static void 136 1.1 christos check_line (int line, FILE *e, const char *str) 137 1.1 christos { 138 1.1 christos const char *p; 139 1.1 christos int c; 140 1.1 christos char buf[1000]; 141 1.1 christos 142 1.1 christos p = str; 143 1.1 christos while (1) 144 1.1 christos { 145 1.1 christos c = getc (e); 146 1.1 christos 147 1.1 christos if (*p == '\0') 148 1.1 christos { 149 1.1 christos if (c != '\n') 150 1.1 christos { 151 1.1 christos snprintf (buf, sizeof buf, "got '%c' when expecting newline", c); 152 1.1 christos fatal_error (line, buf, 0); 153 1.1 christos } 154 1.1 christos c = getc (e); 155 1.1 christos if (c != EOF) 156 1.1 christos { 157 1.1 christos snprintf (buf, sizeof buf, "got '%c' when expecting EOF", c); 158 1.1 christos fatal_error (line, buf, 0); 159 1.1 christos } 160 1.1 christos return; 161 1.1 christos } 162 1.1 christos 163 1.1 christos if (c != *p) 164 1.1 christos { 165 1.1 christos snprintf (buf, sizeof buf, "expected '%c', got '%c'", *p, c); 166 1.1 christos fatal_error (line, buf, 0); 167 1.1 christos } 168 1.1 christos 169 1.1 christos ++p; 170 1.1 christos } 171 1.1 christos } 172 1.1 christos 173 1.1 christos #define CHECK_LINE(E, STR) check_line (__LINE__, E, STR) 174 1.1 christos 175 1.1 christos /* Main function for the pexecute tester. Run the tests. */ 176 1.1 christos 177 1.1 christos int 178 1.1 christos main (int argc, char **argv) 179 1.1 christos { 180 1.1 christos int trace; 181 1.1 christos struct pex_obj *test_pex_tmp; 182 1.1 christos int test_pex_status; 183 1.1 christos FILE *test_pex_file; 184 1.1 christos struct pex_obj *pex1; 185 1.1 christos char *subargv[10]; 186 1.1 christos int status; 187 1.1 christos FILE *e; 188 1.1 christos int statuses[10]; 189 1.1 christos 190 1.1 christos trace = 0; 191 1.1 christos if (argc > 1 && strcmp (argv[1], "-t") == 0) 192 1.1 christos { 193 1.1 christos trace = 1; 194 1.1 christos --argc; 195 1.1 christos ++argv; 196 1.1 christos } 197 1.1 christos 198 1.1 christos if (argc > 1) 199 1.1 christos do_cmd (argc, argv); 200 1.1 christos 201 1.1 christos #define TEST_PEX_INIT(FLAGS, TEMPBASE) \ 202 1.1 christos (((test_pex_tmp = pex_init (FLAGS, "test-pexecute", TEMPBASE)) \ 203 1.1 christos != NULL) \ 204 1.1 christos ? test_pex_tmp \ 205 1.1 christos : (FATAL_ERROR ("pex_init failed", 0), NULL)) 206 1.1 christos 207 1.1 christos #define TEST_PEX_RUN(PEXOBJ, FLAGS, EXECUTABLE, ARGV, OUTNAME, ERRNAME) \ 208 1.1 christos do \ 209 1.1 christos { \ 210 1.1 christos int err; \ 211 1.1 christos const char *pex_run_err; \ 212 1.1 christos if (trace) \ 213 1.1 christos fprintf (stderr, "Line %d: running %s %s\n", \ 214 1.1 christos __LINE__, EXECUTABLE, ARGV[0]); \ 215 1.1 christos pex_run_err = pex_run (PEXOBJ, FLAGS, EXECUTABLE, ARGV, OUTNAME, \ 216 1.1 christos ERRNAME, &err); \ 217 1.1 christos if (pex_run_err != NULL) \ 218 1.1 christos FATAL_ERROR (pex_run_err, err); \ 219 1.1 christos } \ 220 1.1 christos while (0) 221 1.1 christos 222 1.1 christos #define TEST_PEX_GET_STATUS_1(PEXOBJ) \ 223 1.1 christos (pex_get_status (PEXOBJ, 1, &test_pex_status) \ 224 1.1 christos ? test_pex_status \ 225 1.1 christos : (FATAL_ERROR ("pex_get_status failed", errno), 1)) 226 1.1 christos 227 1.1 christos #define TEST_PEX_GET_STATUS(PEXOBJ, COUNT, VECTOR) \ 228 1.1 christos do \ 229 1.1 christos { \ 230 1.1 christos if (!pex_get_status (PEXOBJ, COUNT, VECTOR)) \ 231 1.1 christos FATAL_ERROR ("pex_get_status failed", errno); \ 232 1.1 christos } \ 233 1.1 christos while (0) 234 1.1 christos 235 1.1 christos #define TEST_PEX_READ_OUTPUT(PEXOBJ) \ 236 1.1 christos ((test_pex_file = pex_read_output (PEXOBJ, 0)) != NULL \ 237 1.1 christos ? test_pex_file \ 238 1.1 christos : (FATAL_ERROR ("pex_read_output failed", errno), NULL)) 239 1.1 christos 240 1.1 christos remove ("temp.x"); 241 1.1 christos remove ("temp.y"); 242 1.1 christos 243 1.1 christos memset (subargv, 0, sizeof subargv); 244 1.1 christos 245 1.1 christos subargv[0] = "./test-pexecute"; 246 1.1 christos 247 1.1 christos pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL); 248 1.1 christos subargv[1] = "exit"; 249 1.1 christos subargv[2] = NULL; 250 1.1 christos TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, NULL); 251 1.1 christos status = TEST_PEX_GET_STATUS_1 (pex1); 252 1.1 christos if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) 253 1.1 christos ERROR ("exit failed"); 254 1.1 christos pex_free (pex1); 255 1.1 christos 256 1.1 christos pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL); 257 1.1 christos subargv[1] = "error"; 258 1.1 christos subargv[2] = NULL; 259 1.1 christos TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, NULL); 260 1.1 christos status = TEST_PEX_GET_STATUS_1 (pex1); 261 1.1 christos if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_FAILURE) 262 1.1 christos ERROR ("error test failed"); 263 1.1 christos pex_free (pex1); 264 1.1 christos 265 1.1 christos /* We redirect stderr to a file to avoid an error message which is 266 1.1 christos printed on mingw32 when the child calls abort. */ 267 1.1 christos pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL); 268 1.1 christos subargv[1] = "abort"; 269 1.1 christos subargv[2] = NULL; 270 1.1 christos TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, "temp.z"); 271 1.1 christos status = TEST_PEX_GET_STATUS_1 (pex1); 272 1.1 christos if (!WIFSIGNALED (status) || WTERMSIG (status) != SIGABRT) 273 1.1 christos ERROR ("abort failed"); 274 1.1 christos pex_free (pex1); 275 1.1 christos remove ("temp.z"); 276 1.1 christos 277 1.1 christos pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); 278 1.1 christos subargv[1] = "echo"; 279 1.1 christos subargv[2] = "foo"; 280 1.1 christos subargv[3] = NULL; 281 1.1 christos TEST_PEX_RUN (pex1, 0, "./test-pexecute", subargv, NULL, NULL); 282 1.1 christos e = TEST_PEX_READ_OUTPUT (pex1); 283 1.1 christos CHECK_LINE (e, "foo"); 284 1.1 christos if (TEST_PEX_GET_STATUS_1 (pex1) != 0) 285 1.1 christos ERROR ("echo exit status failed"); 286 1.1 christos pex_free (pex1); 287 1.1 christos 288 1.1.1.2 christos /* Check empty parameters don't get lost. */ 289 1.1.1.2 christos pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); 290 1.1.1.2 christos subargv[1] = "echo"; 291 1.1.1.2 christos subargv[2] = "foo"; 292 1.1.1.2 christos subargv[3] = ""; 293 1.1.1.2 christos subargv[4] = "bar"; 294 1.1.1.2 christos subargv[5] = NULL; 295 1.1.1.2 christos TEST_PEX_RUN (pex1, 0, "./test-pexecute", subargv, NULL, NULL); 296 1.1.1.2 christos e = TEST_PEX_READ_OUTPUT (pex1); 297 1.1.1.2 christos CHECK_LINE (e, "foo bar"); /* Two spaces! */ 298 1.1.1.2 christos if (TEST_PEX_GET_STATUS_1 (pex1) != 0) 299 1.1.1.2 christos ERROR ("echo exit status failed"); 300 1.1.1.2 christos pex_free (pex1); 301 1.1.1.2 christos 302 1.1 christos pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); 303 1.1 christos subargv[1] = "echo"; 304 1.1 christos subargv[2] = "bar"; 305 1.1 christos subargv[3] = NULL; 306 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL); 307 1.1 christos subargv[1] = "copy"; 308 1.1 christos subargv[2] = NULL; 309 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); 310 1.1 christos e = TEST_PEX_READ_OUTPUT (pex1); 311 1.1 christos CHECK_LINE (e, "bar"); 312 1.1 christos TEST_PEX_GET_STATUS (pex1, 2, statuses); 313 1.1 christos if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS 314 1.1 christos || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) 315 1.1 christos ERROR ("copy exit status failed"); 316 1.1 christos pex_free (pex1); 317 1.1 christos if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL) 318 1.1 christos ERROR ("temporary files exist"); 319 1.1 christos 320 1.1 christos pex1 = TEST_PEX_INIT (0, "temp"); 321 1.1 christos subargv[1] = "echo"; 322 1.1 christos subargv[2] = "bar"; 323 1.1 christos subargv[3] = NULL; 324 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL); 325 1.1 christos subargv[1] = "copy"; 326 1.1 christos subargv[2] = NULL; 327 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); 328 1.1 christos e = TEST_PEX_READ_OUTPUT (pex1); 329 1.1 christos CHECK_LINE (e, "bar"); 330 1.1 christos TEST_PEX_GET_STATUS (pex1, 2, statuses); 331 1.1 christos if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS 332 1.1 christos || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) 333 1.1 christos ERROR ("copy exit status failed"); 334 1.1 christos pex_free (pex1); 335 1.1 christos if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL) 336 1.1 christos ERROR ("temporary files exist"); 337 1.1 christos 338 1.1 christos pex1 = TEST_PEX_INIT (PEX_SAVE_TEMPS, "temp"); 339 1.1 christos subargv[1] = "echo"; 340 1.1 christos subargv[2] = "quux"; 341 1.1 christos subargv[3] = NULL; 342 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL); 343 1.1 christos subargv[1] = "copy"; 344 1.1 christos subargv[2] = NULL; 345 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); 346 1.1 christos e = TEST_PEX_READ_OUTPUT (pex1); 347 1.1 christos CHECK_LINE (e, "quux"); 348 1.1 christos TEST_PEX_GET_STATUS (pex1, 2, statuses); 349 1.1 christos if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS 350 1.1 christos || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) 351 1.1 christos ERROR ("copy temp exit status failed"); 352 1.1 christos e = fopen ("temp.x", "r"); 353 1.1 christos if (e == NULL) 354 1.1 christos FATAL_ERROR ("fopen temp.x failed in copy temp", errno); 355 1.1 christos CHECK_LINE (e, "quux"); 356 1.1 christos fclose (e); 357 1.1 christos e = fopen ("temp.y", "r"); 358 1.1 christos if (e == NULL) 359 1.1 christos FATAL_ERROR ("fopen temp.y failed in copy temp", errno); 360 1.1 christos CHECK_LINE (e, "quux"); 361 1.1 christos fclose (e); 362 1.1 christos pex_free (pex1); 363 1.1 christos remove ("temp.x"); 364 1.1 christos remove ("temp.y"); 365 1.1 christos 366 1.1 christos pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); 367 1.1 christos subargv[1] = "echoerr"; 368 1.1 christos subargv[2] = "one"; 369 1.1 christos subargv[3] = "two"; 370 1.1 christos subargv[4] = NULL; 371 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", "temp2.x"); 372 1.1 christos subargv[1] = "write"; 373 1.1 christos subargv[2] = "temp2.y"; 374 1.1 christos subargv[3] = NULL; 375 1.1 christos TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); 376 1.1 christos TEST_PEX_GET_STATUS (pex1, 2, statuses); 377 1.1 christos if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS 378 1.1 christos || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) 379 1.1 christos ERROR ("echoerr exit status failed"); 380 1.1 christos pex_free (pex1); 381 1.1 christos if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL) 382 1.1 christos ERROR ("temporary files exist"); 383 1.1 christos e = fopen ("temp2.x", "r"); 384 1.1 christos if (e == NULL) 385 1.1 christos FATAL_ERROR ("fopen temp2.x failed in echoerr", errno); 386 1.1 christos CHECK_LINE (e, "two"); 387 1.1 christos fclose (e); 388 1.1 christos e = fopen ("temp2.y", "r"); 389 1.1 christos if (e == NULL) 390 1.1 christos FATAL_ERROR ("fopen temp2.y failed in echoerr", errno); 391 1.1 christos CHECK_LINE (e, "one"); 392 1.1 christos fclose (e); 393 1.1 christos remove ("temp2.x"); 394 1.1 christos remove ("temp2.y"); 395 1.1 christos 396 1.1 christos /* Test the old pexecute interface. */ 397 1.1 christos { 398 1.1 christos int pid1, pid2; 399 1.1 christos char *errmsg_fmt; 400 1.1 christos char *errmsg_arg; 401 1.1 christos char errbuf1[1000]; 402 1.1 christos char errbuf2[1000]; 403 1.1 christos 404 1.1 christos subargv[1] = "echo"; 405 1.1 christos subargv[2] = "oldpexecute"; 406 1.1 christos subargv[3] = NULL; 407 1.1 christos pid1 = pexecute ("./test-pexecute", subargv, "test-pexecute", "temp", 408 1.1 christos &errmsg_fmt, &errmsg_arg, PEXECUTE_FIRST); 409 1.1 christos if (pid1 < 0) 410 1.1 christos { 411 1.1 christos snprintf (errbuf1, sizeof errbuf1, errmsg_fmt, errmsg_arg); 412 1.1 christos snprintf (errbuf2, sizeof errbuf2, "pexecute 1 failed: %s", errbuf1); 413 1.1 christos FATAL_ERROR (errbuf2, 0); 414 1.1 christos } 415 1.1 christos 416 1.1 christos subargv[1] = "write"; 417 1.1 christos subargv[2] = "temp.y"; 418 1.1 christos subargv[3] = NULL; 419 1.1 christos pid2 = pexecute ("./test-pexecute", subargv, "test-pexecute", "temp", 420 1.1 christos &errmsg_fmt, &errmsg_arg, PEXECUTE_LAST); 421 1.1 christos if (pid2 < 0) 422 1.1 christos { 423 1.1 christos snprintf (errbuf1, sizeof errbuf1, errmsg_fmt, errmsg_arg); 424 1.1 christos snprintf (errbuf2, sizeof errbuf2, "pexecute 2 failed: %s", errbuf1); 425 1.1 christos FATAL_ERROR (errbuf2, 0); 426 1.1 christos } 427 1.1 christos 428 1.1 christos if (pwait (pid1, &status, 0) < 0) 429 1.1 christos FATAL_ERROR ("write pwait 1 failed", errno); 430 1.1 christos if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) 431 1.1 christos ERROR ("write exit status 1 failed"); 432 1.1 christos 433 1.1 christos if (pwait (pid2, &status, 0) < 0) 434 1.1 christos FATAL_ERROR ("write pwait 1 failed", errno); 435 1.1 christos if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) 436 1.1 christos ERROR ("write exit status 2 failed"); 437 1.1 christos 438 1.1 christos e = fopen ("temp.y", "r"); 439 1.1 christos if (e == NULL) 440 1.1 christos FATAL_ERROR ("fopen temp.y failed in copy temp", errno); 441 1.1 christos CHECK_LINE (e, "oldpexecute"); 442 1.1 christos fclose (e); 443 1.1 christos 444 1.1 christos remove ("temp.y"); 445 1.1 christos } 446 1.1 christos 447 1.1 christos if (trace) 448 1.1 christos fprintf (stderr, "Exiting with status %d\n", error_count); 449 1.1 christos 450 1.1 christos return error_count; 451 1.1 christos } 452 1.1 christos 453 1.1 christos /* Execute one of the special testing commands. */ 454 1.1 christos 455 1.1 christos static void 456 1.1 christos do_cmd (int argc, char **argv) 457 1.1 christos { 458 1.1 christos const char *s; 459 1.1 christos 460 1.1 christos /* Try to prevent generating a core dump. */ 461 1.1 christos #ifdef RLIMIT_CORE 462 1.1 christos { 463 1.1 christos struct rlimit r; 464 1.1 christos 465 1.1 christos r.rlim_cur = 0; 466 1.1 christos r.rlim_max = 0; 467 1.1 christos setrlimit (RLIMIT_CORE, &r); 468 1.1 christos } 469 1.1 christos #endif 470 1.1 christos 471 1.1 christos s = argv[1]; 472 1.1 christos if (strcmp (s, "exit") == 0) 473 1.1 christos exit (EXIT_SUCCESS); 474 1.1 christos else if (strcmp (s, "echo") == 0) 475 1.1 christos { 476 1.1 christos int i; 477 1.1 christos 478 1.1 christos for (i = 2; i < argc; ++i) 479 1.1 christos { 480 1.1 christos if (i > 2) 481 1.1 christos putchar (' '); 482 1.1 christos fputs (argv[i], stdout); 483 1.1 christos } 484 1.1 christos putchar ('\n'); 485 1.1 christos exit (EXIT_SUCCESS); 486 1.1 christos } 487 1.1 christos else if (strcmp (s, "echoerr") == 0) 488 1.1 christos { 489 1.1 christos int i; 490 1.1 christos 491 1.1 christos for (i = 2; i < argc; ++i) 492 1.1 christos { 493 1.1 christos if (i > 3) 494 1.1 christos putc (' ', (i & 1) == 0 ? stdout : stderr); 495 1.1 christos fputs (argv[i], (i & 1) == 0 ? stdout : stderr); 496 1.1 christos } 497 1.1 christos putc ('\n', stdout); 498 1.1 christos putc ('\n', stderr); 499 1.1 christos exit (EXIT_SUCCESS); 500 1.1 christos } 501 1.1 christos else if (strcmp (s, "error") == 0) 502 1.1 christos exit (EXIT_FAILURE); 503 1.1 christos else if (strcmp (s, "abort") == 0) 504 1.1 christos abort (); 505 1.1 christos else if (strcmp (s, "copy") == 0) 506 1.1 christos { 507 1.1 christos int c; 508 1.1 christos 509 1.1 christos while ((c = getchar ()) != EOF) 510 1.1 christos putchar (c); 511 1.1 christos exit (EXIT_SUCCESS); 512 1.1 christos } 513 1.1 christos else if (strcmp (s, "write") == 0) 514 1.1 christos { 515 1.1 christos FILE *e; 516 1.1 christos int c; 517 1.1 christos 518 1.1 christos e = fopen (argv[2], "w"); 519 1.1 christos if (e == NULL) 520 1.1 christos FATAL_ERROR ("fopen for write failed", errno); 521 1.1 christos while ((c = getchar ()) != EOF) 522 1.1 christos putc (c, e); 523 1.1 christos if (fclose (e) != 0) 524 1.1 christos FATAL_ERROR ("fclose for write failed", errno); 525 1.1 christos exit (EXIT_SUCCESS); 526 1.1 christos } 527 1.1 christos else 528 1.1 christos { 529 1.1 christos char buf[1000]; 530 1.1 christos 531 1.1 christos snprintf (buf, sizeof buf, "unrecognized command %s", argv[1]); 532 1.1 christos FATAL_ERROR (buf, 0); 533 1.1 christos } 534 1.1 christos 535 1.1 christos exit (EXIT_FAILURE); 536 1.1 christos } 537