Author: mturk Date: Mon Jan 11 06:51:28 2010 New Revision: 897765 URL: http://svn.apache.org/viewvc?rev=897765&view=rev Log: Misc process argument fixes
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h commons/sandbox/runtime/trunk/src/main/native/include/acr_string.h commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_private.h commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.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/shared/sbuf.c commons/sandbox/runtime/trunk/src/main/native/shared/string.c commons/sandbox/runtime/trunk/src/main/native/test/testsuite.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=897765&r1=897764&r2=897765&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 Mon Jan 11 06:51:28 2010 @@ -50,39 +50,12 @@ ACR_DECLARE(int) ACR_StringToArgvA(const char *cmdline, char ***argv); -#if defined(WIN32) -/** - * Unicode version of ACR_StringToArgvA - */ -ACR_DECLARE(int) ACR_StringToArgvW(const wchar_t *cmdline, - wchar_t ***argv); - -#endif - -/** - * Duplicate argument array. - * @param argv Argument array to duplicate. It has to be NULL terminated. - * @return duplicated array. - * @note Single free is needed to free the entire array data storage. - * Like with ACR_StringToArgv function the argv[0] can be directly - * used by functions that require zero separated double zero terminated - * string. - */ -ACR_DECLARE(char **) ACR_DuplicateArgsA(const char *const *argv); - -/** - * Unicode version of ACR_DuplicateArgsA. - * @note In addition to ACR_DuplicateArgsA, the unicode version double quotes - * the first argument (argv[0]) if it contains space or tab characters. - */ -ACR_DECLARE(wchar_t **) ACR_DuplicateArgsW(const wchar_t *const *argv); - /** * Merge two argument arrays into one. * @param argv1 Source argument array. * @param argv2 Arrgument array to concat to the first one. - * @note Any of the source argument array can be NULL in which - * case function behaves like ACR_DuplicateArgs function. + * @note The second array can be NULL in which case the + * function duplicates first array. */ ACR_DECLARE(char **) ACR_MergeArgsA(const char *const *argv1, const char *const *argv2); @@ -93,9 +66,35 @@ ACR_DECLARE(wchar_t **) ACR_MergeArgsW(const wchar_t *const *argv1, const wchar_t *const *argv2); +/** + * Convert argument arrays into space separate string. + * @param argv Source argument array. + * @return Space separated argument. If argument is empty string + * it is concatenaed as "". + * Use x_free when allocated memory is no longer needed. + */ +ACR_DECLARE(char *) ACR_ArgsToStringA(const char *const *argv); + +/** + * Unicode version of ACR_ArgsToStringA. + */ +ACR_DECLARE(wchar_t *) ACR_ArgsToStringW(const wchar_t *const *argv); + +/** + * Sort the array of string using case insensitive order + * @param pointer to char array to sort. + */ +ACR_DECLARE(void) ACR_ArgsSortA(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); + + #ifdef __cplusplus } #endif #endif /* _ACR_ARGS_H */ - Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_string.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_string.h?rev=897765&r1=897764&r2=897765&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/acr_string.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/acr_string.h Mon Jan 11 06:51:28 2010 @@ -147,6 +147,8 @@ */ ACR_DECLARE(void) ACR_ReleaseMbString(JNIEnv *env, jbyteArray arr, char *s); +ACR_DECLARE(wchar_t *) ACR_Utf8ToWcs(JNIEnv *env, const char *str); + /** Match ascii string to the pattern. * Based loosely on sections of wildmat.c by Rich Salz * @param str String to match. @@ -413,7 +415,6 @@ /** * Convert the multipart string to Java String array. - * @param env Current JNI environment. * @param str String to use. * @return Java string array. */ @@ -421,23 +422,22 @@ /** * Convert the multipart string to pointer array. - * @param env Current JNI environment. * @param str String to use. * @return char array. Use ACR_Free when no longer needed. * @note Returned array is always NULL terminated. */ -ACR_DECLARE(char **) ACR_MszStrToArrayA(JNIEnv *env, - const char *str); +ACR_DECLARE(char **) ACR_MszStrToArrayA(const char *str); /** * Convert the multipart string to pointer array. - * @param env Current JNI environment. * @param str String to use. * @return wide char array. Use ACR_Free when no longer needed. * @note Returned array is always NULL terminated. */ -ACR_DECLARE(wchar_t **) ACR_MszStrToArrayW(JNIEnv *env, - const wchar_t *str); +ACR_DECLARE(wchar_t **) ACR_MszStrToArrayW(const wchar_t *str); + +ACR_DECLARE(char *) ACR_ArrayToMszStrA(const char *const *arr); +ACR_DECLARE(wchar_t *) ACR_ArrayToMszStrW(const wchar_t *const *arr); /** * Convert all tab characters in a string to single space character. @@ -459,18 +459,6 @@ */ ACR_DECLARE(wchar_t *) ACR_wcsqtab2ss(wchar_t *str); -/** - * Sort the array of string using case insensitive order - * @param pointer to char array to sort. - */ -ACR_DECLARE(void) ACR_StrArraySortA(char ***args); - -/** - * Sort the array of wide string using case insensitive order - * @param pointer to the wide char array to sort. - */ -ACR_DECLARE(void) ACR_StrArraySortW(wchar_t ***args); - #ifdef __cplusplus } #endif Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_private.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_private.h?rev=897765&r1=897764&r2=897765&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_private.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_private.h Mon Jan 11 06:51:28 2010 @@ -265,7 +265,8 @@ }; -typedef int rlim_t; +#define RLIMIT_VMEM 1 +typedef size_t rlim_t; struct rlimit { rlim_t rlim_cur; /* Soft limit */ 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=897765&r1=897764&r2=897765&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 Mon Jan 11 06:51:28 2010 @@ -135,6 +135,19 @@ } } +static int limit_proc(HANDLE hProc, acr_proc_limit_t *limit) +{ + if (limit->mem != NULL) { + if (!SetProcessWorkingSetSize(hProc, + limit->mem->rlim_cur, + limit->mem->rlim_max)) { + return ACR_GET_OS_ERROR(); + } + } + + return 0; +} + typedef struct OVERLAPPED_BUFFER { char buff[512]; DWORD stat; @@ -142,7 +155,7 @@ } OVERLAPPED_BUFFER; static int do_exec(acr_exec_t *ep, const wchar_t *cmdline, - wchar_t **argv, + const wchar_t **argv, wchar_t *const *envp) { PROCESS_INFORMATION pi; @@ -161,28 +174,28 @@ DWORD dwPipeFlags; const char *inpp = NULL; wchar_t *args = NULL; + wchar_t *envb = NULL; acr_time_t endat = 0; BOOL iostat; ep->exitwhy = ACR_PARENT_ERROR; if (argv) { - size_t argc; - size_t argl; - - argc = ACR_MszStrSizeW(*argv, &argl); - if (argc == (size_t)-1) { - rc = ACR_EINVAL; - goto cleanup; - } - argl += (argc * 2); - args = x_malloc(argl * sizeof(wchar_t)); + args = ACR_ArgsToStringW(argv); if (!args) { rc = ACR_ENOMEM; goto cleanup; } - if (wcsquotev(argc, argv, args, argl) == (size_t)-1) { - rc = ACR_EINVAL; + printf("CMD %S\n", cmdline); + printf("ARG %S\n", args); + } + if (envp) { + /* Environmet is supposed to be sorted + */ + ACR_ArgsSortW(&envp); + envb = ACR_ArrayToMszStrW(envp); + if (!envb) { + rc = ACR_ENOMEM; goto cleanup; } } @@ -287,7 +300,7 @@ NULL, /* Proc & thread security attributes */ TRUE, /* Inherit handles */ dwCreationFlags, /* Creation flags */ - envp, /* Environment block */ + envb, /* Environment block */ ep->currdir, /* Current directory name */ &si, &pi); @@ -305,7 +318,7 @@ NULL, /* Proc & thread security attributes */ TRUE, /* Inherit handles */ dwCreationFlags, /* Creation flags */ - envp, /* Environment block */ + envb, /* Environment block */ ep->currdir, /* Current directory name */ &si, &pi); @@ -322,6 +335,13 @@ SAFE_CLOSE_HANDLE(pipes[PIPE_STDOUT_WRS]); SAFE_CLOSE_HANDLE(pipes[PIPE_STDERR_WRS]); + if ((rc = limit_proc(pi.hProcess, &ep->limit))) { + /* Failed setting new process limits. + */ + TerminateProcess(pi.hProcess, 9); + ep->exitwhy = ACR_CHILD_SIGNAL; + goto cleanup; + } if (ep->flags & ACR_PROC_DETACHED) { /* We are done in case of detached process */ @@ -528,6 +548,7 @@ SAFE_CLOSE_HANDLE(ob[i].o.hEvent); } x_free(args); + x_free(envb); return ep->exitwhy; } @@ -536,7 +557,7 @@ { int rc; wchar_t **args = NULL; - const wchar_t *sa[4] = { SHELL_PATH, L"/C", cmdline, NULL }; + const wchar_t *sa[5] = { SHELL_PATH, L"/D", L"/C", cmdline, NULL }; if (!(args = ACR_MergeArgsW((const wchar_t *const *)sa, NULL))) { ep->exitval = ACR_GET_OS_ERROR(); @@ -556,16 +577,17 @@ { int rc; wchar_t **args = NULL; - const wchar_t *sa[5] = { SHELL_PATH, L"/C", L"call", fname, NULL }; + const wchar_t *sa[5] = { SHELL_PATH, L"/D", L"/C", fname, NULL }; if (!(args = ACR_MergeArgsW((const wchar_t *const *)sa, argv))) { ep->exitval = ACR_GET_OS_ERROR(); ep->exitwhy = ACR_PARENT_ERROR; return ep->exitwhy; } + rc = do_exec(ep, args[0], args, envp); - x_free(args); + x_free(args); return rc; } 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=897765&r1=897764&r2=897765&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/port/shquote.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/port/shquote.c Mon Jan 11 06:51:28 2010 @@ -162,33 +162,38 @@ rv = 0; + if (argc < 0) { + const char *const *ap = argv; + argc = 0; + if (ap) { + while (*ap) { + argc++; + ap++; + } + } + } if (argc == 0) { - if (bufsize != 0) - *buf = '\0'; - return rv; + PUTC('\0'); + return 0; } for (i = 0; i < argc; i++) { + if (i != 0) { + /* Add space before next arg */ + PUTC(' '); + } + callrv = shquote(argv[i], buf, bufsize); if (callrv == (size_t)-1) - goto bad; - rv += callrv; - buf += callrv; - bufsize = (bufsize > callrv) ? (bufsize - callrv) : 0; - - if (i < (argc - 1)) { - rv++; - if (bufsize > 1) { - *buf++ = ' '; - bufsize--; - } + return callrv; + if (callrv) { + rv += callrv; + buf += callrv; + bufsize = (bufsize > callrv) ? (bufsize - callrv) : 0; } } return rv; - -bad: - return (size_t)-1; } #endif /* ACR_WANT_SHQUOTE */ @@ -197,49 +202,46 @@ */ size_t strquote(const char *arg, char *buf, size_t bufsize) { - char c, lastc; - size_t rv; + char c; + size_t rv = 0; + size_t quoted = 0; int n; - rv = 0; - lastc = 0; - if (!strpbrk(arg, " \t")) { - /* Just copy over the arg */ - return strlcpy(buf, arg, bufsize); + /* Empty args are skipped */ + if (!*arg) { + PUTC('\0'); + return 0; } - if (*arg != '"') { + if (strpbrk(arg, " \t")) { + quoted = 1; + } + if (quoted) { PUTC('"'); } for (;;) { INCH(); - if (n <= 0) + if (n == 0) break; - arg += n; - lastc = c; if (c == '"') { - if (rv != 0) { - PUTC('"'); - } PUTC('\\'); - PUTC('"'); - for (;;) { - INCH(); - if (n <= 0 || c != '"') - break; + } + 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('"'); - arg += n; } - if (n > 0) { - PUTC('"'); - } - } - else { - PUTC(c); + } + PUTC(c); + arg++; } - if (lastc != '"') { + if (quoted) { PUTC('"'); } /* Put NUL terminator, but don't count the NUL. */ @@ -251,49 +253,46 @@ size_t wcsquote(const wchar_t *arg, wchar_t *buf, size_t bufsize) { - wchar_t c, lastc; - size_t rv; + wchar_t c; + size_t rv = 0; + size_t quoted = 0; int n; - rv = 0; - lastc = 0; - if (!wcspbrk(arg, L" \t")) { - /* Just copy over the arg */ - return wcslcpy(buf, arg, bufsize); + /* Empty args are skipped */ + if (!*arg) { + PUTC(L'\0'); + return 0; } - if (*arg != L'"') { + if (wcspbrk(arg, L" \t")) { + quoted = 1; + } + if (quoted) { PUTC(L'"'); } for (;;) { INCH(); - if (n <= 0) + if (n == 0) break; - arg += n; - lastc = c; if (c == L'"') { - if (rv != 0) { - PUTC(L'"'); - } PUTC(L'\\'); - PUTC(L'"'); - for (;;) { - INCH(); - if (n <= 0 || c != L'"') - break; + } + else if (c == L'\\') { + const wchar_t *bsp = arg; + /* Add extra backslash for each backslash + * followed by double quoute. + */ + while (*bsp && *bsp == L'\\') + bsp++; + if (*bsp == L'"') { PUTC(L'\\'); - PUTC(L'"'); - arg += n; - } - if (n > 0) { - PUTC(L'"'); } + } - else { - PUTC(c); - } + PUTC(c); + arg++; } - if (lastc != L'"') { + if (quoted) { PUTC(L'"'); } /* Put NUL terminator, but don't count the NUL. */ @@ -315,31 +314,36 @@ rv = 0; + if (argc < 0) { + const wchar_t *const *ap = argv; + argc = 0; + if (ap) { + while (*ap) { + argc++; + ap++; + } + } + } + if (argc == 0) { - if (bufsize != 0) - *buf = L'\0'; - return rv; + PUTC(L'\0'); + return 0; } for (i = 0; i < argc; i++) { + if (i != 0) { + /* Add space before next arg */ + PUTC(L' '); + } callrv = wcsquote(argv[i], buf, bufsize); if (callrv == (size_t)-1) - goto bad; - rv += callrv; - buf += callrv; - bufsize = (bufsize > callrv) ? (bufsize - callrv) : 0; - - if (i < (argc - 1)) { - rv++; - if (bufsize > 1) { - *buf++ = L' '; - bufsize--; - } + return callrv; + if (callrv) { + rv += (callrv + 1); + buf += callrv; + bufsize = (bufsize > callrv) ? (bufsize - callrv) : 0; } } return rv; - -bad: - return (size_t)-1; } 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=897765&r1=897764&r2=897765&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/args.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/args.c Mon Jan 11 06:51:28 2010 @@ -23,6 +23,8 @@ #include "acr_string.h" #include "acr_sbuf.h" #include "acr_env.h" +#include "acr_port.h" +#include "acr_args.h" /** * Just like strpbrk but it doesn't break if the char @@ -279,302 +281,58 @@ return argnum; } -#if defined(WIN32) -/* Wide char versions make sense on Windows only - */ -static wchar_t *wcspbrk_s(const wchar_t *s1, const wchar_t *s2) -{ - const wchar_t *scanp; - int c, sc, pc = *s1; - - /* Some early sanity check */ - if (!s1 || !*s1) - return NULL; - while ((c = *s1++) != 0) { - for (scanp = s2; (sc = *scanp++) != 0;) { - if (sc == c && pc != L'\'') - return (wchar_t *)(s1 - 1); - } - /* Don't update the previous marker if it was \' already - * In that case we have escaped single quote. - */ - if (pc == L'\\' && c == L'\'') - pc = 0; - else - pc = c; - } - return NULL; -} - -static wchar_t * _wcsexpand(wchar_t *str) -{ - wchar_t *var_pos; - wchar_t *var_end; - wchar_t *var_ptr; - wchar_t *var_rep; - acr_wbuf_t sbuf; - - var_ptr = str; - - if (!var_ptr || !*var_ptr) - return str; /* Guard against zero input */ - var_pos = wcspbrk_s(var_ptr, L"$"); - if (!var_pos) { - wchar_t *buf; - DWORD siz; - - siz = ExpandEnvironmentStringsW(str, NULL, 0); - if (siz) { - buf = s_malloc(wchar_t, siz); - if (buf == NULL) - return str; - siz = ExpandEnvironmentStringsW(str, buf, siz); - if (!siz) { - x_free(buf); - return str; - } - x_free(str); - return buf; - } - return str; - } - acr_wbuf_new(&sbuf, NULL, wcslen(str), ACR_SBUF_AUTOEXTEND); - /* Loop for each unescaped $ */ - while (var_pos) { - int wch = 0; - var_end = NULL; - var_rep = NULL; - if (*(var_pos + 1) == L'(') { - var_end = wcspbrk(var_pos + 1, L" })"); - wch = L')'; - } - else if (*(var_pos + 1) == L'{') { - var_end = wcspbrk(var_pos + 1, L" })"); - wch = L'}'; - } - if (var_end && *var_end == wch) { - *var_pos++ = L'\0'; - *var_pos++ = L'\0'; - *var_end++ = L'\0'; - /* Add the string before $ */ - acr_wbuf_cat(&sbuf, var_ptr); - /* var_pos holds the variable name */ - var_rep = acr_EnvGetW(var_pos); - if (var_rep) { - acr_wbuf_cat(&sbuf, var_rep); - x_free(var_rep); - } - else { - acr_wbuf_putc(&sbuf, L'$'); - if (wch == L'}') - acr_wbuf_putc(&sbuf, L'{'); - else - acr_wbuf_putc(&sbuf, L'('); - acr_wbuf_cat(&sbuf, var_pos); - acr_wbuf_putc(&sbuf, wch); - } - var_ptr = var_end; - var_pos = wcspbrk_s(var_ptr, L"$"); - } - else { - *var_pos++ = L'\0'; - acr_wbuf_cat(&sbuf, var_ptr); - acr_wbuf_putc(&sbuf, L'$'); - var_ptr = var_pos; - var_pos = wcspbrk_s(var_ptr, L"$"); - } - } - /* Add what's left from the original string */ - acr_wbuf_cat(&sbuf, var_ptr); - acr_wbuf_finish(&sbuf); - x_free(str); - - str = acr_wbuf_data(&sbuf); - return str; -} - -ACR_DECLARE(int) ACR_StringToArgvW(const wchar_t *cmdline, - wchar_t ***argv) -{ - const wchar_t *cp; - const wchar_t *ct; - wchar_t *cleaned, *dirty; - wchar_t *args; - wchar_t *argp; - wchar_t *exps; - int escaped; - int isquoted, numargs = 0, argnum; - size_t offset; -#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. - */ -#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'\\') { \ - E = 1; \ - } \ - else { \ - E = 0; \ - *C++ = *D; \ - } \ - ++D; \ - } \ - *C = 0 - - cp = cmdline; - SKIP_WHITESPACEW(cp); - exps = x_wcsdup(cp); - if (!exps) - return -1; - exps = _wcsexpand(exps); - ct = exps; - - /* 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 (*ct != L'\0') { - CHECK_QUOTATIONW(ct, isquoted); - DETERMINE_NEXTSTRINGW(ct, isquoted); - if (*ct != L'\0') { - ct++; - } - numargs++; - SKIP_WHITESPACEW(ct); - } - if (!argv) { - x_free(exps); - return numargs; - } - offset = ACR_ALIGN_DEFAULT(numargs * sizeof(wchar_t*)); - args = x_malloc(offset + ((wcslen(exps) + 1) * sizeof(wchar_t))); - if (!args) { - x_free(exps); - return -1; - } - *argv = (wchar_t **)args; - args += (offset / sizeof(wchar_t)); - wcscpy(args, exps); - x_free(exps); - /* determine first argument */ - for (argnum = 0; argnum < (numargs-1); argnum++) { - SKIP_WHITESPACEW(args); - CHECK_QUOTATIONW(args, isquoted); - argp = args; - DETERMINE_NEXTSTRINGW(args, isquoted); - args++; - (*argv)[argnum] = argp; - (*argv)[argnum][args - argp - 1] = L'\0'; - - cleaned = dirty = (*argv)[argnum]; - REMOVE_ESCAPE_CHARSW(cleaned, dirty, escaped); - } - /* Always NULL terminate the array */ - (*argv)[argnum] = NULL; - - return argnum; -} - -#endif /* WIN32 */ - - ACR_DECLARE(char **) ACR_MergeArgsA(const char *const *argv1, const char *const *argv2) { - size_t arglen; - size_t argnum = 1; - size_t length = 0; - char *buffer; - char **dupargv = NULL; + size_t argnum = 0; + char **dupargv = NULL; const char *const *ap1 = argv1; const char *const *ap2 = argv2; - if (ap1) { - while (*ap1) { + if (!argv1) + return NULL; + while (*ap1) { + if (**ap1) ++argnum; - length += (strlen(*ap1) + 1); - ap1++; - } + ap1++; } + if (ap2) { while (*ap2) { - ++argnum; - length += (strlen(*ap2) + 1); + if (**ap2) + ++argnum; ap2++; } } - if (!length) { + if (!argnum) { /* Nothing to duplicate */ return NULL; } - arglen = ACR_ALIGN_DEFAULT(argnum * sizeof(char *)); - buffer = x_malloc(arglen + length + 1); - if (!buffer) + dupargv = s_malloc(char *, argnum + 1); + if (!dupargv) return NULL; argnum = 0; ap1 = argv1; ap2 = argv2; - dupargv = (char **)buffer; - buffer += arglen; if (ap1) { while (*ap1) { - arglen = strlen(*ap1) + 1; - memcpy(buffer, *ap1, arglen); - dupargv[argnum++] = buffer; - buffer += arglen; + if (**ap1) { + dupargv[argnum++] = (char *)*ap1; + } ap1++; } } if (ap2) { while (*ap2) { - arglen = strlen(*ap2) + 1; - memcpy(buffer, *ap2, arglen); - dupargv[argnum++] = buffer; - buffer += arglen; + if (**ap2) { + dupargv[argnum++] = (char *)*ap2; + } ap2++; } } - *buffer = '\0'; + /* Add terminating NULL pointer. + */ dupargv[argnum] = NULL; return dupargv; @@ -583,88 +341,174 @@ ACR_DECLARE(wchar_t **) ACR_MergeArgsW(const wchar_t *const *argv1, const wchar_t *const *argv2) { - size_t arglen; - size_t argnum = 1; - size_t length = 0; - wchar_t *buffer; + size_t argnum = 0; wchar_t **dupargv = NULL; const wchar_t *const *ap1 = argv1; const wchar_t *const *ap2 = argv2; - if (ap1) { - while (*ap1) { + if (!argv1) + return NULL; + while (*ap1) { + if (**ap1) ++argnum; - length += (wcslen(*ap1) + 1); - ap1++; - } + ap1++; } + if (ap2) { while (*ap2) { - ++argnum; - length += (wcslen(*ap2) + 1); + if (**ap2) + ++argnum; ap2++; } } - if (!length) { + if (!argnum) { /* Nothing to duplicate */ return NULL; } - arglen = ACR_ALIGN_DEFAULT(argnum * sizeof(wchar_t *)); - buffer = x_malloc(arglen + ((length + 3) * sizeof(wchar_t))); - if (!buffer) + dupargv = s_malloc(wchar_t *, argnum + 1); + if (!dupargv) return NULL; argnum = 0; ap1 = argv1; ap2 = argv2; - dupargv = (wchar_t **)buffer; - buffer += (arglen / sizeof(wchar_t)); if (ap1) { while (*ap1) { - arglen = wcslen(*ap1) + 1; - if (argnum == 0 && wcspbrk(*ap1, L" \t")) { - buffer[0] = L'"'; - memcpy(buffer + 1, *ap1, arglen * sizeof(wchar_t)); - buffer[arglen + 1] = L'"'; + if (**ap1) { + dupargv[argnum++] = (wchar_t *)*ap1; } - else - memcpy(buffer, *ap1, arglen * sizeof(wchar_t)); - dupargv[argnum++] = buffer; - buffer += arglen; ap1++; } } if (ap2) { while (*ap2) { - arglen = wcslen(*ap2) + 1; - if (argnum == 0 && wcspbrk(*ap2, L" \t")) { - buffer[0] = L'"'; - memcpy(buffer + 1, *ap2, arglen * sizeof(wchar_t)); - buffer[arglen + 1] = L'"'; + if (**ap2) { + dupargv[argnum++] = (wchar_t *)*ap2; } - else - memcpy(buffer, *ap2, arglen * sizeof(wchar_t)); - dupargv[argnum++] = buffer; - buffer += arglen; ap2++; } } - /* Add double zero termination. - * dupargv[0] can be used as zero separated - * double zero terminated string + /* Add terminating NULL pointer. */ - *buffer = L'\0'; dupargv[argnum] = NULL; return dupargv; } -ACR_DECLARE(char **) ACR_DuplicateArgsA(const char *const *argv) +ACR_DECLARE(char *) ACR_ArgsToStringA(const char *const *argv) +{ + size_t argnum = 0; + size_t length = 0; + size_t arglen = 0; + const char *const *ap = argv; + char *args, *cp; + + if (!ap) { + ACR_SET_OS_ERROR(ACR_EILSEQ); + return NULL; + } + while (*ap) { + size_t al = strquote(*ap, NULL, 0); + if (al == (size_t) -1) { + ACR_SET_OS_ERROR(ACR_EILSEQ); + return NULL; + } + length += (al + 1); + ap++; + } + if (length == 0) + return NULL; + args = cp = s_malloc(char, length + 1); + if (!args) + return NULL; + ap = argv; + + while (*ap) { + if (argnum++) { + *(cp++) = ' '; + --length; + } + arglen = strquote(*ap, cp, length); + cp += arglen; + length -= arglen; + ap++; + } + *cp = '\0'; + return args; +} + +ACR_DECLARE(wchar_t *) ACR_ArgsToStringW(const wchar_t *const *argv) { - return ACR_MergeArgsA(argv, NULL); + size_t argnum = 0; + size_t length = 0; + size_t arglen = 0; + const wchar_t *const *ap = argv; + wchar_t *args, *cp; + + if (!ap) { + ACR_SET_OS_ERROR(ACR_EILSEQ); + return NULL; + } + while (*ap) { + size_t al = wcsquote(*ap, NULL, 0); + if (al == (size_t) -1) { + ACR_SET_OS_ERROR(ACR_EILSEQ); + return NULL; + } + length += (al + 1); + ap++; + } + if (length == 0) + return NULL; + args = cp = s_malloc(wchar_t, length + 1); + if (!args) + return NULL; + ap = argv; + + while (*ap) { + if (argnum++) { + *(cp++) = L' '; + --length; + } + arglen = wcsquote(*ap, cp, length); + cp += arglen; + length -= arglen; + ap++; + } + *cp = L'\0'; + return args; +} + +static int _strcompare(const void *arg1, const void *arg2) +{ + /* Compare all of both strings: */ + return strcasecmp(*((const char **)arg1), + *((const char **)arg2)); +} + +static int _wcscompare(const void *arg1, const void *arg2) +{ + /* Compare all of both strings: */ + return wcscasecmp(*((const wchar_t **)arg1), + *((const wchar_t **)arg2)); +} + +ACR_DECLARE(void) ACR_ArgsSortA(char *const **args) +{ + size_t len = 0; + char *const *sa = *args; + + while (sa[len]) + len++; + qsort((void *)&args, len, sizeof(char *), _strcompare); } -ACR_DECLARE(wchar_t **) ACR_DuplicateArgsW(const wchar_t *const *argv) +ACR_DECLARE(void) ACR_ArgsSortW(wchar_t *const **args) { - return ACR_MergeArgsW(argv, NULL); + size_t len = 0; + wchar_t *const *sa = *args; + + while (sa[len]) + len++; + qsort((void *)&args, len, sizeof(wchar_t *), _wcscompare); } Modified: commons/sandbox/runtime/trunk/src/main/native/shared/sbuf.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/sbuf.c?rev=897765&r1=897764&r2=897765&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/sbuf.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/sbuf.c Mon Jan 11 06:51:28 2010 @@ -56,8 +56,8 @@ #define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & ACR_SBUF_DYNSTRUCT) #define SBUF_ISFINISHED(s) ((s)->s_flags & ACR_SBUF_FINISHED) #define SBUF_HASOVERFLOWED(s) ((s)->s_flags & ACR_SBUF_OVERFLOWED || (s)->s_buf == NULL) -#define SBUF_HASROOM(s) ((s)->s_len < ((s)->s_size - 2)) -#define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len - 2)) +#define SBUF_HASROOM(s) ((s)->s_len < ((s)->s_size - 1)) +#define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len - 1)) #define SBUF_CANEXTEND(s) ((s)->s_flags & ACR_SBUF_AUTOEXTEND) /* @@ -434,8 +434,7 @@ acr_sbuf_finish(acr_sbuf_t *s) { if (s->s_buf) { - s->s_buf[s->s_len++] = '\0'; - s->s_buf[s->s_len] = '\0'; + s->s_buf[s->s_len] = '\0'; SBUF_CLRFLAG(s, ACR_SBUF_OVERFLOWED); } SBUF_SETFLAG(s, ACR_SBUF_FINISHED); @@ -776,9 +775,7 @@ acr_wbuf_finish(acr_wbuf_t *s) { if (s->s_buf) { - s->s_buf[s->s_len++] = L'\0'; - s->s_buf[s->s_len] = L'\0'; - + s->s_buf[s->s_len] = L'\0'; SBUF_CLRFLAG(s, ACR_SBUF_OVERFLOWED); } SBUF_SETFLAG(s, ACR_SBUF_FINISHED); Modified: commons/sandbox/runtime/trunk/src/main/native/shared/string.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/string.c?rev=897765&r1=897764&r2=897765&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/string.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/string.c Mon Jan 11 06:51:28 2010 @@ -281,6 +281,114 @@ return ACR_SUCCESS; } +static int conv_utf8_to_wcs(const char *in, size_t inbytes, + wchar_t *out, size_t *outwords) +{ + acr_int64_t newch, mask; + size_t expect, eating; + int ch; + + while (inbytes && *outwords) { + ch = (unsigned char)(*in++); + if (!(ch & 0200)) { + /* US-ASCII-7 plain text + */ + --inbytes; + --*outwords; + *(out++) = ch; + } + else { + if ((ch & 0300) != 0300) { + /* Multibyte Continuation is out of place + */ + return ACR_EINVAL; + } + else { + /* Multibyte Sequence Lead Character + * + * Compute the expected bytes while adjusting + * or lead byte and leading zeros mask. + */ + mask = 0340; + expect = 1; + while ((ch & mask) == mask) { + mask |= mask >> 1; + if (++expect > 3) /* (truly 5 for ucs-4) */ + return ACR_EINVAL; + } + newch = ch & ~mask; + eating = expect + 1; + if (inbytes <= expect) + return ACR_INCOMPLETE; + /* Reject values of excessive leading 0 bits + * utf-8 _demands_ the shortest possible byte length + */ + if (expect == 1) { + if (!(newch & 0036)) + return ACR_EINVAL; + } + else { + /* Reject values of excessive leading 0 bits + */ + if (!newch && !((unsigned char)*in & 0077 & (mask << 1))) + return ACR_EINVAL; + if (expect == 2) { + /* Reject values D800-DFFF when not utf16 encoded + * (may not be an appropriate restriction for ucs-4) + */ + if (newch == 0015 && ((unsigned char)*in & 0040)) + return ACR_EINVAL; + } + else if (expect == 3) { + /* Short circuit values > 110000 + */ + if (newch > 4) + return ACR_EINVAL; + if (newch == 4 && ((unsigned char)*in & 0060)) + return ACR_EINVAL; + } + } + /* Where the boolean (expect > 2) is true, we will need + * an extra word for the output. + */ + if (*outwords < (size_t)(expect > 2) + 1) + break; /* buffer full */ + while (expect--) { + /* Multibyte Continuation must be legal */ + if (((ch = (unsigned char)*(in++)) & 0300) != 0200) + return ACR_EINVAL; + newch <<= 6; + newch |= (ch & 0077); + } + inbytes -= eating; +#if CC_SIZEOF_WCHAR_T == 2 + /* newch is now a true ucs-4 character + * + * now we need to fold to ucs-2 + */ + if (newch < 0x10000) { + --*outwords; + *(out++) = (wchar_t) newch; + } + else { + *outwords -= 2; + newch -= 0x10000; + *(out++) = (wchar_t) (0xD800 | (newch >> 10)); + *(out++) = (wchar_t) (0xDC00 | (newch & 0x03FF)); + } +#else + --*outwords; + *(out++) = (wchar_t) newch; +#endif + } + } + } + /* Buffer full 'errors' aren't errors, the client must inspect both + * the inbytes and outwords values + */ + return ACR_SUCCESS; +} + /* Java implementation of GetStringUTF is bogus. * It breaks on embeded NUL in strings. * Use the APR implementation instead. @@ -506,6 +614,25 @@ return dst; } +ACR_DECLARE(wchar_t *) ACR_Utf8ToWcs(JNIEnv *_E, const char *str) +{ + int rc; + size_t len, out; + wchar_t *dst; + + out = len = strlen(str) + 1; + dst = ACR_MALLOC(wchar_t, len); + if (!dst) + return NULL; + if ((rc = conv_utf8_to_wcs(str, len, dst, &out))) { + /* Invalid UTF-8 string */ + x_free(dst); + ACR_SET_OS_ERROR(rc); + return NULL; + } + return dst; +} + ACR_DECLARE(char *) ACR_Usc2ToUtf8(JNIEnv *_E, const jchar *str, jsize len) { int rc; @@ -1919,7 +2046,7 @@ return NULL; cnt = (*_E)->GetArrayLength(_E, arr); - ret = (char **)ACR_Malloc(_E, THROW_NMARK, (cnt + 1) * sizeof(char *)); + ret = (char **)ACR_MALLOC(char *, cnt + 1); if (!ret) return NULL; for (i = 0; i < cnt; i++) { @@ -1945,7 +2072,7 @@ return NULL; cnt = (*_E)->GetArrayLength(_E, arr); - ret = (wchar_t **)ACR_Malloc(_E, THROW_NMARK, (cnt + 1) * sizeof(wchar_t *)); + ret = (wchar_t **)ACR_MALLOC(wchar_t *, cnt + 1); if (!ret) return NULL; for (i = 0; i < cnt; i++) { @@ -1961,16 +2088,15 @@ return ret; } -ACR_DECLARE(char **) ACR_MszStrToArrayA(JNIEnv *_E, - const char *str) +ACR_DECLARE(char **) ACR_MszStrToArrayA(const char *str) { char **arr = NULL; - jsize n = 0; + size_t n = 0; const char *p; if (str) { - if ((n = (jsize)ACR_MszStrCountA(str)) > 0) - arr = ACR_Malloc(_E, THROW_FMARK, (n + 1) * sizeof(char *)); + if ((n = ACR_MszStrCountA(str)) > 0) + arr = s_malloc(char *, n + 1); } if (!arr) return NULL; @@ -1985,16 +2111,15 @@ return arr; } -ACR_DECLARE(wchar_t **) ACR_MszStrToArrayW(JNIEnv *_E, - const wchar_t *str) +ACR_DECLARE(wchar_t **) ACR_MszStrToArrayW(const wchar_t *str) { wchar_t **arr = NULL; - jsize n = 0; + size_t n = 0; const wchar_t *p; if (str) { - if ((n = (jsize)ACR_MszStrCountW(str)) > 0) - arr = ACR_Malloc(_E, THROW_FMARK, (n + 1) * sizeof(wchar_t *)); + if ((n = ACR_MszStrCountW(str)) > 0) + arr = s_malloc(wchar_t *, n + 1); } if (!arr) return NULL; @@ -2009,6 +2134,84 @@ return arr; } +ACR_DECLARE(char *) ACR_ArrayToMszStrA(const char *const *arr) +{ + const char *const *ap = arr; + size_t n = 0; + size_t l = 0; + char *p, *s; + + if (!arr) + return NULL; + + while(*ap) { + ++n; + if (**ap) + l += (strlen(*ap) + 1); + ap++; + } + if (l == 0) { + /* Nothing to duplicate + */ + return NULL; + } + ap = arr; + p = s = s_malloc(char, l + 1); + if (!p) + return NULL; + + while(*ap) { + if (**ap) { + l = strlen(*ap); + memcpy(p, *ap, l); + p += l; + *p++ = '\0'; + } + ap++; + } + *p = '\0'; + return s; +} + +ACR_DECLARE(wchar_t *) ACR_ArrayToMszStrW(const wchar_t *const *arr) +{ + const wchar_t *const *ap = arr; + size_t n = 0; + size_t l = 0; + wchar_t *p, *s; + + if (!arr) + return NULL; + + while(*ap) { + ++n; + if (**ap) + l += (wcslen(*ap) + 1); + ap++; + } + if (l == 0) { + /* Nothing to duplicate + */ + return NULL; + } + ap = arr; + p = s = s_malloc(wchar_t, l + 1); + if (!p) + return NULL; + + while(*ap) { + if (**ap) { + l = wcslen(*ap); + memcpy(p, *ap, l * sizeof(wchar_t)); + p += l; + *p++ = L'\0'; + } + ap++; + } + *p = L'\0'; + return s; +} + ACR_DECLARE(char *) ACR_strqtab2ss(char *str) { char *ptr = str; @@ -2058,36 +2261,3 @@ } return ptr; } - -static int _strcompare(const void *arg1, const void *arg2) -{ - /* Compare all of both strings: */ - return strcasecmp(*(char **)arg1, *(char **)arg2); -} - -static int _wcscompare(const void *arg1, const void *arg2) -{ - /* Compare all of both strings: */ - return wcscasecmp(*(wchar_t **)arg1, *(wchar_t **)arg2); -} - -ACR_DECLARE(void) ACR_StrArraySortA(char ***args) -{ - size_t len = 0; - char **sa = *args; - - while (sa[len]) - len++; - qsort((void *)&args, len, sizeof(char *), _strcompare); -} - -ACR_DECLARE(void) ACR_StrArraySortW(wchar_t ***args) -{ - size_t len = 0; - wchar_t **sa = *args; - - while (sa[len]) - len++; - qsort((void *)&args, len, sizeof(wchar_t *), _wcscompare); -} - Modified: commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c?rev=897765&r1=897764&r2=897765&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c Mon Jan 11 06:51:28 2010 @@ -577,7 +577,6 @@ return ACR_EINVAL; } exe = ACR_ExecNew(ACR_PROC_HAS_STDOUT); - printf("Exec is %p\n", exe); exe->limit.timeout = ACR_USEC_PER_SEC * 2; #if defined(WIN32) rc = ACR_ExecShellCmd(exe, wargv[0], NULL);