You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2010/01/19 20:43:54 UTC
svn commit: r900929 - in /commons/sandbox/runtime/trunk/src/main/native:
include/acr_args.h include/acr_port.h os/win32/exec.c os/win32/subproc.c
port/shquote.c shared/args.c support/win32/wsuexec.c
Author: mturk
Date: Tue Jan 19 19:43:54 2010
New Revision: 900929
URL: http://svn.apache.org/viewvc?rev=900929&view=rev
Log:
Rewrite the argument processing code for win32
Modified:
commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h
commons/sandbox/runtime/trunk/src/main/native/include/acr_port.h
commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/subproc.c
commons/sandbox/runtime/trunk/src/main/native/port/shquote.c
commons/sandbox/runtime/trunk/src/main/native/shared/args.c
commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h?rev=900929&r1=900928&r2=900929&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h Tue Jan 19 19:43:54 2010
@@ -85,6 +85,10 @@
char *const *params,
char ***argv);
+/**
+ * This function provides a way to parse a generic argument string
+ * Unicode version of ACR_StringToArgv
+ */
ACR_DECLARE(int) ACR_StringToArgvW(const wchar_t *cmdline,
int nparams,
const wchar_t *const *params,
@@ -124,13 +128,13 @@
* Sort the array of string using case insensitive order
* @param pointer to char array to sort.
*/
-ACR_DECLARE(void) ACR_ArgsSortA(char *const **args);
+ACR_DECLARE(void) ACR_StrArraySortA(char *const **args);
/**
* Sort the array of wide string using case insensitive order
* @param pointer to the wide char array to sort.
*/
-ACR_DECLARE(void) ACR_ArgsSortW(wchar_t *const **args);
+ACR_DECLARE(void) ACR_StrArraySortW(wchar_t *const **args);
#ifdef __cplusplus
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_port.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_port.h?rev=900929&r1=900928&r2=900929&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_port.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_port.h Tue Jan 19 19:43:54 2010
@@ -133,7 +133,6 @@
size_t shquote(const char *, char *, size_t);
size_t shquotev(int, char * const *, char *, size_t);
#endif
-size_t strquote(const char *, char *, size_t);
size_t wcsquote(const wchar_t *, wchar_t *, size_t);
size_t wcsquotev(int argc, wchar_t * const *, wchar_t *, size_t);
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c?rev=900929&r1=900928&r2=900929&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c Tue Jan 19 19:43:54 2010
@@ -187,7 +187,7 @@
if (envp) {
/* Environmet is supposed to be sorted
*/
- ACR_ArgsSortW(&envp);
+ ACR_StrArraySortW(&envp);
envb = ACR_ArrayToMszStrW(envp);
if (!envb) {
rc = ACR_ENOMEM;
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/subproc.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/subproc.c?rev=900929&r1=900928&r2=900929&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/subproc.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/subproc.c Tue Jan 19 19:43:54 2010
@@ -79,6 +79,29 @@
*/
extern wchar_t *dll_dos_modname;
+static wchar_t **CommandLineToArrayW(const wchar_t *cmdline, int *argc)
+{
+ int i, rc = 0;
+ wchar_t **argv;
+ wchar_t **args;
+
+ if ((argv = CommandLineToArgvW(cmdline, argc)) == NULL)
+ return NULL;
+ args = s_malloc(wchar_t *, *argc + 1);
+ if (!args) {
+ rc = ACR_ENOMEM;
+ goto cleanup;
+ }
+ for (i = 0; i < *argc; i++)
+ args[i] = x_wcsdup(argv[i]);
+ args[i] = NULL;
+
+cleanup:
+ LocalFree(argv);
+ ACR_SET_OS_ERROR(rc);
+ return args;
+}
+
/*
* Instead in Makefile exports could go here as well
*
@@ -142,8 +165,8 @@
goto cleanup;
}
- argc = ACR_StringToArgvW(GetCommandLineW(), 0, NULL, &args);
- if (argc < 0) {
+ args = CommandLineToArrayW(GetCommandLineW(), &argc);
+ if (args == NULL) {
rc = ACR_GET_OS_ERROR();
goto cleanup;
}
@@ -843,7 +866,7 @@
if (envp) {
/* Environmet is supposed to be sorted
*/
- ACR_ArgsSortW(&envp);
+ ACR_StrArraySortW(&envp);
envb = ACR_ArrayToMszStrW(envp);
if (!envb) {
rc = ACR_ENOMEM;
Modified: commons/sandbox/runtime/trunk/src/main/native/port/shquote.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/port/shquote.c?rev=900929&r1=900928&r2=900929&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/port/shquote.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/port/shquote.c Tue Jan 19 19:43:54 2010
@@ -200,57 +200,6 @@
/* Just like shquote but surounds the arg by double quotes if
* the arg contains space sharacters
*/
-size_t strquote(const char *arg, char *buf, size_t bufsize)
-{
- char c;
- size_t rv = 0;
- size_t quoted = 0;
- int n;
-
- /* Empty args are skipped */
- if (!*arg) {
- PUTC('\0');
- return 0;
- }
- if (strpbrk(arg, " \t")) {
- quoted = 1;
- }
- if (quoted) {
- PUTC('"');
- }
- for (;;) {
- INCH();
- if (n == 0)
- break;
-
- if (c == '"') {
- PUTC('\\');
- }
- else if (c == '\\') {
- const char *bsp = arg;
- /* Add extra backslash for each backslash
- * followed by double quoute.
- */
- while (*bsp && *bsp == '\\')
- bsp++;
- if (*bsp == '"') {
- PUTC('\\');
- }
-
- }
- PUTC(c);
- arg++;
- }
- if (quoted) {
- PUTC('"');
- }
- /* Put NUL terminator, but don't count the NUL. */
- PUTC('\0');
- rv--;
-
- return rv;
-}
-
size_t wcsquote(const wchar_t *arg, wchar_t *buf, size_t bufsize)
{
wchar_t c;
@@ -280,11 +229,11 @@
else if (c == L'\\') {
const wchar_t *bsp = arg;
/* Add extra backslash for each backslash
- * followed by double quoute.
+ * followed by a double quoute or NUL.
*/
while (*bsp && *bsp == L'\\')
bsp++;
- if (*bsp == L'"') {
+ if (*bsp == L'"' || (*bsp == L'\0' && quoted)) {
PUTC(L'\\');
}
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/args.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/args.c?rev=900929&r1=900928&r2=900929&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/args.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/args.c Tue Jan 19 19:43:54 2010
@@ -790,7 +790,7 @@
return NULL;
}
while (*ap) {
- size_t al = strquote(*ap, NULL, 0);
+ size_t al = shquote(*ap, NULL, 0);
if (al == (size_t) -1) {
ACR_SET_OS_ERROR(ACR_EILSEQ);
return NULL;
@@ -810,7 +810,7 @@
*(cp++) = ' ';
--length;
}
- arglen = strquote(*ap, cp, length);
+ arglen = shquote(*ap, cp, length);
cp += arglen;
length -= arglen;
ap++;
@@ -875,7 +875,7 @@
*((const wchar_t **)arg2));
}
-ACR_DECLARE(void) ACR_ArgsSortA(char *const **args)
+ACR_DECLARE(void) ACR_StrArraySortA(char *const **args)
{
size_t len = 0;
char *const *sa = *args;
@@ -885,7 +885,7 @@
qsort((void *)&args, len, sizeof(char *), _strcompare);
}
-ACR_DECLARE(void) ACR_ArgsSortW(wchar_t *const **args)
+ACR_DECLARE(void) ACR_StrArraySortW(wchar_t *const **args)
{
size_t len = 0;
wchar_t *const *sa = *args;
Modified: commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c?rev=900929&r1=900928&r2=900929&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c Tue Jan 19 19:43:54 2010
@@ -58,61 +58,10 @@
} \
} while (0)
-#define SKIP_WHITESPACEW(C) \
- for ( ; *C == L' ' || *C == L'\t'; ) { \
- C++; \
- };
-
-#define CHECK_QUOTATIONW(C, Q) \
- Q = 0; \
- if (*C == L'"') { \
- Q = 1; \
- C++; \
- } \
- else if (*C == L'\'') { \
- Q = 2; \
- C++; \
- }
-
-/* DETERMINE_NEXTSTRING:
- * At exit, cp will point to one of the following: NULL, SPACE, TAB or QUOTE.
- * NULL implies the argument string has been fully traversed.
+/* List of 'safe' environment variables
+ * for GCI processes
*/
-#define DETERMINE_NEXTSTRINGW(C, Q) \
- for ( ; *C != L'\0'; C++) { \
- if ((*C == L'\\' && (*(C+1) == L' ' || *(C+1) == L'\t' || \
- *(C+1) == L'"' || *(C+1) == L'\''))) { \
- C++; \
- continue; \
- } \
- if ((!Q && (*C == L' ' || *C == L'\t')) \
- || (Q == 1 && *C == L'"') \
- || (Q == 2 && *C == L'\'')) { \
- break; \
- } \
- }
-
-/* REMOVE_ESCAPE_CHARS:
- * Compresses the arg string to remove all of the '\' escape chars.
- * The final argv strings should not have any extra escape chars in it.
- */
-#define REMOVE_ESCAPE_CHARSW(C, D, E) \
- E = 0; \
- while(*D) { \
- if (!E && \
- (*D == L'\\' && (*(D+1) == L' ' || *(D+1) == L'\t' || \
- *(D+1) == L'"' || *(D+1) == L'\''))) { \
- E = 1; \
- } \
- else { \
- E = 0; \
- *C++ = *D; \
- } \
- ++D; \
- } \
- *C = 0
-
-static const wchar_t *const safe_elist[] =
+static const wchar_t *const safe_env_lst[] =
{
/* variable name starts with */
L"HTTP_",
@@ -164,6 +113,35 @@
NULL
};
+#if defined(DEBUG) || defined(_DEBUG)
+static void _dbg_printf(const char *format, ...)
+{
+ char buff[ACR_HBUFF_SIZ];
+ char *bp = buff;
+ char *ep;
+ time_t timevar;
+ struct tm *lt;
+ va_list ap;
+
+ time(&timevar);
+ lt = localtime(&timevar);
+ ep = bp + ACR_HBUFF_SIZ;
+ snprintf(bp, (size_t)(ep - bp),
+ "[%u] [%d-%.2d-%.2d %.2d:%.2d:%.2d] ",
+ GetCurrentThreadId(),
+ lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday,
+ lt->tm_hour, lt->tm_min, lt->tm_sec);
+ bp += strlen(buff);
+ va_start(ap, format);
+ _vsnprintf(bp, (size_t)(ep - bp), format, ap);
+ va_end(ap);
+ OutputDebugStringA(buff);
+}
+#define DBG_PRINTF(x) _dbg_printf x
+#else
+#define DBG_PRINTF(x) //
+#endif
+
static size_t wcsquote(const wchar_t *arg, wchar_t *buf, size_t bufsize)
{
wchar_t c;
@@ -193,11 +171,11 @@
else if (c == L'\\') {
const wchar_t *bsp = arg;
/* Add extra backslash for each backslash
- * followed by double quoute.
+ * followed by a double quoute or NUL.
*/
while (*bsp && *bsp == L'\\')
bsp++;
- if (*bsp == L'"') {
+ if (*bsp == L'"' || (*bsp == L'\0' && quoted)) {
PUTC(L'\\');
}
@@ -215,61 +193,10 @@
return rv;
}
-static wchar_t *wcspbrk_s(const wchar_t *s1, const wchar_t *s2)
-{
- const wchar_t *scanp;
- int inquote = 0;
- int c, sc, pc = *s1;
-
- /* Some early sanity check */
- if (!s1 || !*s1)
- return NULL;
- while ((c = *s1++) != 0) {
- for (scanp = s2; (sc = *scanp++) != L'\0';) {
- if (sc == c && inquote == 0)
- return (wchar_t *)(s1 - 1);
- }
- /* Don't update the previous marker if it was \' already
- * In that case we have escaped single quote.
- */
- if (c == L'\'' && pc != L'\\')
- inquote = !inquote;
- pc = c;
- }
- return NULL;
-}
-
-static wchar_t *getword(wchar_t **line)
-{
- wchar_t *cleaned;
- wchar_t *dirty;
- wchar_t *argp;
- wchar_t *args = *line;
- wchar_t *word;
- int escaped;
- int isquoted;
-
- if (!*args)
- return NULL;
- SKIP_WHITESPACEW(args);
- CHECK_QUOTATIONW(args, isquoted);
- argp = args;
- DETERMINE_NEXTSTRINGW(args, isquoted);
- word = argp;
- if (*args)
- *(args++) = L'\0';
-
- cleaned = dirty = word;
- REMOVE_ESCAPE_CHARSW(cleaned, dirty, escaped);
-
- *line = args;
- return word;
-}
-
/*
* Input string is freed if expansion took place
*/
-static wchar_t *eexpand(wchar_t *str)
+static wchar_t *ExpandEnvStringW(wchar_t *str)
{
if (str == NULL)
return NULL;
@@ -280,25 +207,25 @@
siz = ExpandEnvironmentStringsW(str, NULL, 0);
if (siz) {
- buf = (wchar_t *)malloc(siz * sizeof(wchar_t));
+ buf = s_malloc(wchar_t, siz);
if (buf == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return str;
}
siz = ExpandEnvironmentStringsW(str, buf, siz);
if (siz == 0) {
- free(buf);
+ x_free(buf);
return str;
}
- free(str);
+ x_free(str);
return buf;
}
}
return str;
}
-static wchar_t **mergeargs(const wchar_t *const *argv1,
- const wchar_t *const *argv2)
+static wchar_t **MergeArrays(const wchar_t *const *argv1,
+ const wchar_t *const *argv2)
{
size_t argnum = 0;
wchar_t **dupargv = NULL;
@@ -325,7 +252,7 @@
*/
return NULL;
}
- dupargv = malloc((argnum + 1) * sizeof(wchar_t *));
+ dupargv = s_malloc(wchar_t *, argnum + 1);
if (!dupargv) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
@@ -356,7 +283,7 @@
return dupargv;
}
-static wchar_t *argstostr(const wchar_t *const *argv)
+static wchar_t *ArgvToCommandLineW(const wchar_t *const *argv)
{
size_t argnum = 0;
size_t length = 0;
@@ -369,7 +296,7 @@
return NULL;
}
while (*ap) {
- size_t al = (*ap, NULL, 0);
+ size_t al = wcsquote(*ap, NULL, 0);
if (al == (size_t) -1) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
@@ -379,7 +306,7 @@
}
if (length == 0)
return NULL;
- args = cp = malloc((length + 1) * sizeof(wchar_t));
+ args = cp = s_malloc(wchar_t, length + 1);
if (!args) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
@@ -400,101 +327,28 @@
return args;
}
-static int strtoargs(const wchar_t *cmdline,
- int nparams,
- const wchar_t *const *params,
- wchar_t ***argv)
-{
- const wchar_t *cp;
- wchar_t *args;
- wchar_t *cmds;
- int isquoted, numargs, argnum, argidx = 0;
-
- SKIP_WHITESPACEW(cmdline);
- cp = cmdline;
-
- /* This is ugly and expensive, but if anyone wants to figure a
- * way to support any number of args without counting and
- * allocating, please go ahead and change the code.
- *
- * Must account for the trailing NULL arg.
- */
- numargs = 1;
- while (*cp != L'\0') {
- CHECK_QUOTATIONW(cp, isquoted);
- DETERMINE_NEXTSTRINGW(cp, isquoted);
- if (*cp != L'\0') {
- cp++;
- }
- numargs++;
- SKIP_WHITESPACEW(cp);
- }
- if (!argv) {
- /* We are only interested in the number of arguments
- */
- return numargs;
- }
- cmds = wcsdup(cmdline);
- if (!cmds) {
- return -1;
- }
- *argv = calloc(numargs, sizeof(wchar_t *));
- if (!*argv) {
- x_free(cmds);
- return -1;
- }
- args = cmds;
- /* determine first argument */
- for (argnum = 0; argnum < (numargs-1); argnum++) {
- wchar_t *argument = getword(&args);
+static wchar_t **CommandLineToArrayW(const wchar_t *cmdline, int *argc)
+{
+ int i, rc = 0;
+ wchar_t **argv;
+ wchar_t **args;
- if (!argument)
- break;
- if (*argument == L'%' || *argument == L'$') {
- cp = argument + 1;
- if (*cp == L'*' && *(cp + 1) == L'\0') {
- if (argidx >= nparams)
- break;
- argument = wcsdup(params[argidx++]);
- for (; argidx < nparams; argidx++) {
- wchar_t *as = malloc((wcslen(argument) + wcslen(params[argidx]) + 2) * sizeof(wchar_t));
- wcscpy(as, argument);
- wcscat(as, L" ");
- wcscat(as, params[argidx]);
- free(argument);
- argument = as;
- }
- (*argv)[argnum] = eexpand(argument);
- continue;
- }
- else if (iswdigit(*cp) && *(cp + 1) == L'\0') {
- argidx = *cp - L'0';
- if (argidx == 0) {
- if (argnum == 0) {
- /* Guard against '$0 ...' strings
- */
- break;
- }
- (*argv)[argnum] = wcsdup((*argv)[0]);
- continue;
- }
- else if (argidx <= nparams) {
- /* $n <- params[n-1] */
- argument = (wchar_t *)params[argidx-1];
- }
- else {
- /* We have $n without params[n-1]
- * Stop processing
- */
- break;
- }
- }
- }
- (*argv)[argnum] = eexpand(wcsdup(argument));
+ if ((argv = CommandLineToArgvW(cmdline, argc)) == NULL)
+ return NULL;
+ args = s_malloc(wchar_t *, *argc + 1);
+ if (!args) {
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
}
-
- x_free(cmds);
- return argnum;
+ for (i = 0; i < *argc; i++)
+ args[i] = x_wcsdup(argv[i]);
+ args[i] = NULL;
+
+cleanup:
+ LocalFree(argv);
+ if (rc)
+ SetLastError(rc);
+ return args;
}
static int _vwcsicmp(const void *arg1, const void *arg2)
@@ -504,7 +358,7 @@
*((const wchar_t **)arg2));
}
-static void envsort(wchar_t *const **envp)
+static void SortEnvoronmentArray(wchar_t *const **envp)
{
size_t len = 0;
wchar_t *const *ea = *envp;
@@ -514,12 +368,79 @@
qsort((void *)&envp, len, sizeof(wchar_t *), _vwcsicmp);
}
+static void dumpcmdline(const wchar_t *cmdline)
+{
+ wchar_t **args;
+ int i, nargs;
+
+ args = CommandLineToArgvW(cmdline, &nargs);
+
+ DBG_PRINTF(("Dumping %S", cmdline));
+ for (i = 0; i < nargs; i++) {
+ DBG_PRINTF(("ARGC[%d]='%S'\n", i, args[i]));
+ }
+}
+
+static void FreeArrayAndElements(void **arr)
+{
+ void **ptr = arr;
+
+ if (arr) {
+ while (*ptr != NULL)
+ x_free(*(ptr++));
+ x_free(arr);
+ }
+}
+
int WINAPI wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow)
{
- return 0;
-}
+ DWORD rc = 0;
+ int i;
+ int argc;
+ wchar_t **args = NULL;
+ wchar_t **argv = NULL;
+ wchar_t *cmdline = NULL;
+
+ args = CommandLineToArrayW(GetCommandLineW(), &argc);
+ if (args == NULL) {
+ rc = GetLastError();
+ goto cleanup;
+ }
+ argv = args;
+ if (argc < 2) {
+ /* First two arguments are wsuexec.exe and program to run
+ * Our private arguments always start with double hypen
+ * and end on first argument that doesn't start with it or
+ * with explicit "--" argument marker.
+ */
+ rc = ERROR_INVALID_PARAMETER;
+ goto cleanup;
+ }
+ cmdline = ArgvToCommandLineW(argv);
+ if (!cmdline) {
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
+ }
+ DBG_PRINTF(("CCMDLINE='%S'\n", cmdline));
+ for (i = 0; i < argc; i++) {
+ DBG_PRINTF(("ARGV[%d]='%S'\n", i, argv[i]));
+ }
+ /* Just for checking the CommandLineToArgvW parser
+ * and our wcsquote
+ */
+ dumpcmdline(cmdline);
+ FreeArrayAndElements(args);
+ return 0x20000000;
+
+cleanup:
+ FreeArrayAndElements(args);
+ /* We always return the Windows error code
+ * but add Error Severity and Customer code set.
+ */
+ return (rc | 0xE0000000);
+}