Added PR_ProcessAttrSetCurrentDirectory to allow setting the current
authorwtc%netscape.com
Fri, 18 Sep 1998 02:15:21 +0000
changeset 242 fdee486f4e5fba7e8b6822213284431dee7d6e8e
parent 241 031608abdfe6e6fe617c6b0eb70d54bfe45a0ffc
child 243 fad36bc76035f56da4403922e68c298a8f6ae8f9
push idunknown
push userunknown
push dateunknown
Added PR_ProcessAttrSetCurrentDirectory to allow setting the current working directory of the new process. PR_SetStdioRedirect is renamed PR_ProcessAttrSetStdioRedirect. The old name is retained but moved to obsolete/probslet.h. This work is contributed by Ben Laurie <ben@algroup.co.ul>. Files changed: prproces.h, probslet.h, primpl.h, uxproces.c, ntmisc.c, prinit.c, and parent.c.
pr/include/obsolete/probslet.h
pr/include/private/primpl.h
pr/include/prproces.h
pr/src/md/unix/uxproces.c
pr/src/md/windows/ntmisc.c
pr/src/misc/prinit.c
pr/tests/parent.c
--- a/pr/include/obsolete/probslet.h
+++ b/pr/include/obsolete/probslet.h
@@ -20,16 +20,17 @@
 ** A collection of things thought to be obsolete
 */
 
 #if defined(PROBSLET_H)
 #else
 #define PROBSLET_H
 
 #include "prio.h"
+#include "prproces.h"
 
 PR_BEGIN_EXTERN_C
 
 /*
 ** Yield the current thread.  The proper function to use in place of
 ** PR_Yield() is PR_Sleep() with an argument of PR_INTERVAL_NO_WAIT.
 */
 PR_EXTERN(PRStatus) PR_Yield(void);
@@ -213,13 +214,19 @@ PR_EXTERN(PRStatus) PR_DestroyNetAddr(PR
 PR_EXTERN(PRStatus) PR_GetHostName(char *name, PRUint32 namelen);
 
 /*
 ** Return the current thread's last error string.
 ** obsoleted by PR_GetErrorText().
 */
 PR_EXTERN(const char *) PR_GetErrorString(void);
 
+PR_EXTERN(void) PR_SetStdioRedirect(
+    PRProcessAttr *attr,
+    PRSpecialFD stdioFd,
+    PRFileDesc *redirectFd
+);
+
 PR_END_EXTERN_C
 
 #endif /* defined(PROBSLET_H) */
 
 /* probslet.h */
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -1366,16 +1366,17 @@ struct PRThread {
     _MDThread md;
 #endif /* defined(_PR_PTHREADS) */
 };
 
 struct PRProcessAttr {
     PRFileDesc *stdinFd;
     PRFileDesc *stdoutFd;
     PRFileDesc *stderrFd;
+    char *currentDirectory;
 };
 
 struct PRProcess {
     _MDProcess md;
 };
 
 struct PRFileMap {
     PRFileDesc *fd;
--- a/pr/include/prproces.h
+++ b/pr/include/prproces.h
@@ -32,22 +32,27 @@ typedef struct PRProcess PRProcess;
 typedef struct PRProcessAttr PRProcessAttr;
 
 PR_EXTERN(PRProcessAttr *) PR_NewProcessAttr(void);
 
 PR_EXTERN(void) PR_ResetProcessAttr(PRProcessAttr *attr);
 
 PR_EXTERN(void) PR_DestroyProcessAttr(PRProcessAttr *attr);
 
-PR_EXTERN(void) PR_SetStdioRedirect(
+PR_EXTERN(void) PR_ProcessAttrSetStdioRedirect(
     PRProcessAttr *attr,
     PRSpecialFD stdioFd,
     PRFileDesc *redirectFd
 );
 
+PR_EXTERN(PRStatus) PR_ProcessAttrSetCurrentDirectory(
+    PRProcessAttr *attr,
+    const char *dir
+);
+
 /*
 ** Create a new process
 **
 ** Create a new process executing the file specified as 'path' and with
 ** the supplied arguments and environment.
 **
 ** This function may fail because of illegal access (permissions),
 ** invalid arguments or insufficient resources.
--- a/pr/src/md/unix/uxproces.c
+++ b/pr/src/md/unix/uxproces.c
@@ -164,16 +164,21 @@ ForkAndExec(
             }
             if (attr->stderrFd
                     && attr->stderrFd->secret->md.osfd != 2) {
                 if (dup2(attr->stderrFd->secret->md.osfd, 2) != 2) {
                     _exit(1);  /* failed */
                 }
                 close(attr->stderrFd->secret->md.osfd);
             }
+            if (attr->currentDirectory) {
+                if (chdir(attr->currentDirectory) < 0) {
+                    _exit(1);  /* failed */
+                }
+            }
         }
 
         (void)execve(path, argv, envp);
         /* Whoops! It returned. That's a bad sign. */
         _exit(1);
     }
 
 #if defined(_PR_NATIVE_THREADS)
--- a/pr/src/md/windows/ntmisc.c
+++ b/pr/src/md/windows/ntmisc.c
@@ -426,17 +426,17 @@ PRProcess * _PR_CreateWindowsProcess(
                            TRUE,  /* inherit handles */
                            0,     /* creation flags */
                            envBlock,  /* an environment block, consisting
                                        * of a null-terminated block of
                                        * null-terminated strings.  Each
                                        * string is in the form:
                                        *     name=value
                                        * XXX: usually NULL */
-                           NULL,  /* current drive and directory */
+                           attr->currentDirectory,  /* current drive and directory */
                            &startupInfo,
                            &procInfo
                           );
     if (retVal == FALSE) {
         /* XXX what error code? */
         PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
         goto errorExit;
     }
@@ -624,28 +624,28 @@ PRStatus _MD_CloseFileMap(PRFileMap *fma
 
 #pragma warning(disable: 4035)
 PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
 {
     __asm
     {
         mov ecx, val
         mov eax, 1
-        xadd dword ptr [ecx], eax
+        lock xadd dword ptr [ecx], eax
         inc eax
     }
 }
 #pragma warning(default: 4035)
 
 #pragma warning(disable: 4035)
 PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
 {
     __asm
     {
         mov ecx, val
         mov eax, 0ffffffffh
-        xadd dword ptr [ecx], eax
+        lock xadd dword ptr [ecx], eax
         dec eax
     }
 }
 #pragma warning(default: 4035)
 
 #endif /* x86 processors */
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -377,47 +377,82 @@ PR_NewProcessAttr(void)
         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     }
     return attr;
 }
 
 PR_IMPLEMENT(void)
 PR_ResetProcessAttr(PRProcessAttr *attr)
 {
+    PR_FREEIF(attr->currentDirectory);
     memset(attr, 0, sizeof(*attr));
 }
 
 PR_IMPLEMENT(void)
 PR_DestroyProcessAttr(PRProcessAttr *attr)
 {
+    PR_FREEIF(attr->currentDirectory);
     PR_DELETE(attr);
 }
 
 PR_IMPLEMENT(void)
-PR_SetStdioRedirect(
+PR_ProcessAttrSetStdioRedirect(
     PRProcessAttr *attr,
     PRSpecialFD stdioFd,
-    PRFileDesc *redirectFd
-)
+    PRFileDesc *redirectFd)
 {
     switch (stdioFd) {
         case PR_StandardInput:
             attr->stdinFd = redirectFd;
             break;
         case PR_StandardOutput:
             attr->stdoutFd = redirectFd;
             break;
         case PR_StandardError:
             attr->stderrFd = redirectFd;
             break;
         default:
             PR_ASSERT(0);
     }
 }
 
+/*
+ * OBSOLETE
+ */
+PR_IMPLEMENT(void)
+PR_SetStdioRedirect(
+    PRProcessAttr *attr,
+    PRSpecialFD stdioFd,
+    PRFileDesc *redirectFd)
+{
+#if defined(DEBUG)
+    static PRBool warn = PR_TRUE;
+    if (warn) {
+        warn = _PR_Obsolete("PR_SetStdioRedirect()",
+                "PR_ProcessAttrSetStdioRedirect()");
+    }
+#endif
+    PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd);
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_ProcessAttrSetCurrentDirectory(
+    PRProcessAttr *attr,
+    const char *dir)
+{
+    PR_FREEIF(attr->currentDirectory);
+    attr->currentDirectory = PR_MALLOC(strlen(dir) + 1);
+    if (!attr->currentDirectory) {
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+        return PR_FAILURE;
+    }
+    strcpy(attr->currentDirectory, dir);
+    return PR_SUCCESS;
+}
+
 PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
     const char *path,
     char *const *argv,
     char *const *envp,
     const PRProcessAttr *attr)
 {
     return _PR_MD_CREATE_PROCESS(path, argv, envp, attr);
 }  /* PR_CreateProcess */
--- a/pr/tests/parent.c
+++ b/pr/tests/parent.c
@@ -71,20 +71,20 @@ PRIntn main (PRIntn argc, char **argv)
         PrintUsage();
         return 2;
     }
 
     child->name = *argv;
     if (NULL != debug) PR_fprintf(debug, "Forking %s\n", child->name);
 
     child->attr = PR_NewProcessAttr();
-    PR_SetStdioRedirect(
+    PR_ProcessAttrSetStdioRedirect(
         child->attr, PR_StandardOutput,
         PR_GetSpecialFD(PR_StandardOutput));
-    PR_SetStdioRedirect(
+    PR_ProcessAttrSetStdioRedirect(
         child->attr, PR_StandardError,
         PR_GetSpecialFD(PR_StandardError));
 
     child->process = PR_CreateProcess(
         child->name, argv, NULL, child->attr);
 
     test_status = (NULL == child->process) ? 1 : 0;
     if (NULL != debug)