From e2403327e9913bbcbd515f9c38b8f4e26fb9b0d9 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Thu, 30 Jul 1998 20:54:47 +0000 Subject: GNU make release 3.77. --- w32/subproc/NMakefile | 3 +- w32/subproc/build.bat | 4 +- w32/subproc/sub_proc.c | 345 ++++++++++++++++++++++++++++--------------------- 3 files changed, 204 insertions(+), 148 deletions(-) (limited to 'w32/subproc') diff --git a/w32/subproc/NMakefile b/w32/subproc/NMakefile index ab11d96..f187827 100644 --- a/w32/subproc/NMakefile +++ b/w32/subproc/NMakefile @@ -27,7 +27,7 @@ CC = cl OUTDIR=. MAKEFILE=NMakefile -CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS -I. -I../include +CFLAGS_any = /nologo /MT /W3 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS -I. -I../include -I../.. CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/ CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/ @@ -40,6 +40,7 @@ Debug: clean: rmdir /s /q WinRel WinDebug + erase *.pdb $(OUTDIR): if not exist .\$@\nul mkdir .\$@ diff --git a/w32/subproc/build.bat b/w32/subproc/build.bat index 955f6d5..26ab1cb 100644 --- a/w32/subproc/build.bat +++ b/w32/subproc/build.bat @@ -1,10 +1,10 @@ if not exist .\WinDebug\nul mkdir .\WinDebug cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c -cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c +cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c cl.exe /nologo /MT /W3 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib .\WinDebug/misc.obj .\WinDebug/sub_proc.obj .\WinDebug/w32err.obj if not exist .\WinRel\nul mkdir .\WinRel cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c -cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c +cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c cl.exe /nologo /MT /W3 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib .\WinRel/misc.obj .\WinRel/sub_proc.obj .\WinRel/w32err.obj diff --git a/w32/subproc/sub_proc.c b/w32/subproc/sub_proc.c index 4166d34..281c81c 100644 --- a/w32/subproc/sub_proc.c +++ b/w32/subproc/sub_proc.c @@ -6,6 +6,7 @@ #include "sub_proc.h" #include "proc.h" #include "w32err.h" +#include "config.h" static char *make_command_line( char *shell_name, char *exec_path, char **argv); @@ -889,170 +890,224 @@ process_cleanup( /* - * Try to protect against WINDOWS32 argument munging. This function takes - * an argv vector and outputs a 'protected' string as a return - * value. The return code can be safely passed to CreateProcess(). + * Description: + * Create a command line buffer to pass to CreateProcess + * + * Returns: the buffer or NULL for failure + * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ... + * Otherwise: argv[0] argv[1] argv[2] ... * - * The caller should free the return value. + * Notes/Dependencies: + * CreateProcess does not take an argv, so this command creates a + * command line for the executable. */ -#define TRACE(x) -static char *fix_command_line(char *args[]) +static char * +make_command_line( char *shell_name, char *full_exec_path, char **argv) { - int i; - char *narg; - char *nargp; - char *p; - char *q; - int alloc_len = 0; - - for (i = 0; args[i]; i++) - alloc_len += ((strlen(args[i]) * 2) + 1); - /* account for possible enclosing quotes and null termination */ - alloc_len += 3; - - nargp = narg = malloc(alloc_len); - - for (i = 0; args[i]; i++) { - p = args[i]; - TRACE(("original arg: %s\n", p)); - - if (*p == '\0') { - *nargp++ = '"'; - *nargp++ = '"'; - *nargp = '\0'; - TRACE(("empty string arg: %s\n", nargp-2)); - } else if (strpbrk(p, "\" \t")) { - /* point to end of copy buffer */ - q = narg; - q += (alloc_len-1); - *q-- = '\0'; /* ensure null terminated string */ - *q-- = '"'; /* terminating quote of argument */ - - /* point to end of the input string */ - p = args[i]; - p += strlen(args[i]); - p--; - - /* - * Because arg is quoted, escape any backslashes - * that might occur at the end of the string which - * proceed the closing quote. - * Example: - * foo c:\ - * Becomes: - * "foo c:\\" - */ - while (*p == '\\') - *q-- = *p--, *q-- = '\\'; + int argc = 0; + char** argvi; + int* enclose_in_quotes = NULL; + int* enclose_in_quotes_i; + unsigned int bytes_required = 0; + char* command_line; + char* command_line_i; + + if (shell_name && full_exec_path) { + bytes_required + = strlen(shell_name) + 1 + strlen(full_exec_path); + /* + * Skip argv[0] if any, when shell_name is given. + */ + if (*argv) argv++; + /* + * Add one for the intervening space. + */ + if (*argv) bytes_required++; + } + + argvi = argv; + while (*(argvi++)) argc++; + + if (argc) { + enclose_in_quotes = (int*) calloc(1, argc * sizeof(int)); + + if (!enclose_in_quotes) { + return NULL; + } + } - /* copy the string in reverse */ - while (p >= args[i]) { - /* copy the character */ - *q-- = *p--; + /* We have to make one pass through each argv[i] to see if we need + * to enclose it in ", so we might as well figure out how much + * memory we'll need on the same pass. + */ - /* - * Escape any double quote found. Also escape - * each backslash preceding the double quote. + argvi = argv; + enclose_in_quotes_i = enclose_in_quotes; + while(*argvi) { + char* p = *argvi; + unsigned int backslash_count = 0; + + /* + * We have to enclose empty arguments in ". + */ + if (!(*p)) *enclose_in_quotes_i = 1; + + while(*p) { + switch (*p) { + case '\"': + /* + * We have to insert a backslash for each " + * and each \ that precedes the ". */ - if (*(p+1) == '"') { - *q-- = '\\'; - if (p >= args[i] && *p == '\\') - while (p >= args[i] && *p == '\\') - *q-- = *p--, *q-- = '\\'; - } + bytes_required += (backslash_count + 1); + backslash_count = 0; + break; + + case '\\': + backslash_count++; + break; + /* + * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress + * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so + * that argv in always equals argv out. This was removed. Say you have + * such a program named glob.exe. You enter + * glob '*' + * at the sh command prompt. Obviously the intent is to make glob do the + * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?', + * then the command line that glob would see would be + * glob "*" + * and the _setargv in SETARGV.OBJ would _not_ expand the *. + */ + case ' ': + case '\t': + *enclose_in_quotes_i = 1; + /* fall through */ + + default: + backslash_count = 0; + break; } + + /* + * Add one for each character in argv[i]. + */ + bytes_required++; - /* finish quoting arg, q now points to complete arg */ - *q = '"'; + p++; + } - /* rejustify */ - memmove(nargp, q, strlen(q) + 1); - TRACE(("arg with white space or doublequotes: %s\n", nargp)); - nargp += strlen(nargp); - } else { - /* just copy the argument, no protection needed */ - strcpy(nargp, args[i]); - TRACE(("plain arg: %s\n", nargp)); - nargp += strlen(nargp); + if (*enclose_in_quotes_i) { + /* + * Add one for each enclosing ", + * and one for each \ that precedes the + * closing ". + */ + bytes_required += (backslash_count + 2); } + + /* + * Add one for the intervening space. + */ + if (*(++argvi)) bytes_required++; + enclose_in_quotes_i++; + } - /* separate arguments with spaces (if more args to gather) */ - if (args[i+1]) - *nargp++ = ' '; - *nargp = '\0'; - } /* end for */ + /* + * Add one for the terminating NULL. + */ + bytes_required++; - /* NULL terminate the arg list */ - *nargp = '\0'; + command_line = (char*) malloc(bytes_required); - return (narg); -} -#undef TRACE + if (!command_line) { + if (enclose_in_quotes) free(enclose_in_quotes); + return NULL; + } -/* - * Description: - * Create a command line buffer to pass to CreateProcess - * - * Returns: the buffer or NULL for failure - * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ... - * Otherwise: argv[0] argv[1] argv[2] ... - * - * Notes/Dependencies: - * CreateProcess does not take an argv, so this command creates a - * command line for the executable. - */ + command_line_i = command_line; -static char * -make_command_line( char *shell_name, char *exec_path, char **argv) -{ - char** nargv; - char* buf; - int i; - char** shargv = NULL; - char* p = NULL; - char* q = NULL; - int j = 0; - - if (shell_name) { - /* handle things like: #!/bin/sh -x */ - - /* count tokens */ - q = strdup(shell_name); - for (j = 0, p = q; (p = strtok(p, " \t")) != NULL; p = NULL, j++); - free(q); - - /* copy tokens */ - q = strdup(shell_name); - shargv = (char **) malloc((j+1) * sizeof (char *)); - for (j = 0, p = q; (p = strtok(p, " \t")) != NULL; p = NULL, j++) - shargv[j] = strdup(p); - shargv[j] = NULL; - free(q); - - /* create argv */ - for (i = 0; argv[i]; i++); - i += (j+1); - nargv = (char **) malloc(i * sizeof (char *)); - for (i = 0; shargv[i] != NULL; i++) - nargv[i] = shargv[i]; - for (j = 0; argv[j]; j++, i++) - nargv[i] = argv[j]; - nargv[i] = NULL; - } else - nargv = argv; + if (shell_name && full_exec_path) { + while(*shell_name) { + *(command_line_i++) = *(shell_name++); + } - /* create string suitable for CreateProcess() */ - buf = fix_command_line(nargv); + *(command_line_i++) = ' '; - if (shell_name) { - for (j = 0; shargv[j]; j++) - free(shargv[j]); - free(shargv); - free(nargv); + while(*full_exec_path) { + *(command_line_i++) = *(full_exec_path++); + } + + if (*argv) { + *(command_line_i++) = ' '; + } } - - return buf; + + argvi = argv; + enclose_in_quotes_i = enclose_in_quotes; + + while(*argvi) { + char* p = *argvi; + unsigned int backslash_count = 0; + + if (*enclose_in_quotes_i) { + *(command_line_i++) = '\"'; + } + + while(*p) { + if (*p == '\"') { + /* + * We have to insert a backslash for the " + * and each \ that precedes the ". + */ + backslash_count++; + + while(backslash_count) { + *(command_line_i++) = '\\'; + backslash_count--; + }; + + } else if (*p == '\\') { + backslash_count++; + } else { + backslash_count = 0; + } + + /* + * Copy the character. + */ + *(command_line_i++) = *(p++); + } + + if (*enclose_in_quotes_i) { + /* + * Add one \ for each \ that precedes the + * closing ". + */ + while(backslash_count--) { + *(command_line_i++) = '\\'; + }; + + *(command_line_i++) = '\"'; + } + + /* + * Append an intervening space. + */ + if (*(++argvi)) { + *(command_line_i++) = ' '; + } + + enclose_in_quotes_i++; + } + + /* + * Append the terminating NULL. + */ + *command_line_i = '\0'; + + if (enclose_in_quotes) free(enclose_in_quotes); + return command_line; } /* -- cgit v1.2.3