From: Eli Zaretskii Date: Fri, 6 Dec 2013 15:55:08 +0000 (+0200) Subject: Converted spawnve, but not tested the result yet. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~446^2~21 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=17788cb3da557d2d5c2dda8f7dedb80999a48242;p=emacs.git Converted spawnve, but not tested the result yet. --- diff --git a/src/unexw32.c b/src/unexw32.c index 5320ec1e371..3dfce22d757 100644 --- a/src/unexw32.c +++ b/src/unexw32.c @@ -120,6 +120,8 @@ _start (void) /* File handling. */ +/* Implementation note: this and the next functions work with ANSI + codepage encoded file names! */ int open_input_file (file_data *p_file, char *filename) { @@ -128,8 +130,8 @@ open_input_file (file_data *p_file, char *filename) void *file_base; unsigned long size, upper_size; - file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + file = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (file == INVALID_HANDLE_VALUE) return FALSE; @@ -166,9 +168,9 @@ open_output_file (file_data *p_file, char *filename, unsigned long size) creating it, all the emacs-XX.YY.ZZ.nn.exe end up being hard links to the same file, which defeats the purpose of these hard links: being able to run previous builds. */ - DeleteFile (filename); - file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + DeleteFileA (filename); + file = CreateFileA (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (file == INVALID_HANDLE_VALUE) return FALSE; @@ -722,7 +724,7 @@ void unexec (const char *new_name, const char *old_name) { file_data in_file, out_file; - char out_filename[MAX_PATH], in_filename[MAX_PATH]; + char out_filename[MAX_PATH], in_filename[MAX_PATH], new_name_a[MAX_PATH]; unsigned long size; char *p; char *q; @@ -738,13 +740,14 @@ unexec (const char *new_name, const char *old_name) *p = '/'; strcpy (out_filename, in_filename); + filename_to_ansi (new_name, new_name_a); /* Change the base of the output filename to match the requested name. */ if ((p = strrchr (out_filename, '/')) == NULL) abort (); /* The filenames have already been expanded, and will be in Unix format, so it is safe to expect an absolute name. */ - if ((q = strrchr (new_name, '/')) == NULL) + if ((q = strrchr (new_name_a, '/')) == NULL) abort (); strcpy (p, q); diff --git a/src/w32proc.c b/src/w32proc.c index de4e9103173..76d8bb19cf8 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -30,6 +30,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include /* must include CRT headers *before* config.h */ #include @@ -1056,9 +1057,10 @@ reader_thread (void *arg) return 0; } -/* To avoid Emacs changing directory, we just record here the directory - the new process should start in. This is set just before calling - sys_spawnve, and is not generally valid at any other time. */ +/* To avoid Emacs changing directory, we just record here the + directory the new process should start in. This is set just before + calling sys_spawnve, and is not generally valid at any other time. + Note that this directory's name is UTF-8 encoded. */ static char * process_dir; static BOOL @@ -1071,7 +1073,8 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app, SECURITY_DESCRIPTOR sec_desc; #endif DWORD flags; - char dir[ MAXPATHLEN ]; + char dir[ MAX_PATH ]; + char *p; if (cp == NULL) emacs_abort (); @@ -1101,16 +1104,22 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app, sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */; sec_attrs.bInheritHandle = FALSE; - strcpy (dir, process_dir); - unixtodos_filename (dir); + filename_to_ansi (process_dir, dir); + /* Can't use unixtodos_filename here, since that needs its file name + argument encoded in UTF-8. OTOH, process_dir, which _is_ in + UTF-8, points, to the directory computed by our caller, and we + don't want to modify that, either. */ + for (p = dir; *p; p = CharNextA (p)) + if (*p == '/') + *p = '\\'; flags = (!NILP (Vw32_start_process_share_console) ? CREATE_NEW_PROCESS_GROUP : CREATE_NEW_CONSOLE); if (NILP (Vw32_start_process_inherit_error_mode)) flags |= CREATE_DEFAULT_ERROR_MODE; - if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE, - flags, env, dir, &start, &cp->procinfo)) + if (!CreateProcessA (exe, cmdline, &sec_attrs, NULL, TRUE, + flags, env, dir, &start, &cp->procinfo)) goto EH_Fail; cp->pid = (int) cp->procinfo.dwProcessId; @@ -1371,6 +1380,8 @@ waitpid (pid_t pid, int *status, int options) # define IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER #endif +/* Implementation note: This function works with file names encoded in + the current ANSI codepage. */ static void w32_executable_type (char * filename, int * is_dos_app, @@ -1561,6 +1572,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) char *sepchars = " \t*?"; /* This is for native w32 apps; modified below for Cygwin apps. */ char escape_char = '\\'; + char cmdname_a[MAX_PATH]; /* We don't care about the other modes */ if (mode != _P_NOWAIT) @@ -1569,12 +1581,15 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) return -1; } - /* Handle executable names without an executable suffix. */ - program = build_string (cmdname); - if (NILP (Ffile_executable_p (program))) + /* Handle executable names without an executable suffix. The caller + already searched exec-path and verified the file is executable, + but start-process doesn't do that for file names that are already + absolute. So we double-check this here, just in case. */ + if (faccessat (AT_FDCWD, cmdname, X_OK, AT_EACCESS) != 0) { struct gcpro gcpro1; + program = build_string (cmdname); full = Qnil; GCPRO1 (program); openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK)); @@ -1584,12 +1599,27 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) errno = EINVAL; return -1; } - program = full; + program = ENCODE_FILE (full); + cmdname = SDATA (program); } /* make sure argv[0] and cmdname are both in DOS format */ - cmdname = SDATA (program); unixtodos_filename (cmdname); + /* argv[0] was encoded by caller using ENCODE_FILE, so it is in + UTF-8. All the other arguments are encoded by ENCODE_SYSTEM or + some such, and are in some ANSI codepage. We need to have + argv[0] encoded in ANSI codepage. */ + filename_to_ansi (cmdname, cmdname_a); + /* We explicitly require that the command's file name be encodable + in the current ANSI codepage, because we will be invoking it via + the ANSI APIs. */ + if (_mbspbrk (cmdname_a, "?")) + { + errno = ENOENT; + return -1; + } + /* From here on, CMDNAME is an ANSI-encoded string. */ + cmdname = cmdname_a argv[0] = cmdname; /* Determine whether program is a 16-bit DOS executable, or a 32-bit Windows @@ -1607,7 +1637,9 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) while leaving the real app name as argv[0]. */ if (is_dos_app) { - cmdname = alloca (MAXPATHLEN); + char *p; + + cmdname = alloca (MAX_PATH); if (egetenv ("CMDPROXY")) strcpy (cmdname, egetenv ("CMDPROXY")); else @@ -1615,7 +1647,12 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) strcpy (cmdname, SDATA (Vinvocation_directory)); strcat (cmdname, "cmdproxy.exe"); } - unixtodos_filename (cmdname); + + /* Can't use unixtodos_filename here, since that needs its file + name argument encoded in UTF-8. */ + for (p = cmdname; *p; p = CharNextA (p)) + if (*p == '/') + *p = '\\'; } /* we have to do some conjuring here to put argv and envp into the