From 5a298d2d9c2cf09936f8380963173e6b66249207 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 7 Jan 2000 22:33:48 +0000 Subject: [PATCH] Apply Mumit Khan's patch to allow temporary file for process interconnection --- binutils/ChangeLog | 22 ++++ binutils/binutils.texi | 11 ++ binutils/resrc.c | 275 ++++++++++++++++++++++++++++++++++++++--- binutils/windres.c | 23 +++- binutils/windres.h | 2 +- 5 files changed, 309 insertions(+), 24 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 98ce3bb321..b20df8f3be 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,25 @@ +2000-01-07 Mumit Khan + + * windres.c (long_options): Add --use-temp-file and + --no-use-temp-file options. + (usage): Document. + (main): Handle. + + * windres.h: Update read_rc_file prototype. + + * resrc.c (cpp_temp_file): New static variable. + (istream_type): New static variable. + (close_pipe): Delete function. + (run_cmd): New static function. + (open_input_stream): New static function. + (close_input_stream): New static function. + (look_for_default): Handle DOS directory separator. Use + open_input_stream instead of popen. + (read_rc_file): Likewise. + + * binutils.texi: Document --use-temp-file, --no-use-temp-file + options. + 2000-01-04 Mumit Khan * dlltool.c (create_compat_implib): New variable. diff --git a/binutils/binutils.texi b/binutils/binutils.texi index 8ef446debc..ff87412ddc 100644 --- a/binutils/binutils.texi +++ b/binutils/binutils.texi @@ -2140,6 +2140,17 @@ Specify the default language to use when reading an @code{rc} file. @var{val} should be a hexadecimal language code. The low eight bits are the language, and the high eight bits are the sublanguage. +@item --use-temp-file +Use a temporary file to instead of using popen to read the output of +the preprocessor. Use this option if the popen implementation is buggy +on the host (eg., certain non-English language versions of Windows 95 and +Windows 98 are known to have buggy popen where the output will instead +go the console). + +@item --no-use-temp-file +Use popen, not a temporary file, to read the output of the preprocessor. +This is the default behaviour. + @item --help Prints a usage summary. diff --git a/binutils/resrc.c b/binutils/resrc.c index 8ed6a5d158..b38c75d207 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -29,9 +29,50 @@ #include #include +#include #include +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#else /* ! HAVE_SYS_WAIT_H */ +#if ! defined (_WIN32) || defined (__CYGWIN__) +#ifndef WIFEXITED +#define WIFEXITED(w) (((w)&0377) == 0) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0177) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) >> 8) & 0377) +#endif +#else /* defined (_WIN32) && ! defined (__CYGWIN__) */ +#ifndef WIFEXITED +#define WIFEXITED(w) (((w) & 0xff) == 0) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0x7f) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) +#endif +#endif /* defined (_WIN32) && ! defined (__CYGWIN__) */ +#endif /* ! HAVE_SYS_WAIT_H */ #if defined (_WIN32) && ! defined (__CYGWIN32__) +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#if defined (_WIN32) && ! defined (__CYGWIN__) #define popen _popen #define pclose _pclose #endif @@ -86,6 +127,15 @@ int rc_lineno; static FILE *cpp_pipe; +/* The temporary file used if we're not using popen, so we can delete it + if we exit. */ + +static char *cpp_temp_file; + +/* Input stream is either a file or a pipe. */ + +static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type; + /* As we read the rc file, we attach information to this structure. */ static struct res_directory *resources; @@ -112,9 +162,11 @@ static int icons; /* Local functions. */ +static int run_cmd PARAMS ((char *, const char *)); +static FILE *open_input_stream PARAMS ((char *)); static FILE *look_for_default PARAMS ((char *, const char *, int, const char *, const char *)); -static void close_pipe PARAMS ((void)); +static void close_input_stream PARAMS ((void)); static void unexpected_eof PARAMS ((const char *)); static int get_word PARAMS ((FILE *, const char *)); static unsigned long get_long PARAMS ((FILE *, const char *)); @@ -122,6 +174,163 @@ static void get_data PARAMS ((FILE *, unsigned char *, unsigned long, const char *)); static void define_fontdirs PARAMS ((void)); +/* Run `cmd' and redirect the output to `redir'. */ + +static int +run_cmd (cmd, redir) + 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 reponse 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 (cmd) + 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; +} + /* look for the preprocessor program */ static FILE * @@ -143,7 +352,11 @@ look_for_default (cmd, prefix, end_prefix, preprocargs, filename) if (space) *space = 0; - if (strchr (cmd, '/')) + if ( +#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32) + strchr (cmd, '\\') || +#endif + strchr (cmd, '/')) { found = (stat (cmd, &s) == 0 #ifdef HAVE_EXECUTABLE_SUFFIX @@ -154,7 +367,7 @@ look_for_default (cmd, prefix, end_prefix, preprocargs, filename) if (! found) { if (verbose) - fprintf (stderr, "Tried `%s'\n", cmd); + fprintf (stderr, _("Tried `%s'\n"), cmd); return NULL; } } @@ -165,23 +378,26 @@ look_for_default (cmd, prefix, end_prefix, preprocargs, filename) DEFAULT_PREPROCESSOR, preprocargs, filename); if (verbose) - fprintf (stderr, "Using `%s'\n", cmd); + fprintf (stderr, _("Using `%s'\n"), cmd); - cpp_pipe = popen (cmd, FOPEN_RT); + cpp_pipe = open_input_stream (cmd); return cpp_pipe; } /* Read an rc file. */ struct res_directory * -read_rc_file (filename, preprocessor, preprocargs, language) +read_rc_file (filename, preprocessor, preprocargs, language, use_temp_file) const char *filename; const char *preprocessor; const char *preprocargs; int language; + int use_temp_file; { char *cmd; + istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE; + if (preprocargs == NULL) preprocargs = ""; if (filename == NULL) @@ -195,7 +411,7 @@ read_rc_file (filename, preprocessor, preprocargs, language) + 10); sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename); - cpp_pipe = popen (cmd, FOPEN_RT); + cpp_pipe = open_input_stream (cmd); } else { @@ -219,7 +435,7 @@ read_rc_file (filename, preprocessor, preprocargs, language) if (*cp == '-') dash = cp; if ( -#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) +#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32) *cp == ':' || *cp == '\\' || #endif *cp == '/') @@ -257,12 +473,9 @@ read_rc_file (filename, preprocessor, preprocargs, language) } } - if (cpp_pipe == NULL) - fatal (_("can't popen `%s': %s"), cmd, strerror (errno)); + free (cmd); - xatexit (close_pipe); - rc_filename = xstrdup (filename); rc_lineno = 1; if (language != -1) @@ -270,10 +483,8 @@ read_rc_file (filename, preprocessor, preprocargs, language) yyin = cpp_pipe; yyparse (); - if (pclose (cpp_pipe) != 0) - fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name); - cpp_pipe = NULL; - + close_input_stream (); + if (fontdirs != NULL) define_fontdirs (); @@ -283,13 +494,37 @@ read_rc_file (filename, preprocessor, preprocargs, language) return resources; } -/* Close the pipe if it is open. This is called via xatexit. */ +/* Close the input stream if it is open. */ -void -close_pipe () +static void +close_input_stream () { if (cpp_pipe != NULL) pclose (cpp_pipe); + + if (istream_type == ISTREAM_FILE) + { + if (cpp_pipe != NULL) + fclose (cpp_pipe); + + if (cpp_temp_file != NULL) + { + int errno_save = errno; + + unlink (cpp_temp_file); + errno = errno_save; + free (cpp_temp_file); + } + } + else + { + if (cpp_pipe != NULL) + pclose (cpp_pipe); + } + + /* Since this is also run via xatexit, safeguard. */ + cpp_pipe = NULL; + cpp_temp_file = NULL; } /* Report an error while reading an rc file. */ @@ -307,7 +542,7 @@ void rcparse_warning (msg) const char *msg; { - fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg); + fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg); } /* Die if we get an unexpected end of file. */ diff --git a/binutils/windres.c b/binutils/windres.c index 0ccd909404..3b24b47825 100644 --- a/binutils/windres.c +++ b/binutils/windres.c @@ -113,7 +113,9 @@ static struct include_dir *include_dirs; #define OPTION_INCLUDE_DIR (OPTION_HELP + 1) #define OPTION_LANGUAGE (OPTION_INCLUDE_DIR + 1) #define OPTION_PREPROCESSOR (OPTION_LANGUAGE + 1) -#define OPTION_VERSION (OPTION_PREPROCESSOR + 1) +#define OPTION_USE_TEMP_FILE (OPTION_PREPROCESSOR + 1) +#define OPTION_NO_USE_TEMP_FILE (OPTION_USE_TEMP_FILE + 1) +#define OPTION_VERSION (OPTION_NO_USE_TEMP_FILE + 1) #define OPTION_YYDEBUG (OPTION_VERSION + 1) static const struct option long_options[] = @@ -126,6 +128,8 @@ static const struct option long_options[] = {"output-format", required_argument, 0, 'O'}, {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR}, {"target", required_argument, 0, 'F'}, + {"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE}, + {"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, OPTION_VERSION}, {"yydebug", no_argument, 0, OPTION_YYDEBUG}, @@ -713,7 +717,10 @@ Options:\n\ -DSYM[=VAL], --define SYM[=VAL]\n\ Define SYM when preprocessing rc file\n\ -v Verbose - tells you what it's doing\n\ - --language VAL Set language when reading rc file\n")); + --language VAL Set language when reading rc file\n\ + --use-temp-file Use a temporary file instead of popen to read\n\ + the preprocessor output\n\ + --no-use-temp-file Use popen (default)\n")); #ifdef YYDEBUG fprintf (stream, _("\ --yydebug Turn on parser debugging\n")); @@ -777,6 +784,7 @@ main (argc, argv) const char *quotedarg; int language; struct res_directory *resources; + int use_temp_file; #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) setlocale (LC_MESSAGES, ""); @@ -800,6 +808,7 @@ main (argc, argv) preprocessor = NULL; preprocargs = NULL; language = -1; + use_temp_file = 0; while ((c = getopt_long (argc, argv, "i:o:I:O:F:D:v", long_options, (int *) 0)) != EOF) @@ -890,6 +899,14 @@ main (argc, argv) language = strtol (optarg, (char **) NULL, 16); break; + case OPTION_USE_TEMP_FILE: + use_temp_file = 1; + break; + + case OPTION_NO_USE_TEMP_FILE: + use_temp_file = 0; + break; + #ifdef YYDEBUG case OPTION_YYDEBUG: yydebug = 1; @@ -949,7 +966,7 @@ main (argc, argv) abort (); case RES_FORMAT_RC: resources = read_rc_file (input_filename, preprocessor, preprocargs, - language); + language, use_temp_file); break; case RES_FORMAT_RES: resources = read_res_file (input_filename); diff --git a/binutils/windres.h b/binutils/windres.h index db43dd51c9..ba73612982 100644 --- a/binutils/windres.h +++ b/binutils/windres.h @@ -747,7 +747,7 @@ extern int verbose; /* Function declarations. */ extern struct res_directory *read_rc_file - PARAMS ((const char *, const char *, const char *, int)); + PARAMS ((const char *, const char *, const char *, int, int)); extern struct res_directory *read_res_file PARAMS ((const char *)); extern struct res_directory *read_coff_rsrc PARAMS ((const char *, const char *));