static void do_compile (const char **current_argv, int current_argc) { char *errmsg_fmt, *errmsg_arg; int index = 0; int dash_o_index = current_argc; int of_index = current_argc + 1; int argc_count = current_argc + 2; while (index < num_arches) { int additional_arch_options = 0; current_argv[0] = get_driver_name (get_arch_name (arches[index])); /* setup output file. */ out_files[num_outfiles] = make_temp_file (".out"); current_argv[dash_o_index] = "-o"; current_argv[of_index] = out_files [num_outfiles]; num_outfiles++; /* Add arch option as the last option. Do not add any other option before removing this option. */ additional_arch_options = add_arch_options (index, current_argv, argc_count); argc_count += additional_arch_options; commands[index].prog = current_argv[0]; commands[index].argv = current_argv; current_argv[argc_count] = NULL; #ifdef DEBUG debug_command_line (current_argv, argc_count); #endif commands[index].pid = pexecute (current_argv[0], (char *const *)current_argv, progname, NULL, &errmsg_fmt, &errmsg_arg, PEXECUTE_SEARCH | PEXECUTE_ONE); if (commands[index].pid == -1) pfatal_pexecute (errmsg_fmt, errmsg_arg); do_wait (commands[index].pid, commands[index].prog); fflush (stdout); /* Remove the last arch option added in the current_argv list. */ if (additional_arch_options) argc_count -= remove_arch_options (current_argv, argc_count); index++; } }
static void do_lipo (int start_outfile_index, const char *out_file) { int i, j, pid; char *errmsg_fmt, *errmsg_arg; /* Populate lipo arguments. */ lipo_argv[0] = "lipo"; lipo_argv[1] = "-create"; lipo_argv[2] = "-o"; lipo_argv[3] = out_file; /* Already 4 lipo arguments are set. Now add all lipo inputs. */ j = 4; for (i = 0; i < num_arches; i++) lipo_argv[j++] = out_files[start_outfile_index + i]; /* Add the NULL at the end. */ lipo_argv[j++] = NULL; #ifdef DEBUG debug_command_line (lipo_argv, j); #endif if (verbose_flag) { for (i = 0; lipo_argv[i]; i++) fprintf (stderr, "%s ", lipo_argv[i]); fprintf (stderr, "\n"); } pid = pexecute (lipo_argv[0], (char *const *)lipo_argv, progname, NULL, &errmsg_fmt, &errmsg_arg, PEXECUTE_SEARCH | PEXECUTE_ONE); if (pid == -1) pfatal_pexecute (errmsg_fmt, errmsg_arg); do_wait (pid, lipo_argv[0]); }
static int run (const char *what, char *args) { char *s; int pid, wait_status, retcode; int i; const char **argv; char *errmsg_fmt, *errmsg_arg; char *temp_base = choose_temp_base (); int in_quote; char sep; if (verbose || dry_run) fprintf (stderr, "%s %s\n", what, args); /* Count the args */ i = 0; for (s = args; *s; s++) if (*s == ' ') i++; i++; argv = xmalloc (sizeof (char *) * (i + 3)); i = 0; argv[i++] = what; s = args; while (1) { while (*s == ' ' && *s != 0) s++; if (*s == 0) break; in_quote = (*s == '\'' || *s == '"'); sep = (in_quote) ? *s++ : ' '; argv[i++] = s; while (*s != sep && *s != 0) s++; if (*s == 0) break; *s++ = 0; if (in_quote) s++; } argv[i++] = NULL; if (dry_run) return 0; pid = pexecute (argv[0], (char * const *) argv, prog_name, temp_base, &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); free (argv); if (pid == -1) { int errno_val = errno; fprintf (stderr, "%s: ", prog_name); fprintf (stderr, errmsg_fmt, errmsg_arg); fprintf (stderr, ": %s\n", strerror (errno_val)); return 1; } retcode = 0; pid = pwait (pid, &wait_status, 0); if (pid == -1) { warn (_("pwait returns: %s"), strerror (errno)); retcode = 1; } else if (WIFSIGNALED (wait_status)) { warn (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); retcode = 1; } else if (WIFEXITED (wait_status)) { if (WEXITSTATUS (wait_status) != 0) { warn (_("%s exited with status %d"), what, WEXITSTATUS (wait_status)); retcode = 1; } } else retcode = 1; return retcode; }
/* Main entry point. This is gcc driver driver! Interpret -arch flag from the list of input arguments. Invoke appropriate compiler driver. 'lipo' the results if more than one -arch is supplied. */ int main (int argc, const char **argv) { size_t i; int l, pid, argv_0_len, prog_len; char *errmsg_fmt, *errmsg_arg; char *override_option_str = NULL; char path_buffer[2*PATH_MAX+1]; int linklen; total_argc = argc; prog_len = 0; argv_0_len = strlen (argv[0]); /* Get the progname, required by pexecute () and program location. */ prog_len = get_prog_name_len (argv[0]); /* If argv[0] is all program name (no slashes), search the PATH environment variable to get the fully resolved path to the executable. */ if (prog_len == argv_0_len) { #ifdef DEBUG progname = argv[0] + argv_0_len - prog_len; fprintf (stderr,"%s: before PATH resolution, full progname = %s\n", argv[0]+argv_0_len-prog_len, argv[0]); #endif argv[0] = resolve_path_to_executable (argv[0]); prog_len = get_prog_name_len (argv[0]); argv_0_len = strlen(argv[0]); } /* If argv[0] is a symbolic link, use the directory of the pointed-to file to find compiler components. */ if ((linklen = readlink (argv[0], path_buffer, PATH_MAX)) != -1) { /* readlink succeeds if argv[0] is a symlink. path_buffer now contains the file referenced. */ path_buffer[linklen] = '\0'; #ifdef DEBUG progname = argv[0] + argv_0_len - prog_len; fprintf (stderr, "%s: before symlink, full prog = %s target = %s\n", progname, argv[0], path_buffer); #endif argv[0] = resolve_symlink(argv[0], path_buffer, argv_0_len, prog_len); argv_0_len = strlen(argv[0]); /* Get the progname, required by pexecute () and program location. */ prog_len = get_prog_name_len (argv[0]); #ifdef DEBUG progname = argv[0] + argv_0_len - prog_len; printf("%s: ARGV[0] after symlink = %s\n", progname, argv[0]); #endif } progname = argv[0] + argv_0_len - prog_len; /* Setup driver prefix. */ prefix_len = argv_0_len - prog_len; curr_dir = (char *) malloc (sizeof (char) * (prefix_len + 1)); strncpy (curr_dir, argv[0], prefix_len); curr_dir[prefix_len] = '\0'; driver_exec_prefix = (argv[0], "/usr/bin", curr_dir); #ifdef DEBUG fprintf (stderr,"%s: full progname = %s\n", progname, argv[0]); fprintf (stderr,"%s: progname = %s\n", progname, progname); fprintf (stderr,"%s: driver_exec_prefix = %s\n", progname, driver_exec_prefix); #endif /* Before we get too far, rewrite the command line with any requested overrides */ if ((override_option_str = getenv ("QA_OVERRIDE_GCC3_OPTIONS")) != NULL) rewrite_command_line(override_option_str, &argc, (char***)&argv); initialize (); /* Process arguments. Take appropriate actions when -arch, -c, -S, -E, -o is encountered. Find input file name. */ for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "-arch")) { if (i + 1 >= argc) abort (); add_arch (argv[i+1]); i++; } else if (!strcmp (argv[i], "-c")) { new_argv[new_argc++] = argv[i]; compile_only_request = 1; } else if (!strcmp (argv[i], "-S")) { new_argv[new_argc++] = argv[i]; asm_output_request = 1; } else if (!strcmp (argv[i], "-E")) { new_argv[new_argc++] = argv[i]; preprocessed_output_request = 1; } else if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD")) { new_argv[new_argc++] = argv[i]; dash_capital_m_seen = 1; } else if (!strcmp (argv[i], "-m32")) { new_argv[new_argc++] = argv[i]; dash_m32_seen = 1; } else if (!strcmp (argv[i], "-m64")) { new_argv[new_argc++] = argv[i]; dash_m64_seen = 1; } else if (!strcmp (argv[i], "-dynamiclib")) { new_argv[new_argc++] = argv[i]; dash_dynamiclib_seen = 1; } else if (!strcmp (argv[i], "-v")) { new_argv[new_argc++] = argv[i]; verbose_flag = 1; } else if (!strcmp (argv[i], "-o")) { if (i + 1 >= argc) fatal ("argument to '-o' is missing"); output_filename = argv[i+1]; i++; } else if ((! strcmp (argv[i], "-pass-exit-codes")) || (! strcmp (argv[i], "-print-search-dirs")) || (! strcmp (argv[i], "-print-libgcc-file-name")) || (! strncmp (argv[i], "-print-file-name=", 17)) || (! strncmp (argv[i], "-print-prog-name=", 17)) || (! strcmp (argv[i], "-print-multi-lib")) || (! strcmp (argv[i], "-print-multi-directory")) || (! strcmp (argv[i], "-print-multi-os-directory")) || (! strcmp (argv[i], "-ftarget-help")) || (! strcmp (argv[i], "-fhelp")) || (! strcmp (argv[i], "+e")) || (! strncmp (argv[i], "-Wa,",4)) || (! strncmp (argv[i], "-Wp,",4)) || (! strncmp (argv[i], "-Wl,",4)) || (! strncmp (argv[i], "-l", 2)) || (! strncmp (argv[i], "-weak-l", 7)) || (! strncmp (argv[i], "-specs=", 7)) || (! strcmp (argv[i], "-ObjC")) || (! strcmp (argv[i], "-fobjC")) || (! strcmp (argv[i], "-ObjC++")) || (! strcmp (argv[i], "-time")) || (! strcmp (argv[i], "-###")) || (! strcmp (argv[i], "-fconstant-cfstrings")) || (! strcmp (argv[i], "-fno-constant-cfstrings")) || (! strcmp (argv[i], "-static-libgcc")) || (! strcmp (argv[i], "-shared-libgcc")) || (! strcmp (argv[i], "-pipe")) ) { new_argv[new_argc++] = argv[i]; } else if (! strcmp (argv[i], "-save-temps") || ! strcmp (argv[i], "--save-temps")) { new_argv[new_argc++] = argv[i]; save_temps_seen = 1; } else if ((! strcmp (argv[i], "-Xlinker")) || (! strcmp (argv[i], "-Xassembler")) || (! strcmp (argv[i], "-Xpreprocessor")) || (! strcmp (argv[i], "-l")) || (! strcmp (argv[i], "-weak_library")) || (! strcmp (argv[i], "-weak_framework")) || (! strcmp (argv[i], "-specs")) || (! strcmp (argv[i], "-framework")) ) { new_argv[new_argc++] = argv[i]; i++; new_argv[new_argc++] = argv[i]; } else if (! strncmp (argv[i], "-Xarch_", 7)) { arch_conditional[new_argc] = get_arch_name (argv[i] + 7); i++; new_argv[new_argc++] = argv[i]; } else if (argv[i][0] == '-' && argv[i][1] != 0) { const char *p = &argv[i][1]; int c = *p; /* First copy this flag itself. */ new_argv[new_argc++] = argv[i]; if (argv[i][1] == 'M') dash_capital_m_seen = 1; /* Now copy this flag's arguments, if any, appropriately. */ if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) || WORD_SWITCH_TAKES_ARG (p)) { int j = 0; int n_args = WORD_SWITCH_TAKES_ARG (p); if (n_args == 0) { /* Count only the option arguments in separate argv elements. */ n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); } if (i + n_args >= argc) fatal ("argument to `-%s' is missing", p); while ( j < n_args) { i++; new_argv[new_argc++] = argv[i]; j++; } } } else { struct input_filename *ifn; new_argv[new_argc++] = argv[i]; ifn = (struct input_filename *) malloc (sizeof (struct input_filename)); ifn->name = argv[i]; ifn->index = i; ifn->next = NULL; num_infiles++; if (last_infile) last_infile->next = ifn; else in_files = ifn; last_infile = ifn; } } #if 0 if (num_infiles == 0) fatal ("no input files"); #endif if (num_arches == 0) add_arch(get_arch_name(NULL)); if (num_arches > 1) { if (preprocessed_output_request || save_temps_seen || asm_output_request || dash_capital_m_seen) fatal ("-E, -S, -save-temps and -M options are not allowed with multiple -arch flags"); } /* If -arch is not present OR Only one -arch <blah> is specified. Invoke appropriate compiler driver. FAT build is not required in this case. */ if (num_arches == 1) { int arch_specific_argc; const char **arch_specific_argv; /* Find compiler driver based on -arch <foo> and add approriate -m* argument. */ new_argv[0] = get_driver_name (get_arch_name (arches[0])); new_argc = new_argc + add_arch_options (0, new_argv, new_argc); #ifdef DEBUG printf ("%s: invoking single driver name = %s\n", progname, new_argv[0]); #endif /* Re insert output file name. */ if (output_filename) { new_argv[new_argc++] = "-o"; new_argv[new_argc++] = output_filename; } /* Add the NULL. */ new_argv[new_argc] = NULL; arch_specific_argv = (const char **) malloc ((new_argc + 1) * sizeof (const char *)); arch_specific_argc = filter_args_for_arch (new_argv, new_argc, arch_specific_argv, get_arch_name (arches[0])); #ifdef DEBUG debug_command_line (arch_specific_argv, arch_specific_argc); #endif pid = pexecute (arch_specific_argv[0], (char *const *)arch_specific_argv, progname, NULL, &errmsg_fmt, &errmsg_arg, PEXECUTE_SEARCH | PEXECUTE_ONE); if (pid == -1) pfatal_pexecute (errmsg_fmt, errmsg_arg); do_wait (pid, arch_specific_argv[0]); } else { /* Handle multiple -arch <blah>. */ /* If more than one input files are supplied but only one output filename is present then IMA will be used. */ if (num_infiles > 1 && !compile_only_request) ima_is_used = 1; /* Linker wants to know this in case of multiple -arch. */ if (!compile_only_request && !dash_dynamiclib_seen) new_argv[new_argc++] = "-Wl,-arch_multiple"; /* If only one input file is specified OR IMA is used then expected output is one FAT binary. */ if (num_infiles == 1 || ima_is_used) { const char *out_file; /* Create output file name based on input filename, if required. */ if (compile_only_request && !output_filename && num_infiles == 1) out_file = strip_path_and_suffix (in_files->name, ".o"); else out_file = (output_filename ? output_filename : final_output); /* Linker wants to know name of output file using one extra arg. */ if (!compile_only_request) { char *oname = (char *)(output_filename ? output_filename : final_output); char *n = malloc (sizeof (char) * (strlen (oname) + 5)); strcpy (n, "-Wl,"); strcat (n, oname); new_argv[new_argc++] = "-Wl,-final_output"; new_argv[new_argc++] = n; } /* Compile file(s) for each arch and lipo 'em together. */ do_compile (new_argv, new_argc); /* Make FAT binary by combining individual output files for each architecture, using 'lipo'. */ do_lipo (0, out_file); } else { /* Multiple input files are present and IMA is not used. Which means need to generate multiple FAT files. */ do_compile_separately (); do_lipo_separately (); } } final_cleanup (); free (curr_dir); return greatest_status; }
int main (int argc, char **argv) { int trace; struct pex_obj *test_pex_tmp; int test_pex_status; FILE *test_pex_file; struct pex_obj *pex1; char *subargv[10]; int status; FILE *e; int statuses[10]; trace = 0; if (argc > 1 && strcmp (argv[1], "-t") == 0) { trace = 1; --argc; ++argv; } if (argc > 1) do_cmd (argc, argv); #define TEST_PEX_INIT(FLAGS, TEMPBASE) \ (((test_pex_tmp = pex_init (FLAGS, "test-pexecute", TEMPBASE)) \ != NULL) \ ? test_pex_tmp \ : (FATAL_ERROR ("pex_init failed", 0), NULL)) #define TEST_PEX_RUN(PEXOBJ, FLAGS, EXECUTABLE, ARGV, OUTNAME, ERRNAME) \ do \ { \ int err; \ const char *pex_run_err; \ if (trace) \ fprintf (stderr, "Line %d: running %s %s\n", \ __LINE__, EXECUTABLE, ARGV[0]); \ pex_run_err = pex_run (PEXOBJ, FLAGS, EXECUTABLE, ARGV, OUTNAME, \ ERRNAME, &err); \ if (pex_run_err != NULL) \ FATAL_ERROR (pex_run_err, err); \ } \ while (0) #define TEST_PEX_GET_STATUS_1(PEXOBJ) \ (pex_get_status (PEXOBJ, 1, &test_pex_status) \ ? test_pex_status \ : (FATAL_ERROR ("pex_get_status failed", errno), 1)) #define TEST_PEX_GET_STATUS(PEXOBJ, COUNT, VECTOR) \ do \ { \ if (!pex_get_status (PEXOBJ, COUNT, VECTOR)) \ FATAL_ERROR ("pex_get_status failed", errno); \ } \ while (0) #define TEST_PEX_READ_OUTPUT(PEXOBJ) \ ((test_pex_file = pex_read_output (PEXOBJ, 0)) != NULL \ ? test_pex_file \ : (FATAL_ERROR ("pex_read_output failed", errno), NULL)) remove ("temp.x"); remove ("temp.y"); memset (subargv, 0, sizeof subargv); subargv[0] = "./test-pexecute"; pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL); subargv[1] = "exit"; subargv[2] = NULL; TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, NULL); status = TEST_PEX_GET_STATUS_1 (pex1); if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) ERROR ("exit failed"); pex_free (pex1); pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL); subargv[1] = "error"; subargv[2] = NULL; TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, NULL); status = TEST_PEX_GET_STATUS_1 (pex1); if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_FAILURE) ERROR ("error test failed"); pex_free (pex1); /* We redirect stderr to a file to avoid an error message which is printed on mingw32 when the child calls abort. */ pex1 = TEST_PEX_INIT (PEX_USE_PIPES, NULL); subargv[1] = "abort"; subargv[2] = NULL; TEST_PEX_RUN (pex1, PEX_LAST, "./test-pexecute", subargv, NULL, "temp.z"); status = TEST_PEX_GET_STATUS_1 (pex1); if (!WIFSIGNALED (status) || WTERMSIG (status) != SIGABRT) ERROR ("abort failed"); pex_free (pex1); remove ("temp.z"); pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); subargv[1] = "echo"; subargv[2] = "foo"; subargv[3] = NULL; TEST_PEX_RUN (pex1, 0, "./test-pexecute", subargv, NULL, NULL); e = TEST_PEX_READ_OUTPUT (pex1); CHECK_LINE (e, "foo"); if (TEST_PEX_GET_STATUS_1 (pex1) != 0) ERROR ("echo exit status failed"); pex_free (pex1); pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); subargv[1] = "echo"; subargv[2] = "bar"; subargv[3] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL); subargv[1] = "copy"; subargv[2] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); e = TEST_PEX_READ_OUTPUT (pex1); CHECK_LINE (e, "bar"); TEST_PEX_GET_STATUS (pex1, 2, statuses); if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) ERROR ("copy exit status failed"); pex_free (pex1); if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL) ERROR ("temporary files exist"); pex1 = TEST_PEX_INIT (0, "temp"); subargv[1] = "echo"; subargv[2] = "bar"; subargv[3] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL); subargv[1] = "copy"; subargv[2] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); e = TEST_PEX_READ_OUTPUT (pex1); CHECK_LINE (e, "bar"); TEST_PEX_GET_STATUS (pex1, 2, statuses); if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) ERROR ("copy exit status failed"); pex_free (pex1); if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL) ERROR ("temporary files exist"); pex1 = TEST_PEX_INIT (PEX_SAVE_TEMPS, "temp"); subargv[1] = "echo"; subargv[2] = "quux"; subargv[3] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", NULL); subargv[1] = "copy"; subargv[2] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); e = TEST_PEX_READ_OUTPUT (pex1); CHECK_LINE (e, "quux"); TEST_PEX_GET_STATUS (pex1, 2, statuses); if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) ERROR ("copy temp exit status failed"); e = fopen ("temp.x", "r"); if (e == NULL) FATAL_ERROR ("fopen temp.x failed in copy temp", errno); CHECK_LINE (e, "quux"); fclose (e); e = fopen ("temp.y", "r"); if (e == NULL) FATAL_ERROR ("fopen temp.y failed in copy temp", errno); CHECK_LINE (e, "quux"); fclose (e); pex_free (pex1); remove ("temp.x"); remove ("temp.y"); pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); subargv[1] = "echoerr"; subargv[2] = "one"; subargv[3] = "two"; subargv[4] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".x", "temp2.x"); subargv[1] = "write"; subargv[2] = "temp2.y"; subargv[3] = NULL; TEST_PEX_RUN (pex1, PEX_SUFFIX, "./test-pexecute", subargv, ".y", NULL); TEST_PEX_GET_STATUS (pex1, 2, statuses); if (!WIFEXITED (statuses[0]) || WEXITSTATUS (statuses[0]) != EXIT_SUCCESS || !WIFEXITED (statuses[1]) || WEXITSTATUS (statuses[1]) != EXIT_SUCCESS) ERROR ("echoerr exit status failed"); pex_free (pex1); if (fopen ("temp.x", "r") != NULL || fopen ("temp.y", "r") != NULL) ERROR ("temporary files exist"); e = fopen ("temp2.x", "r"); if (e == NULL) FATAL_ERROR ("fopen temp2.x failed in echoerr", errno); CHECK_LINE (e, "two"); fclose (e); e = fopen ("temp2.y", "r"); if (e == NULL) FATAL_ERROR ("fopen temp2.y failed in echoerr", errno); CHECK_LINE (e, "one"); fclose (e); remove ("temp2.x"); remove ("temp2.y"); /* Test the old pexecute interface. */ { int pid1, pid2; char *errmsg_fmt; char *errmsg_arg; char errbuf1[1000]; char errbuf2[1000]; subargv[1] = "echo"; subargv[2] = "oldpexecute"; subargv[3] = NULL; pid1 = pexecute ("./test-pexecute", subargv, "test-pexecute", "temp", &errmsg_fmt, &errmsg_arg, PEXECUTE_FIRST); if (pid1 < 0) { snprintf (errbuf1, sizeof errbuf1, errmsg_fmt, errmsg_arg); snprintf (errbuf2, sizeof errbuf2, "pexecute 1 failed: %s", errbuf1); FATAL_ERROR (errbuf2, 0); } subargv[1] = "write"; subargv[2] = "temp.y"; subargv[3] = NULL; pid2 = pexecute ("./test-pexecute", subargv, "test-pexecute", "temp", &errmsg_fmt, &errmsg_arg, PEXECUTE_LAST); if (pid2 < 0) { snprintf (errbuf1, sizeof errbuf1, errmsg_fmt, errmsg_arg); snprintf (errbuf2, sizeof errbuf2, "pexecute 2 failed: %s", errbuf1); FATAL_ERROR (errbuf2, 0); } if (pwait (pid1, &status, 0) < 0) FATAL_ERROR ("write pwait 1 failed", errno); if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) ERROR ("write exit status 1 failed"); if (pwait (pid2, &status, 0) < 0) FATAL_ERROR ("write pwait 1 failed", errno); if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) ERROR ("write exit status 2 failed"); e = fopen ("temp.y", "r"); if (e == NULL) FATAL_ERROR ("fopen temp.y failed in copy temp", errno); CHECK_LINE (e, "oldpexecute"); fclose (e); remove ("temp.y"); } if (trace) fprintf (stderr, "Exiting with status %d\n", error_count); return error_count; }