+/* Run `cmd' and redirect the output to `redir'. */
+
+static int
+run_cmd (char *cmd, const char *redir)
+{
+ 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;
+ int redir_handle = -1;
+ int stdout_save = -1;
+
+ /* Count the args. */
+ i = 0;
+
+ for (s = cmd; *s; s++)
+ if (*s == ' ')
+ i++;
+
+ i++;
+ argv = alloca (sizeof (char *) * (i + 3));
+ i = 0;
+ s = cmd;
+
+ 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;
+
+ /* Setup the redirection. We can't use the usual fork/exec and redirect
+ since we may be running on non-POSIX Windows host. */
+
+ fflush (stdout);
+ fflush (stderr);
+
+ /* Open temporary output file. */
+ redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ if (redir_handle == -1)
+ fatal (_("can't open temporary file `%s': %s"), redir,
+ strerror (errno));
+
+ /* Duplicate the stdout file handle so it can be restored later. */
+ stdout_save = dup (STDOUT_FILENO);
+ if (stdout_save == -1)
+ fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
+
+ /* Redirect stdout to our output file. */
+ dup2 (redir_handle, STDOUT_FILENO);
+
+ pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
+ &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
+
+ /* Restore stdout to its previous setting. */
+ dup2 (stdout_save, STDOUT_FILENO);
+
+ /* Close response file. */
+ close (redir_handle);
+
+ if (pid == -1)
+ {
+ fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
+ return 1;
+ }
+
+ retcode = 0;
+ pid = pwait (pid, &wait_status, 0);
+
+ if (pid == -1)
+ {
+ fatal (_("wait: %s"), strerror (errno));
+ retcode = 1;
+ }
+ else if (WIFSIGNALED (wait_status))
+ {
+ fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
+ retcode = 1;
+ }
+ else if (WIFEXITED (wait_status))
+ {
+ if (WEXITSTATUS (wait_status) != 0)
+ {
+ fatal (_("%s exited with status %d"), cmd,
+ WEXITSTATUS (wait_status));
+ retcode = 1;
+ }
+ }
+ else
+ retcode = 1;
+
+ return retcode;
+}
+
+static FILE *
+open_input_stream (char *cmd)
+{
+ if (istream_type == ISTREAM_FILE)
+ {
+ char *fileprefix;
+
+ fileprefix = choose_temp_base ();
+ cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
+ sprintf (cpp_temp_file, "%s.irc", fileprefix);
+ free (fileprefix);
+
+ if (run_cmd (cmd, cpp_temp_file))
+ fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
+
+ cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
+ if (cpp_pipe == NULL)
+ fatal (_("can't open temporary file `%s': %s"),
+ cpp_temp_file, strerror (errno));
+
+ if (verbose)
+ fprintf (stderr,
+ _("Using temporary file `%s' to read preprocessor output\n"),
+ cpp_temp_file);
+ }
+ else
+ {
+ cpp_pipe = popen (cmd, FOPEN_RT);
+ if (cpp_pipe == NULL)
+ fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
+ if (verbose)
+ fprintf (stderr, _("Using popen to read preprocessor output\n"));
+ }
+
+ xatexit (close_input_stream);
+ return cpp_pipe;
+}
+
+/* Determine if FILENAME contains special characters that
+ can cause problems unless the entire filename is quoted. */
+
+static int
+filename_need_quotes (const char *filename)
+{
+ if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
+ return 0;
+
+ while (*filename != 0)
+ {
+ switch (*filename)
+ {
+ case '&':
+ case ' ':
+ case '<':
+ case '>':
+ case '|':
+ case '%':
+ return 1;
+ }
+ ++filename;
+ }
+ return 0;
+}
+
+/* Look for the preprocessor program. */
+
+static FILE *
+look_for_default (char *cmd, const char *prefix, int end_prefix,
+ const char *preprocargs, const char *filename)
+{
+ char *space;
+ int found;
+ struct stat s;
+ const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
+
+ strcpy (cmd, prefix);
+
+ sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
+ space = strchr (cmd + end_prefix, ' ');
+ if (space)
+ *space = 0;
+
+ if (
+#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
+ strchr (cmd, '\\') ||
+#endif
+ strchr (cmd, '/'))
+ {
+ found = (stat (cmd, &s) == 0
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
+#endif
+ );
+
+ if (! found)
+ {
+ if (verbose)
+ fprintf (stderr, _("Tried `%s'\n"), cmd);
+ return NULL;
+ }
+ }
+
+ strcpy (cmd, prefix);
+
+ sprintf (cmd + end_prefix, "%s %s %s%s%s",
+ DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
+
+ if (verbose)
+ fprintf (stderr, _("Using `%s'\n"), cmd);
+
+ cpp_pipe = open_input_stream (cmd);
+ return cpp_pipe;
+}
+