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(&current_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");
     }


Reply via email to