#265219 AVIARY_1_0_20040515_BRANCH
authormkaply%us.ibm.com
Thu, 02 Dec 2004 17:47:52 +0000
branchAVIARY_1_0_20040515_BRANCH
changeset 3226 98b30e25cba57b9fe70a7f5ef924c3e8c5652dd4
parent 3177 e518471b7da4dc97fb8a777efbca3d66f837a84b
child 3227 0f767894d6c32e8b65453ed82408a1c0d92b1c7c
push idunknown
push userunknown
push dateunknown
bugs265219
#265219 r=mkaply, sr=wtc, a=mkaply (platform specific) Patch from Davide Bresolin - OS/2 only - add support for redirecting stdin/stdout of a child
pr/src/md/os2/os2misc.c
--- a/pr/src/md/os2/os2misc.c
+++ b/pr/src/md/os2/os2misc.c
@@ -1,41 +1,45 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
  * The Original Code is the Netscape Portable Runtime (NSPR).
- * 
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation.  Portions created by Netscape are 
- * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
- * Rights Reserved.
- * 
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
  * Contributor(s):
- * 
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable 
- * instead of those above.  If you wish to allow use of your 
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL.  If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
+ *   Davide Bresolin <davide@teamos2.it>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
 
 /*
  * os2misc.c
  *
  */
 #include <string.h>
 #include "primpl.h"
 
@@ -247,16 +251,29 @@ PRProcess * _PR_CreateOS2Process(
     PID       pid = 0;
     char     *pEnvWPS = NULL;
     char     *pszComSpec;
     char      pszEXEName[CCHMAXPATH] = "";
     char      pszFormatString[CCHMAXPATH];
     char      pszObjectBuffer[CCHMAXPATH];
     char     *pszFormatResult = NULL;
 
+    /*
+     * Variables for DosExecPgm
+     */
+    char szFailed[CCHMAXPATH];
+    char *pszCmdLine = NULL;
+    RESULTCODES procInfo;
+    HFILE hStdIn  = 0,
+          hStdOut = 0,
+          hStdErr = 0;
+    HFILE hStdInSave  = -1,
+          hStdOutSave = -1,
+          hStdErrSave = -1;
+
     proc = PR_NEW(PRProcess);
     if (!proc) {
         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         goto errorExit;
     }
    
     if (assembleCmdLine(argv, &cmdLine) == -1) {
         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
@@ -277,20 +294,16 @@ PRProcess * _PR_CreateOS2Process(
         }
         qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare);
     }
     if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         goto errorExit;
     }
   
-    if (attr) {
-       PR_ASSERT(!"Not implemented");
-    }
-
     rc = DosQueryAppType(path, &ulAppType);
     if (rc != NO_ERROR) {
        char *pszDot = strrchr(path, '.');
        if (pszDot) {
           /* If it is a CMD file, launch the users command processor */
           if (!stricmp(pszDot, ".cmd")) {
              rc = DosScanEnv("COMSPEC", &pszComSpec);
              if (!rc) {
@@ -336,28 +349,99 @@ PRProcess * _PR_CreateOS2Process(
     startData.PgmName = pszEXEName;
  
     startData.Length = sizeof(startData);
     startData.Related = SSF_RELATED_INDEPENDENT;
     startData.ObjectBuffer = pszObjectBuffer;
     startData.ObjectBuffLen = CCHMAXPATH;
     startData.Environment = envBlock;
  
-    rc = DosStartSession(&startData, &ulAppType, &pid);
+    if (attr) {
+        /* On OS/2, there is really no way to pass file handles for stdin,
+         * stdout, and stderr to a new process.  Instead, we can make it
+         * a child process and make the given file handles a copy of our
+         * stdin, stdout, and stderr.  The child process then inherits
+         * ours, and we set ours back.  Twisted and gross I know. If you
+         * know a better way, please use it.
+         */
+        if (attr->stdinFd) {
+            hStdIn = 0;
+            DosDupHandle(hStdIn, &hStdInSave);
+            DosDupHandle((HFILE) attr->stdinFd->secret->md.osfd, &hStdIn);
+        }
+
+        if (attr->stdoutFd) {
+            hStdOut = 1;
+            DosDupHandle(hStdOut, &hStdOutSave);
+            DosDupHandle((HFILE) attr->stdoutFd->secret->md.osfd, &hStdOut);
+        }
 
-    if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) {
-        PR_SetError(PR_UNKNOWN_ERROR, 0);
+        if (attr->stderrFd) {
+            hStdErr = 2;
+            DosDupHandle(hStdErr, &hStdErrSave);
+            DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr);
+        }
+        /*
+         * Build up the Command Line for DosExecPgm
+         */
+        pszCmdLine = PR_MALLOC(strlen(pszEXEName) +
+                               strlen(startData.PgmInputs) + 3);
+        sprintf(pszCmdLine, "%s%c%s%c", pszEXEName, '\0',
+                startData.PgmInputs, '\0');
+        rc = DosExecPgm(szFailed,
+                        CCHMAXPATH,
+                        EXEC_ASYNCRESULT,
+                        pszCmdLine,
+                        envBlock,
+                        &procInfo,
+                        pszEXEName);
+        PR_DELETE(pszCmdLine);
+
+        /* Restore our old values.  Hope this works */
+        if (hStdInSave != -1) {
+            DosDupHandle(hStdInSave, &hStdIn);
+            DosClose(hStdInSave);
+        }
+
+        if (hStdOutSave != -1) {
+            DosDupHandle(hStdOutSave, &hStdOut);
+            DosClose(hStdOutSave);
+        }
+
+        if (hStdErrSave != -1) {
+            DosDupHandle(hStdErrSave, &hStdErr);
+            DosClose(hStdErrSave);
+        }
+
+        if (rc != NO_ERROR) {
+            /* XXX what error code? */
+            PR_SetError(PR_UNKNOWN_ERROR, rc);
+            goto errorExit;
+        }
+
+        proc->md.pid = procInfo.codeTerminate;
+    } else {	
+        /*
+         * If no STDIN/STDOUT redirection is not needed, use DosStartSession
+         * to create a new, independent session
+         */
+        rc = DosStartSession(&startData, &ulAppType, &pid);
+
+        if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) {
+            PR_SetError(PR_UNKNOWN_ERROR, rc);
+            goto errorExit;
+        }
+ 
+        proc->md.pid = pid;
     }
- 
-    proc->md.pid = pid;
 
     if (pszFormatResult) {
         PR_DELETE(pszFormatResult);
     }
- 
+
     PR_DELETE(cmdLine);
     if (newEnvp) {
         PR_DELETE(newEnvp);
     }
     if (envBlock) {
         PR_DELETE(envBlock);
     }
     return proc;
@@ -475,43 +559,8 @@ PRStatus _MD_MemUnmap(void *addr, PRUint
 }
 
 PRStatus _MD_CloseFileMap(PRFileMap *fmap)
 {
     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
     return PR_FAILURE;
 }
 
-/*
- *  Automatically set apptype switch for interactive and other
- *  tests that create an invisible plevent window.
- */
-unsigned long _System _DLL_InitTerm( unsigned long mod_handle, unsigned long flag)
-{
-   unsigned long rc = 0; /* failure */
-
-   if( !flag)
-   {
-      /* init */
-      if( _CRT_init() == 0)
-      {
-         PPIB pPib;
-         PTIB pTib;
-
-         /* probably superfluous, but can't hurt */
-         __ctordtorInit(0);
-
-         DosGetInfoBlocks( &pTib, &pPib);
-         pPib->pib_ultype = 3; /* PM */
-
-         rc = 1;
-      }
-   }
-   else
-   {
-      __ctordtorTerm(0);
-      _CRT_term();
-      rc = 1;
-   }
-
-   return rc;
-}
-