зеркало из https://github.com/microsoft/git.git
Merge branch 'sk/mingw-unicode-spawn-args'
* sk/mingw-unicode-spawn-args: Win32: Unicode arguments (incoming) Win32: Unicode arguments (outgoing) MinGW: disable CRT command line globbing Win32: fix potential multi-threading issue Win32: simplify internal mingw_spawn* APIs Win32: let mingw_execve() return an int
This commit is contained in:
Коммит
cb9cd515ee
|
@ -441,7 +441,7 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
|
|||
static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
|
||||
{
|
||||
int namelen;
|
||||
static char alt_name[PATH_MAX];
|
||||
char alt_name[PATH_MAX];
|
||||
|
||||
if (!do_lstat(follow, file_name, buf))
|
||||
return 0;
|
||||
|
@ -831,9 +831,10 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
|||
const char *dir,
|
||||
int prepend_cmd, int fhin, int fhout, int fherr)
|
||||
{
|
||||
STARTUPINFO si;
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION pi;
|
||||
struct strbuf envblk, args;
|
||||
wchar_t wcmd[MAX_PATH], wdir[MAX_PATH], *wargs;
|
||||
unsigned flags;
|
||||
BOOL ret;
|
||||
|
||||
|
@ -869,6 +870,11 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
|||
si.hStdOutput = winansi_get_osfhandle(fhout);
|
||||
si.hStdError = winansi_get_osfhandle(fherr);
|
||||
|
||||
if (xutftowcs_path(wcmd, cmd) < 0)
|
||||
return -1;
|
||||
if (dir && xutftowcs_path(wdir, dir) < 0)
|
||||
return -1;
|
||||
|
||||
/* concatenate argv, quoting args as we go */
|
||||
strbuf_init(&args, 0);
|
||||
if (prepend_cmd) {
|
||||
|
@ -886,6 +892,10 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
|||
free(quoted);
|
||||
}
|
||||
|
||||
wargs = xmalloc((2 * args.len + 1) * sizeof(wchar_t));
|
||||
xutftowcs(wargs, args.buf, 2 * args.len + 1);
|
||||
strbuf_release(&args);
|
||||
|
||||
if (env) {
|
||||
int count = 0;
|
||||
char **e, **sorted_env;
|
||||
|
@ -907,12 +917,12 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
|||
}
|
||||
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
ret = CreateProcess(cmd, args.buf, NULL, NULL, TRUE, flags,
|
||||
env ? envblk.buf : NULL, dir, &si, &pi);
|
||||
ret = CreateProcessW(wcmd, wargs, NULL, NULL, TRUE, flags,
|
||||
env ? envblk.buf : NULL, dir ? wdir : NULL, &si, &pi);
|
||||
|
||||
if (env)
|
||||
strbuf_release(&envblk);
|
||||
strbuf_release(&args);
|
||||
free(wargs);
|
||||
|
||||
if (!ret) {
|
||||
errno = ENOENT;
|
||||
|
@ -941,10 +951,9 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
|||
return (pid_t)pi.dwProcessId;
|
||||
}
|
||||
|
||||
static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
|
||||
int prepend_cmd)
|
||||
static pid_t mingw_spawnv(const char *cmd, const char **argv, int prepend_cmd)
|
||||
{
|
||||
return mingw_spawnve_fd(cmd, argv, env, NULL, prepend_cmd, 0, 1, 2);
|
||||
return mingw_spawnve_fd(cmd, argv, environ, NULL, prepend_cmd, 0, 1, 2);
|
||||
}
|
||||
|
||||
pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
|
||||
|
@ -986,7 +995,7 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
|
|||
return pid;
|
||||
}
|
||||
|
||||
static int try_shell_exec(const char *cmd, char *const *argv, char **env)
|
||||
static int try_shell_exec(const char *cmd, char *const *argv)
|
||||
{
|
||||
const char *interpr = parse_interpreter(cmd);
|
||||
char **path;
|
||||
|
@ -1004,7 +1013,7 @@ static int try_shell_exec(const char *cmd, char *const *argv, char **env)
|
|||
argv2 = xmalloc(sizeof(*argv) * (argc+1));
|
||||
argv2[0] = (char *)cmd; /* full path to the script file */
|
||||
memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
|
||||
pid = mingw_spawnve(prog, argv2, env, 1);
|
||||
pid = mingw_spawnv(prog, argv2, 1);
|
||||
if (pid >= 0) {
|
||||
int status;
|
||||
if (waitpid(pid, &status, 0) < 0)
|
||||
|
@ -1019,19 +1028,20 @@ static int try_shell_exec(const char *cmd, char *const *argv, char **env)
|
|||
return pid;
|
||||
}
|
||||
|
||||
static void mingw_execve(const char *cmd, char *const *argv, char *const *env)
|
||||
int mingw_execv(const char *cmd, char *const *argv)
|
||||
{
|
||||
/* check if git_command is a shell script */
|
||||
if (!try_shell_exec(cmd, argv, (char **)env)) {
|
||||
if (!try_shell_exec(cmd, argv)) {
|
||||
int pid, status;
|
||||
|
||||
pid = mingw_spawnve(cmd, (const char **)argv, (char **)env, 0);
|
||||
pid = mingw_spawnv(cmd, (const char **)argv, 0);
|
||||
if (pid < 0)
|
||||
return;
|
||||
return -1;
|
||||
if (waitpid(pid, &status, 0) < 0)
|
||||
status = 255;
|
||||
exit(status);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mingw_execvp(const char *cmd, char *const *argv)
|
||||
|
@ -1040,7 +1050,7 @@ int mingw_execvp(const char *cmd, char *const *argv)
|
|||
char *prog = path_lookup(cmd, path, 0);
|
||||
|
||||
if (prog) {
|
||||
mingw_execve(prog, argv, environ);
|
||||
mingw_execv(prog, argv);
|
||||
free(prog);
|
||||
} else
|
||||
errno = ENOENT;
|
||||
|
@ -1049,12 +1059,6 @@ int mingw_execvp(const char *cmd, char *const *argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int mingw_execv(const char *cmd, char *const *argv)
|
||||
{
|
||||
mingw_execve(cmd, argv, environ);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mingw_kill(pid_t pid, int sig)
|
||||
{
|
||||
if (pid > 0 && sig == SIGTERM) {
|
||||
|
@ -1933,10 +1937,54 @@ int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable MSVCRT command line wildcard expansion (__getmainargs called from
|
||||
* mingw startup code, see init.c in mingw runtime).
|
||||
*/
|
||||
int _CRT_glob = 0;
|
||||
|
||||
typedef struct {
|
||||
int newmode;
|
||||
} _startupinfo;
|
||||
|
||||
extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob,
|
||||
_startupinfo *si);
|
||||
|
||||
static NORETURN void die_startup()
|
||||
{
|
||||
fputs("fatal: not enough memory for initialization", stderr);
|
||||
exit(128);
|
||||
}
|
||||
|
||||
void mingw_startup()
|
||||
{
|
||||
/* copy executable name to argv[0] */
|
||||
__argv[0] = xstrdup(_pgmptr);
|
||||
int i, len, maxlen, argc;
|
||||
char *buffer;
|
||||
wchar_t **wenv, **wargv;
|
||||
_startupinfo si;
|
||||
|
||||
/* get wide char arguments and environment */
|
||||
si.newmode = 0;
|
||||
if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0)
|
||||
die_startup();
|
||||
|
||||
/* determine size of argv and environ conversion buffer */
|
||||
maxlen = wcslen(_wpgmptr);
|
||||
for (i = 1; i < argc; i++)
|
||||
maxlen = max(maxlen, wcslen(wargv[i]));
|
||||
|
||||
/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
|
||||
maxlen = 3 * maxlen + 1;
|
||||
buffer = xmalloc(maxlen);
|
||||
|
||||
/* convert command line arguments and environment to UTF-8 */
|
||||
len = xwcstoutf(buffer, _wpgmptr, maxlen);
|
||||
__argv[0] = xmemdupz(buffer, len);
|
||||
for (i = 1; i < argc; i++) {
|
||||
len = xwcstoutf(buffer, wargv[i], maxlen);
|
||||
__argv[i] = xmemdupz(buffer, len);
|
||||
}
|
||||
free(buffer);
|
||||
|
||||
/* initialize critical section for waitpid pinfo_t list */
|
||||
InitializeCriticalSection(&pinfo_cs);
|
||||
|
|
Загрузка…
Ссылка в новой задаче