From 31807189b55d9519a46e4b35fadbe20218e4ebea Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 27 Jun 2015 13:48:26 +0300 Subject: [PATCH] Add a new function w32-application-type * src/w32proc.c (Fw32_application_type): New function. ; * etc/NEWS: Mention w32-application-type. --- etc/NEWS | 4 ++ src/w32proc.c | 104 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 93 insertions(+), 15 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index ae62e76a6dc..84636552973 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1114,6 +1114,10 @@ Pass '--without-ns' to configure to create an X11 build, the old default. ** OS X on PowerPC is no longer supported. +--- +** The new function 'w32-application-type' returns the type of an +MS-Windows application given the name of its executable program file. + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/src/w32proc.c b/src/w32proc.c index 1f633d834c2..b301fcf18ab 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -1527,22 +1527,25 @@ waitpid (pid_t pid, int *status, int options) /* Implementation note: This function works with file names encoded in the current ANSI codepage. */ -static void +static int w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, + int * is_msys_app, int * is_gui_app) { file_data executable; char * p; + int retval = 0; /* Default values in case we can't tell for sure. */ *is_dos_app = FALSE; *is_cygnus_app = FALSE; + *is_msys_app = FALSE; *is_gui_app = FALSE; if (!open_input_file (&executable, filename)) - return; + return -1; p = strrchr (filename, '.'); @@ -1560,7 +1563,8 @@ w32_executable_type (char * filename, extension, which is defined in the registry. */ p = egetenv ("COMSPEC"); if (p) - w32_executable_type (p, is_dos_app, is_cygnus_app, is_gui_app); + retval = w32_executable_type (p, is_dos_app, is_cygnus_app, is_msys_app, + is_gui_app); } else { @@ -1637,6 +1641,16 @@ w32_executable_type (char * filename, *is_cygnus_app = TRUE; break; } + else if (strncmp (dllname, "msys-", 5) == 0) + { + /* This catches both MSYS 1.x and MSYS2 + executables (the DLL name is msys-1.0.dll and + msys-2.0.dll, respectively). There's doesn't + seem to be a reason to distinguish between + the two, for now. */ + *is_msys_app = TRUE; + break; + } } } } @@ -1644,6 +1658,7 @@ w32_executable_type (char * filename, unwind: close_file_data (&executable); + return retval; } static int @@ -1702,7 +1717,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) int arglen, numenv; pid_t pid; child_process *cp; - int is_dos_app, is_cygnus_app, is_gui_app; + int is_dos_app, is_cygnus_app, is_msys_app, is_gui_app; int do_quoting = 0; /* We pass our process ID to our children by setting up an environment variable in their environment. */ @@ -1713,10 +1728,10 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) argument being split into two or more. Arguments with wildcards are also quoted, for consistency with posix platforms, where wildcards are not expanded if we run the program directly without a shell. - Some extra whitespace characters need quoting in Cygwin programs, + Some extra whitespace characters need quoting in Cygwin/MSYS programs, so this list is conditionally modified below. */ char *sepchars = " \t*?"; - /* This is for native w32 apps; modified below for Cygwin apps. */ + /* This is for native w32 apps; modified below for Cygwin/MSUS apps. */ char escape_char = '\\'; char cmdname_a[MAX_PATH]; @@ -1777,15 +1792,17 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) cmdname = cmdname_a; argv[0] = cmdname; - /* Determine whether program is a 16-bit DOS executable, or a 32-bit Windows - executable that is implicitly linked to the Cygnus dll (implying it - was compiled with the Cygnus GNU toolchain and hence relies on - cygwin.dll to parse the command line - we use this to decide how to - escape quote chars in command line args that must be quoted). + /* Determine whether program is a 16-bit DOS executable, or a 32-bit + Windows executable that is implicitly linked to the Cygnus or + MSYS dll (implying it was compiled with the Cygnus/MSYS GNU + toolchain and hence relies on cygwin.dll or MSYS DLL to parse the + command line - we use this to decide how to escape quote chars in + command line args that must be quoted). Also determine whether it is a GUI app, so that we don't hide its initial window unless specifically requested. */ - w32_executable_type (cmdname, &is_dos_app, &is_cygnus_app, &is_gui_app); + w32_executable_type (cmdname, &is_dos_app, &is_cygnus_app, &is_msys_app, + &is_gui_app); /* On Windows 95, if cmdname is a DOS app, we invoke a helper application to start it by specifying the helper app as cmdname, @@ -1845,10 +1862,10 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) if (INTEGERP (Vw32_quote_process_args)) escape_char = XINT (Vw32_quote_process_args); else - escape_char = is_cygnus_app ? '"' : '\\'; + escape_char = (is_cygnus_app || is_msys_app) ? '"' : '\\'; } - /* Cygwin apps needs quoting a bit more often. */ + /* Cygwin/MSYS apps need quoting a bit more often. */ if (escape_char == '"') sepchars = "\r\n\t\f '"; @@ -1866,7 +1883,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) for ( ; *p; p++) { if (escape_char == '"' && *p == '\\') - /* If it's a Cygwin app, \ needs to be escaped. */ + /* If it's a Cygwin/MSYS app, \ needs to be escaped. */ arglen++; else if (*p == '"') { @@ -2947,6 +2964,59 @@ If successful, the return value is t, otherwise nil. */) return result; } +DEFUN ("w32-application-type", Fw32_application_type, + Sw32_application_type, 1, 1, 0, + doc: /* Return the type of an MS-Windows PROGRAM. + +Knowing the type of an executable could be useful for formatting +file names passed to it or for quoting its command-line arguments. + +PROGRAM should specify an executable file, including the extension. + +The value is one of the following: + +`dos' -- a DOS .com program or some other non-PE executable +`cygwin' -- a Cygwin program that depends on Cygwin DLL +`msys' -- an MSYS 1.x or MSYS2 program +`w32-native' -- a native Windows application +`unknown' -- a file that doesn't exist, or cannot be open, or whose + name is not encodable in the current ANSI codepage. + +Note that for .bat and .cmd batch files the function returns the type +of their command interpreter, as specified by the \"COMSPEC\" +environment variable. + +This function returns `unknown' for programs whose file names +include characters not supported by the current ANSI codepage, as +such programs cannot be invoked by Emacs anyway. */) + (Lisp_Object program) +{ + int is_dos_app, is_cygwin_app, is_msys_app, dummy; + Lisp_Object encoded_progname; + char *progname, progname_a[MAX_PATH]; + + program = Fexpand_file_name (program, Qnil); + encoded_progname = ENCODE_FILE (program); + progname = SDATA (encoded_progname); + unixtodos_filename (progname); + filename_to_ansi (progname, progname_a); + /* Reject file names that cannot be encoded in the current ANSI + codepage. */ + if (_mbspbrk (progname_a, "?")) + return Qunknown; + + if (w32_executable_type (progname_a, &is_dos_app, &is_cygwin_app, + &is_msys_app, &dummy) != 0) + return Qunknown; + if (is_dos_app) + return Qdos; + if (is_cygwin_app) + return Qcygwin; + if (is_msys_app) + return Qmsys; + return Qw32_native; +} + #ifdef HAVE_LANGINFO_CODESET /* Emulation of nl_langinfo. Used in fns.c:Flocale_info. */ char * @@ -3541,6 +3611,9 @@ syms_of_ntproc (void) { DEFSYM (Qhigh, "high"); DEFSYM (Qlow, "low"); + DEFSYM (Qcygwin, "cygwin"); + DEFSYM (Qmsys, "msys"); + DEFSYM (Qw32_native, "w32-native"); defsubr (&Sw32_has_winsock); defsubr (&Sw32_unload_winsock); @@ -3548,6 +3621,7 @@ syms_of_ntproc (void) defsubr (&Sw32_short_file_name); defsubr (&Sw32_long_file_name); defsubr (&Sw32_set_process_priority); + defsubr (&Sw32_application_type); defsubr (&Sw32_get_locale_info); defsubr (&Sw32_get_current_locale_id); defsubr (&Sw32_get_default_locale_id); -- 2.39.2