Author: mturk Date: Sat Jan 9 12:46:39 2010 New Revision: 897438 URL: http://svn.apache.org/viewvc?rev=897438&view=rev Log: Implement step 1 of Windows exec
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_exec.h commons/sandbox/runtime/trunk/src/main/native/include/acr_port.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/os/win32/main.c commons/sandbox/runtime/trunk/src/main/native/os/win32/platform.c commons/sandbox/runtime/trunk/src/main/native/os/win32/posix.c commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c commons/sandbox/runtime/trunk/src/main/native/os/win32/wusec.c commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.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/string.c commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_exec.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_exec.h?rev=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/acr_exec.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/acr_exec.h Sat Jan 9 12:46:39 2010 @@ -64,17 +64,18 @@ int flags; /** Process limits */ acr_proc_limit_t limit; +#if defined(WIN32) + /** User token. + */ + acr_osd_t usertoken; +#else /** User Id for child process */ acr_uid_t uid; /** Group Id for child process */ acr_gid_t gid; - /** User logon password. - * Used for Windows and su mode. - */ - acr_pchar_t *password; +#endif /** Process working directory */ acr_pchar_t *currdir; - /** Process exit value */ int exitval; /** Process exit reason */ @@ -136,9 +137,9 @@ * environment of the calling process is used. * @return Exit reason. */ -ACR_DECLARE(int) ACR_ExecProgram(acr_exec_t *ep, const char *executable, - const char *const *argv, - char *const *envp); +ACR_DECLARE(int) ACR_ExecProgram(acr_exec_t *ep, const acr_pchar_t *executable, + const acr_pchar_t *const *argv, + acr_pchar_t *const *envp); /** * Get executed program output stream. 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=897438&r1=897437&r2=897438&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 Sat Jan 9 12:46:39 2010 @@ -135,6 +135,7 @@ #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); #if defined(ACR_WANT_FDWALK) int fdwalk(int (*func)(void *, int), void *); 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=897438&r1=897437&r2=897438&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 Sat Jan 9 12:46:39 2010 @@ -388,6 +388,17 @@ * terminated strings * <p> * @param str String to use. + * @param len Length in chars of the string. + * @return Number of string parts. + */ +ACR_DECLARE(size_t) ACR_MszStrSizeW(const wchar_t *s, size_t *len); + +/** + * Count the number of string parts in multi string. Unicode version. + * <p> Multi strings are zero separated double zero + * terminated strings + * <p> + * @param str String to use. * @return Number of string parts. */ ACR_DECLARE(size_t) ACR_MszStrCountW(const wchar_t *s); 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=897438&r1=897437&r2=897438&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 Sat Jan 9 12:46:39 2010 @@ -142,9 +142,15 @@ if (_w##V && _w##V != _b##V) x_free (_w##V); \ } else ACR_ThrowException(_E, THROW_FMARK, ACR_EX_ENULL, 0) +#define SAFE_CLOSE_HANDLE(H) \ + if ((H) != NULL && (H) != INVALID_HANDLE_VALUE) { \ + CloseHandle((H)); \ + (H) = NULL; \ + } else (void)0 -void acr_thread_lock(void); -void acr_thread_unlock(void); + +void ACR_THREAD_LOCK_EX(void); +void ACR_THREAD_LOCK_UN(void); /** * Local functions from wusec.c @@ -199,7 +205,13 @@ #define ACR_SIGNAL_NWAITERS() InterlockedCompareExchange(¤t_signal_listeners, 0, 0) #define WAIT_ABANDONED_1 (WAIT_ABANDONED_0 + 1) +#define WAIT_ABANDONED_2 (WAIT_ABANDONED_0 + 2) +#define WAIT_ABANDONED_3 (WAIT_ABANDONED_0 + 3) +#define WAIT_ABANDONED_4 (WAIT_ABANDONED_0 + 4) #define WAIT_OBJECT_1 (WAIT_OBJECT_0 + 1) +#define WAIT_OBJECT_2 (WAIT_OBJECT_0 + 2) +#define WAIT_OBJECT_3 (WAIT_OBJECT_0 + 3) +#define WAIT_OBJECT_4 (WAIT_OBJECT_0 + 4) static ACR_INLINE DWORD ACR_WaitForObjectOrSignal(HANDLE handle, DWORD dwTimeout) { DWORD rc; @@ -236,8 +248,8 @@ wchar_t *x_wcsdup_utf8_path(const char *); wchar_t *x_wcsdup_utf8(const char *); char *x_strdup_utf8(const wchar_t *); -LPWSTR MbsToWcs(DWORD, LPCSTR, LPWSTR, DWORD); -LPSTR WcsToMbs(DWORD, LPCWSTR, LPSTR, DWORD); +ACR_DECLARE(LPWSTR) MbsToWcs(DWORD, LPCSTR, LPWSTR, DWORD); +ACR_DECLARE(LPSTR) WcsToMbs(DWORD, LPCWSTR, LPSTR, DWORD); wchar_t *acr_GetAbsolutePath(JNIEnv *, HANDLE, const wchar_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=897438&r1=897437&r2=897438&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 Sat Jan 9 12:46:39 2010 @@ -46,6 +46,7 @@ #define PIPE_STDERR_RDS 4 #define PIPE_STDERR_WRS 5 +extern wchar_t *SHELL_PATH; ACR_DECLARE(acr_exec_t *) ACR_ExecNew(int flags) { @@ -125,6 +126,7 @@ ACR_DECLARE(void) ACR_ExecFree(acr_exec_t *e) { if (e) { + SAFE_CLOSE_HANDLE(e->usertoken); x_free(e->currdir); acr_sbuf_delete(&e->sout); acr_sbuf_delete(&e->serr); @@ -133,3 +135,455 @@ } } +typedef struct OVERLAPPED_BUFFER { + char buff[512]; + DWORD stat; + OVERLAPPED o; +} OVERLAPPED_BUFFER; + +static int do_exec(acr_exec_t *ep, const wchar_t *cmdline, + wchar_t **argv, + wchar_t *const *envp) +{ + PROCESS_INFORMATION pi; + STARTUPINFOW si; + int i; + HANDLE cp = GetCurrentProcess(); + DWORD rd, wr; + DWORD rc = 0; + BOOL rs = FALSE; + DWORD exitval; + HANDLE pipes[6] = { NULL, NULL, NULL, NULL, NULL, NULL }; + HANDLE waith[6] = { NULL, NULL, NULL, NULL, NULL, NULL }; + DWORD waitn = 0; + OVERLAPPED_BUFFER ob[3]; + DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | CREATE_SUSPENDED; + DWORD dwPipeFlags; + const char *inpp = NULL; + wchar_t *args = 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)); + if (!args) { + rc = ACR_ENOMEM; + goto cleanup; + } + if (wcsquotev(argc, argv, args, argl) == (size_t)-1) { + rc = ACR_EINVAL; + goto cleanup; + } + } + memset(&pi, 0, sizeof(pi)); + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + for (i = 0; i < 3; i++) + memset(&ob[i], 0, sizeof(OVERLAPPED_BUFFER)); + + /* Sanity check. + * Daemons have no stream pipes + */ + if (ep->flags & ACR_PROC_DETACHED) { + ep->flags &= ~(ACR_PROC_HAS_STDIN | + ACR_PROC_HAS_STDOUT | + ACR_PROC_HAS_STDERR); + dwCreationFlags |= DETACHED_PROCESS; + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + + } + /* Create standard stream pipes + */ + if (ep->flags & ACR_PROC_HAS_STDIN && ep->data.iov_len) { + if ((rc = pipepair(&pipes[PIPE_STDINP_RDS], &pipes[PIPE_STDINP_WRS], + NULL, ACR_PIPE_READ_BLOCK))) + goto cleanup; + inpp = (const char *)ep->data.iov_base; + } + else { + /* Use NUL (aka /dev/null) */ + pipes[PIPE_STDINP_RDS] = nullpipe(GENERIC_READ, NULL); + } + if (ep->flags & ACR_PROC_HAS_STDOUT) { + if ((rc = pipepair(&pipes[PIPE_STDOUT_RDS], &pipes[PIPE_STDOUT_WRS], + NULL, ACR_PIPE_WRITE_BLOCK))) + goto cleanup; + } + else { + /* Use NUL (aka /dev/null) */ + pipes[PIPE_STDOUT_WRS] = nullpipe(GENERIC_WRITE, NULL); + } + if (ep->flags & ACR_PROC_HAS_STDERR) { + if ((rc = pipepair(&pipes[PIPE_STDERR_RDS], &pipes[PIPE_STDERR_WRS], + NULL, ACR_PIPE_WRITE_BLOCK))) + goto cleanup; + } + else { + /* Use same pipes for stderr and stdout + */ + pipes[PIPE_STDERR_WRS] = pipes[PIPE_STDOUT_WRS]; + pipes[PIPE_STDERR_RDS] = pipes[PIPE_STDOUT_RDS]; + } + /* Always use STDHANDLES + * They are either real handles or handles to NUL device + */ + si.dwFlags |= STARTF_USESTDHANDLES; + dwPipeFlags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS; + if (!DuplicateHandle(cp, pipes[PIPE_STDINP_RDS], cp, &pipes[PIPE_STDINP_RDS], + 0, TRUE, dwPipeFlags)) { + rc = ACR_GET_OS_ERROR(); + goto cleanup; + } + dwPipeFlags = DUPLICATE_SAME_ACCESS; + if (ep->flags & ACR_PROC_HAS_STDERR) + dwPipeFlags |= DUPLICATE_CLOSE_SOURCE; + if (!DuplicateHandle(cp, pipes[PIPE_STDOUT_WRS], cp, &pipes[PIPE_STDOUT_WRS], + 0, TRUE, dwPipeFlags)) { + rc = ACR_GET_OS_ERROR(); + goto cleanup; + } + dwPipeFlags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS; + if (!DuplicateHandle(cp, pipes[PIPE_STDERR_WRS], cp, &pipes[PIPE_STDERR_WRS], + 0, TRUE, dwPipeFlags)) { + rc = ACR_GET_OS_ERROR(); + goto cleanup; + } + + si.hStdInput = pipes[PIPE_STDINP_RDS]; + si.hStdOutput = pipes[PIPE_STDOUT_WRS]; + si.hStdError = pipes[PIPE_STDERR_WRS]; + if (ep->limit.timeout > 0) + endat = ACR_TimeNow() + ep->limit.timeout; + + if (ep->usertoken) { + /* XXX: for terminal services, handles cannot be + * inherited across sessions. This process must be created + * in our existing session. lpDesktop assignment appears + * to be wrong according to these rules. + */ + si.lpDesktop = L"Winsta0\\Default"; + if (!ImpersonateLoggedOnUser(ep->usertoken)) { + /* failed to impersonate the logged user */ + rc = ACR_GET_OS_ERROR(); + goto cleanup; + } + rs = CreateProcessAsUserW( + ep->usertoken, + cmdline, /* Executable */ + args, /* Command line */ + NULL, + NULL, /* Proc & thread security attributes */ + TRUE, /* Inherit handles */ + dwCreationFlags, /* Creation flags */ + envp, /* Environment block */ + ep->currdir, /* Current directory name */ + &si, + &pi); + if (!rs) + rc = GetLastError(); + RevertToSelf(); + if (!rs) + SetLastError(rc); + } + else { + rs = CreateProcessW( + cmdline, /* Executable */ + args, /* Command line */ + NULL, + NULL, /* Proc & thread security attributes */ + TRUE, /* Inherit handles */ + dwCreationFlags, /* Creation flags */ + envp, /* Environment block */ + ep->currdir, /* Current directory name */ + &si, + &pi); + } + if (!rs) { + rc = ACR_GET_OS_ERROR(); + goto cleanup; + } + + /* Close our side of the pipes + */ + SAFE_CLOSE_HANDLE(pipes[PIPE_STDINP_RDS]); + SAFE_CLOSE_HANDLE(pipes[PIPE_STDOUT_WRS]); + SAFE_CLOSE_HANDLE(pipes[PIPE_STDERR_WRS]); + + if (ep->flags & ACR_PROC_DETACHED) { + /* We are done in case of detached process + */ + rc = 0; + ep->exitwhy = ACR_CHILD_NOTDONE; + ResumeThread(pi.hThread); + goto finally; + } + /* Setup wait handles + */ + waith[waitn++] = sig_raised_event; + waith[waitn++] = pi.hProcess; + if (IS_VALID_HANDLE(pipes[PIPE_STDOUT_RDS])) { + ob[0].o.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + waith[waitn++] = ob[0].o.hEvent; + } + if (IS_VALID_HANDLE(pipes[PIPE_STDERR_RDS]) && + (ep->flags & ACR_PROC_HAS_STDERR)) { + ob[1].o.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + waith[waitn++] = ob[1].o.hEvent; + } + if (IS_VALID_HANDLE(pipes[PIPE_STDINP_WRS])) { + ob[2].o.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + waith[waitn++] = ob[2].o.hEvent; + } + ep->pid = pi.dwProcessId; + + /* We have created a process with the suspended main thread. + * Resume the main process thread. + */ + ResumeThread(pi.hThread); + rc = 0; + + /* Sink the console pipes and wait until the child terminates. + */ + do { + DWORD dwTimeout = ep->limit.timeout > 0 ? PROC_TIMEOUT_STEP : INFINITE; + DWORD ws; + + ACR_SIG_WAITER_INIT(); + ws = WaitForMultipleObjectsEx(waitn, waith, FALSE, dwTimeout, TRUE); + ACR_SIG_WAITER_DONE(); + switch (ws) { + case WAIT_IO_COMPLETION: + case WAIT_ABANDONED_0: + case WAIT_ABANDONED_1: + case WAIT_ABANDONED_2: + case WAIT_ABANDONED_3: + case WAIT_ABANDONED_4: + case WAIT_OBJECT_0: + /* Signal event is set. + * Get it's status. + */ + rc = ACR_DeliverSignals(); + break; + case WAIT_OBJECT_1: + /* Signal on hProcess is set. + * This means the process exited + */ + GetExitCodeProcess(pi.hProcess, &exitval); + rc = 0; + rs = FALSE; + break; + case WAIT_OBJECT_2: + /* Signal on stdout stream + */ + if (IS_VALID_HANDLE(pipes[PIPE_STDOUT_RDS])) { + if (ob[0].stat == ERROR_IO_PENDING) { + if (!GetOverlappedResult(pipes[PIPE_STDOUT_RDS], + &ob[0].o, + &rd, + FALSE)) { + ob[0].stat = GetLastError(); + } + else { + ob[0].stat = 0; + rd = acr_sbuf_bcat(&ep->sout, ob[0].buff, rd); + } + rc = ACR_EINTR; + break; + } + iostat = ReadFile(pipes[PIPE_STDOUT_RDS], + ob[0].buff, sizeof(ob[0].buff), + &rd, &ob[0].o); + if (iostat && rd != 0) { + ob[0].stat = 0; + rd = acr_sbuf_bcat(&ep->sout, ob[0].buff, rd); + } + else { + ob[0].stat = GetLastError(); + if (ob[0].stat != ERROR_IO_PENDING) { + SAFE_CLOSE_HANDLE(pipes[PIPE_STDOUT_RDS]); + } + } + } + rc = ACR_EINTR; + break; + case WAIT_OBJECT_3: + /* Signal on stderr stream + */ + if (IS_VALID_HANDLE(pipes[PIPE_STDERR_RDS])) { + if (ob[1].stat == ERROR_IO_PENDING) { + if (!GetOverlappedResult(pipes[PIPE_STDERR_RDS], + &ob[1].o, + &rd, + FALSE)) { + ob[1].stat = GetLastError(); + } + else { + ob[1].stat = 0; + rd = acr_sbuf_bcat(&ep->serr, ob[1].buff, rd); + } + rc = ACR_EINTR; + break; + } + iostat = ReadFile(pipes[PIPE_STDERR_RDS], + ob[1].buff, sizeof(ob[1].buff), + &rd, &ob[1].o); + if (iostat && rd != 0) { + ob[1].stat = 0; + rd = acr_sbuf_bcat(&ep->serr, ob[1].buff, rd); + } + else { + ob[1].stat = GetLastError(); + if (ob[1].stat != ERROR_IO_PENDING) { + SAFE_CLOSE_HANDLE(pipes[PIPE_STDERR_RDS]); + } + } + rc = ACR_EINTR; + break; + } + case WAIT_OBJECT_4: + /* Signal on stdin stream + */ + if (IS_VALID_HANDLE(pipes[PIPE_STDINP_WRS]) && + ep->data.iov_len > 0) { + if (ob[2].stat == ERROR_IO_PENDING) { + if (!GetOverlappedResult(pipes[PIPE_STDINP_WRS], + &ob[2].o, + &wr, + FALSE)) { + ob[2].stat = GetLastError(); + } + else { + ob[2].stat = 0; + ep->data.iov_len -= wr; + inpp += wr; + } + rc = ACR_EINTR; + break; + } + iostat = WriteFile(pipes[PIPE_STDINP_WRS], inpp, + ep->data.iov_len, &wr, &ob[2].o); + if (iostat && wr != 0) { + ep->data.iov_len -= wr; + inpp += wr; + } + else { + ob[2].stat = GetLastError(); + if (ob[2].stat != ERROR_IO_PENDING) { + SAFE_CLOSE_HANDLE(pipes[PIPE_STDINP_WRS]); + } + } + } + rc = ACR_EINTR; + break; + case WAIT_TIMEOUT: + if (ACR_TimeNow() >= endat) + rc = ACR_TIMEUP; + break; + default: + /* Unexpected result from Wait + */ + rc = ACR_EINVAL; + break; + } + } while (rc == ACR_EINTR); + + if (rs) { + /* Still running. + * Time to kill the bugger + */ + TerminateProcess(pi.hProcess, 9); + ep->exitwhy = ACR_CHILD_SIGNAL; + rc = 9; + } + else { + ep->exitwhy = ACR_CHILD_DONE; + rc = exitval; + } + +finally: + SAFE_CLOSE_HANDLE(pi.hThread); + SAFE_CLOSE_HANDLE(pi.hProcess); + +cleanup: + acr_sbuf_finish(&ep->sout); + acr_sbuf_finish(&ep->serr); + ep->exitval = rc; + if (pipes[PIPE_STDERR_RDS] == pipes[PIPE_STDOUT_RDS]) + pipes[PIPE_STDERR_RDS] = NULL; + for (i = 0; i < 6; i++) + SAFE_CLOSE_HANDLE(pipes[i]); + for (i = 0; i < 3; i++) { + SAFE_CLOSE_HANDLE(ob[i].o.hEvent); + } + x_free(args); + return ep->exitwhy; +} + +ACR_DECLARE(int) ACR_ExecShellCmd(acr_exec_t *ep, const wchar_t *cmdline, + wchar_t *const *envp) +{ + int rc; + wchar_t **args = NULL; + const wchar_t *sa[4] = { SHELL_PATH, L"/C", cmdline, NULL }; + + if (!(args = ACR_MergeArgsW((const wchar_t *const *)sa, NULL))) { + 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); + + return rc; + +} + +ACR_DECLARE(int) ACR_ExecShellScript(acr_exec_t *ep, const wchar_t *fname, + const wchar_t *const *argv, + wchar_t *const *envp) +{ + int rc; + wchar_t **args = NULL; + const wchar_t *sa[5] = { SHELL_PATH, L"/C", L"call", 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); + + return rc; +} + +ACR_DECLARE(int) ACR_ExecProgram(acr_exec_t *ep, const wchar_t *executable, + const wchar_t *const *argv, + wchar_t *const *envp) +{ + int rc; + wchar_t **args = NULL; + const wchar_t *sa[2] = { executable, 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); + + return rc; +} Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/main.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/main.c?rev=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/main.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/main.c Sat Jan 9 12:46:39 2010 @@ -522,13 +522,13 @@ return tlsd->env; } -void acr_thread_lock() +void ACR_THREAD_LOCK_EX() { if (dll_instance) EnterCriticalSection(&dll_main_lock); } -void acr_thread_unlock() +void ACR_THREAD_LOCK_UN() { if (dll_instance) LeaveCriticalSection(&dll_main_lock); Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/platform.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/platform.c?rev=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/platform.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/platform.c Sat Jan 9 12:46:39 2010 @@ -35,7 +35,8 @@ acr_size_t acr_page_size; int acr_native_codepage = ACR_CP_DEFAULT; -wchar_t *acr_comspec = NULL; +wchar_t *SHELL_PATH = NULL; + typedef struct struct_align_t { char c; acr_int64_t l; @@ -47,8 +48,11 @@ { int rc; - if (ACR_AtomicInc32(&initialized)) + if (ACR_AtomicInc32(&initialized) > 1) { + /* Second invocation + */ return 0; + } acr_page_size = (acr_size_t)acr_osinf->dwPageSize; if (!acr_everyone_sid) { acr_everyone_sid = ACR_AllocateWellKnownSid(_E, WinWorldSid); @@ -80,11 +84,11 @@ FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE); /* Get the path to the cmd.exe */ - acr_comspec = acr_EnvGetW(L"COMSPEC"); - if (!acr_comspec) { + SHELL_PATH = acr_EnvGetW(L"COMSPEC"); + if (!SHELL_PATH) { /* Hope the PATH is set correctly */ - acr_comspec = x_wcsdup(L"CMD.EXE"); + SHELL_PATH = x_wcsdup(L"CMD.EXE"); } return acr_ioh_init(ios); } Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/posix.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/posix.c?rev=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/posix.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/posix.c Sat Jan 9 12:46:39 2010 @@ -42,7 +42,7 @@ */ return ppid; } - acr_thread_lock(); + ACR_THREAD_LOCK_EX(); if (ppid >= 0) goto finally; @@ -67,7 +67,7 @@ CloseHandle(snap); finally: - acr_thread_unlock(); + ACR_THREAD_LOCK_UN(); return ppid; } @@ -146,12 +146,12 @@ if (psid) process = OpenProcess(MAXIMUM_ALLOWED, FALSE, psid); else { - acr_thread_lock(); + ACR_THREAD_LOCK_EX(); if (dll_user_token == NULL) process = GetCurrentProcess(); else ctok = dll_user_token; - acr_thread_unlock(); + ACR_THREAD_LOCK_UN(); } if (process != NULL) { if (!OpenProcessToken(process, @@ -172,10 +172,10 @@ CloseHandle(process); } else { - acr_thread_lock(); + ACR_THREAD_LOCK_EX(); if (dll_user_token == NULL) dll_user_token = ctok; - acr_thread_unlock(); + ACR_THREAD_LOCK_UN(); } } } Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c?rev=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c Sat Jan 9 12:46:39 2010 @@ -464,11 +464,13 @@ HANDLE wh[2]; DWORD nw = 1; DWORD rc; - DWORD cs; + DWORD cs = 0; sig_pipe_data_t *pd; wh[0] = sig_handle_event; wh[1] = CreateEvent(NULL, TRUE, TRUE, NULL); + memset(&sync, 0, sizeof(OVERLAPPED)); + if (IS_VALID_HANDLE(wh[1])) { sync.hEvent = wh[nw++]; cs = sig_pipe_connect(&sync); @@ -569,6 +571,7 @@ { HANDLE h; DWORD i; + /* Guard against multiple invocations. * We might initialize twice; in daemon and in JVM again */ Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/wusec.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/wusec.c?rev=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/wusec.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/wusec.c Sat Jan 9 12:46:39 2010 @@ -26,6 +26,14 @@ #include "acr_file.h" #include "acr_users.h" +#define SECURITY_LCK() \ + if (security_table) \ + EnterCriticalSection(&security_lock) + +#define SECURITY_UNL() \ + if (security_table) \ + LeaveCriticalSection(&security_lock) + PSID ACR_GetSidFromAccountName(LPCWSTR name, PSID_NAME_USE sidtype) { WCHAR domain[MAX_PATH]; @@ -479,10 +487,10 @@ strcat(sdd, saa); strcat(sdd, ";;;AU)"); } - EnterCriticalSection(&security_lock); + SECURITY_LCK(); if (ACR_TableGet(security_table, sdd, &pSD, NULL) == ACR_SUCCESS) { /* Return catched entry */ - LeaveCriticalSection(&security_lock); + SECURITY_UNL(); return pSD; } if (!ConvertStringSecurityDescriptorToSecurityDescriptorA(sdd, @@ -499,7 +507,7 @@ */ ACR_TableAdd(_E, THROW_FMARK, security_table, sdd, pSD, sizeof(PSECURITY_DESCRIPTOR)); } - LeaveCriticalSection(&security_lock); + SECURITY_UNL(); if (rc) ACR_SET_OS_ERROR(rc); return pSD; @@ -584,9 +592,9 @@ if (_null_sa) return _null_sa; - EnterCriticalSection(&security_lock); + SECURITY_LCK(); if (_null_sa) { - LeaveCriticalSection(&security_lock); + SECURITY_UNL(); return _null_sa; } _null_sa = (PSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES)); @@ -609,7 +617,7 @@ _null_sa->lpSecurityDescriptor = pSD; _null_sa->bInheritHandle = FALSE; - LeaveCriticalSection(&security_lock); + SECURITY_UNL(); SetLastError(0); return _null_sa; @@ -625,7 +633,7 @@ _null_sa->lpSecurityDescriptor = NULL; _null_sa->bInheritHandle = FALSE; - LeaveCriticalSection(&security_lock); + SECURITY_UNL(); SetLastError(rc); return _null_sa; } Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c?rev=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c Sat Jan 9 12:46:39 2010 @@ -497,13 +497,14 @@ } } -LPWSTR MbsToWcs(DWORD dwCp, LPCSTR szAnsi, LPWSTR szWide, DWORD dwLength) +ACR_DECLARE(LPWSTR) +MbsToWcs(DWORD dwCp, LPCSTR szAnsi, LPWSTR szWide, DWORD dwLength) { if (!szWide) { dwLength = MultiByteToWideChar(dwCp, MB_ERR_INVALID_CHARS, szAnsi, -1, NULL, 0); - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + if (dwLength == 0) return NULL; if (!(szWide = s_malloc(WCHAR, dwLength + 1))) return NULL; @@ -515,12 +516,13 @@ return NULL; } -LPSTR WcsToMbs(DWORD dwCp, LPCWSTR szWide, LPSTR szAnsi, DWORD dwLength) +ACR_DECLARE(LPSTR) +WcsToMbs(DWORD dwCp, LPCWSTR szWide, LPSTR szAnsi, DWORD dwLength) { if (!szAnsi) { dwLength = WideCharToMultiByte(dwCp, 0, szWide, -1, NULL, 0, NULL, NULL); - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + if (dwLength == 0) return NULL; if (!(szAnsi = s_malloc(CHAR, dwLength + 1))) return NULL; 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=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/port/shquote.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/port/shquote.c Sat Jan 9 12:46:39 2010 @@ -302,3 +302,44 @@ return rv; } + +/* + * wcsquotev(): + * + * Apply wcsquote() to a set of strings, separating the results by spaces. + */ +size_t wcsquotev(int argc, wchar_t * const * argv, wchar_t *buf, size_t bufsize) +{ + size_t rv, callrv; + int i; + + rv = 0; + + if (argc == 0) { + if (bufsize != 0) + *buf = L'\0'; + return rv; + } + + for (i = 0; i < argc; i++) { + 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 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=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/args.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/args.c Sat Jan 9 12:46:39 2010 @@ -668,4 +668,3 @@ { return ACR_MergeArgsW(argv, NULL); } - 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=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/string.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/string.c Sat Jan 9 12:46:39 2010 @@ -1801,7 +1801,7 @@ return cnt; } -ACR_DECLARE(size_t) ACR_MszStrCountA(const char *s) +ACR_DECLARE(size_t) ACR_MszStrSizeA(const char *s, size_t *l) { size_t n = 0; const char *p; @@ -1811,10 +1811,12 @@ while (*p) p++; } + if (l) + *l = (size_t)(p - s); return n; } -ACR_DECLARE(size_t) ACR_MszStrCountW(const wchar_t *s) +ACR_DECLARE(size_t) ACR_MszStrSizeW(const wchar_t *s, size_t *l) { size_t n = 0; const wchar_t *p; @@ -1824,9 +1826,21 @@ while (*p) p++; } + if (l) + *l = (size_t)(p - s); return n; } +ACR_DECLARE(size_t) ACR_MszStrCountA(const char *s) +{ + return ACR_MszStrSizeA(s, NULL); +} + +ACR_DECLARE(size_t) ACR_MszStrCountW(const wchar_t *s) +{ + return ACR_MszStrSizeW(s, NULL); +} + ACR_DECLARE(jobjectArray) ACR_MszStrToStringArrayA(JNIEnv *_E, const char *str) { 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=897438&r1=897437&r2=897438&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c Sat Jan 9 12:46:39 2010 @@ -54,6 +54,8 @@ #define PRINT_PSTR "%S" #define STD_PREFIX L"acr-test-" #define _TXT(X) L ## X +static LPWSTR wide_args[64]; +static LPWSTR *wargv = NULL; #else extern mode_t acr_default_umask; extern mode_t acr_default_perms; @@ -454,7 +456,7 @@ i = ACR_StrMatchA(argv[0], argv[1], &mp, 0); printf("smatch returned %d\n", i); printf("smatch ended on '%s'\n", argv[0] + mp); -#if 0 +#if 0 { char buf[1024]; @@ -575,9 +577,13 @@ 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); +#else rc = ACR_ExecShellCmd(exe, argv[0], NULL); - +#endif fprintf(stdout, "[STDOUT]:\n%s", ACR_ExecStream(exe, 1)); fprintf(stdout, "[STDERR]:\n%s", ACR_ExecStream(exe, 2)); fprintf(stdout, "\n[EXITWHY]: %d\n[EXITVAL]: %d\n[EXITPID]: %d\n", @@ -594,8 +600,11 @@ return ACR_EINVAL; } exe = ACR_ExecNew(ACR_PROC_HAS_STDOUT | ACR_PROC_HAS_STDERR); +#if defined(WIN32) + rc = ACR_ExecShellScript(exe, wargv[0], &wargv[1], NULL); +#else rc = ACR_ExecShellScript(exe, argv[0], &argv[1], NULL); - +#endif fprintf(stdout, "[STDOUT]:\n%s", ACR_ExecStream(exe, 1)); fprintf(stdout, "[STDERR]:\n%s", ACR_ExecStream(exe, 2)); fprintf(stdout, "\n[EXITWHY]: %d\n[EXITVAL]: %d\n[EXITPID]: %d\n", @@ -612,8 +621,11 @@ return ACR_EINVAL; } exe = ACR_ExecNew(ACR_PROC_HAS_STDOUT | ACR_PROC_HAS_STDERR); +#if defined(WIN32) + rc = ACR_ExecProgram(exe, wargv[0], &wargv[1], NULL); +#else rc = ACR_ExecProgram(exe, argv[0], &argv[1], NULL); - +#endif fprintf(stdout, "[STDOUT]:\n%s", ACR_ExecStream(exe, 1)); fprintf(stdout, "[STDERR]:\n%s", ACR_ExecStream(exe, 2)); fprintf(stdout, "\n[EXITWHY]: %d\n[EXITVAL]: %d\n[EXITPID]: %d\n", @@ -630,8 +642,11 @@ return ACR_EINVAL; } exe = ACR_ExecNew(ACR_PROC_DETACHED); +#if defined(WIN32) + rc = ACR_ExecProgram(exe, wargv[0], &wargv[1], NULL); +#else rc = ACR_ExecProgram(exe, argv[0], &argv[1], NULL); - +#endif fprintf(stdout, "[STDOUT]:\n%s", ACR_ExecStream(exe, 1)); fputc('\n', stdout); fprintf(stdout, "[STDERR]:\n%s", ACR_ExecStream(exe, 2)); @@ -648,6 +663,7 @@ acr_getopt_t *os; int ch; const char *run_test = NULL; + fprintf(stdout, "Running Apache Commons Runtime %s (%s version) test suite.\n", ACR_VERSION_STRING, ACR_GetLibraryBuilt()); @@ -664,6 +680,16 @@ return ACR_GET_OS_ERROR(); } +#if defined(WIN32) + wargv = wide_args; + for (ch = 0; ch < argc; ch++) { + if (ch > 62) + break; + wide_args[ch] = MbsToWcs(CP_ACP, argv[ch], NULL, 0); + } + wide_args[ch] = NULL; +#endif + while ((ch = ACR_Getopt(os, "W;ht:", toptions, NULL)) != -1) { switch (ch) { @@ -683,6 +709,9 @@ } argc -= os->ind; argv += os->ind; +#if defined(WIN32) + wargv += os->ind; +#endif if (ACR_EnvHas("ACR_TEST")) { run_test = ACR_EnvGet("ACR_TEST"); }