merged fork/exec into one, in order to use vfork
authorClaus Gittinger <cg@exept.de>
Sat, 16 Dec 1995 03:21:11 +0100
changeset 771 1ad3f852e201
parent 770 402958905760
child 772 f86b117950c5
merged fork/exec into one, in order to use vfork (child may only perform read accesses ultrix - so we cannot create an Array to pass args; now command execution is as fast as everywhere on ultrix)
Unix.st
--- a/Unix.st	Sat Dec 16 02:23:39 1995 +0100
+++ b/Unix.st	Sat Dec 16 03:21:11 1995 +0100
@@ -1796,12 +1796,32 @@
 exec:aPath withArguments:argArray
     "execute the unix command specified by the argument, aPath, with
      arguments in argArray (no arguments, if nil).
-     If successful, this method does not return and smalltalk is gone.
-     If not successful, false is returned. Normal use is with forkForCommand."
+     If successful, this method does NOT return and smalltalk is gone.
+     If not successful, false is returned. Can be used with fork or to transfer
+     to another program."
+
+    self exec:aPath withArguments:argArray fork:false
+!
+
+exec:aPath withArguments:argArray fork:doFork
+    "Internal combined fork & exec;
+     If fork is false:
+         execute the unix command specified by the argument, aPath, with
+         arguments in argArray (no arguments, if nil).
+         If successful, this method does not return and smalltalk is gone.
+         If not successful, false is returned. Normal use is with forkForCommand.
+     if its true:
+	for a child to do the above.
+	The id of the child process is returned.
+
+    Notice: this used to be two separate ST-methods; however, in order to use
+   	    vfork on some machines, it had to be merged into one, to avoid write
+	    accesses to ST/X memory from the vforked-child. The code below only does
+	    read accesses."
 
 %{
     char **argv;
-    int nargs, i;
+    int nargs, i, id;
     OBJ arg;
 
     if (__isString(aPath) && ((argArray == nil) || __isArray(argArray))) {
@@ -1817,13 +1837,29 @@
 		}
 	    }
 	    argv[i] = NULL;
-	    execv(_stringVal(aPath), argv);
-	    /* 
-	     * should not be reached
-	     * (well, it is, if you pass a wrong command-path)
-	     */
-	    free(argv);
-	    RETURN ( false );
+
+	    if (doFork == true) {
+#ifdef HAS_VFORK
+		id = vfork();
+#else
+		id = fork();
+#endif
+		if (id == 0) {
+	            execv(_stringVal(aPath), argv);
+		    /* should not be reached */
+		    _exit(1);
+		}
+		free(argv);
+		RETURN (__MKSMALLINT(id));
+	    } else {
+	        execv(_stringVal(aPath), argv);
+	        /* 
+	         * should not be reached
+	         * (well, it is, if you pass a wrong command-path)
+	         */
+	        free(argv);
+	        RETURN ( false );
+	    }
 	}
     }
 %}.
@@ -1837,7 +1873,7 @@
     "
      |id|
 
-     id := OperatingSystem forkForCommand.
+     id := OperatingSystem fork.
      id == 0 ifTrue:[
 	"I am the child"
 	OperatingSystem exec:'/bin/ls' withArguments:#('ls' '/tmp').
@@ -1847,7 +1883,7 @@
     "
      |id|
 
-     id := OperatingSystem forkForCommand.
+     id := OperatingSystem fork.
      id == 0 ifTrue:[
 	"I am the child"
 	OperatingSystem exec:'/bin/sh' withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2').
@@ -1918,8 +1954,7 @@
      unix-process-id) to the parent (original) process.
 
      In normal situations, you dont need to use this low level entry; see
-     #startProcess: and #executCommand: for higher level interfaces.
-     If you need a process for command execution, please use forkForCommand."
+     #startProcess: and #executCommand: for higher level interfaces."
 
 %{  /* NOCONTEXT */
 
@@ -1938,25 +1973,6 @@
     "
 !
 
-forkForCommand
-    "fork a new (HEAVY-weight) unix process for command execution.
-     See description of fork for what it does.
-     This one should be used, if all you need a new proces for is to
-     execute another command. On some systems (namely old SYSV3 / BSD systems),
-    this executes faster thatn fork."
-
-%{  /* NOCONTEXT */
-    int pid;
-
-#ifdef HAS_VFORK
-    pid = vfork();
-#else
-    pid = fork();
-#endif
-    RETURN ( _MKSMALLINT(pid) );
-%}
-!
-
 pathOfCommand:aCommand
     "find where aCommand's executable file is"
 
@@ -1988,18 +2004,10 @@
      Use #waitForProcess: for synchronization and exec status return,
      or #killProcess: to stop it."
 
-     |id|
-
-     id := self forkForCommand.
-     id == 0 ifTrue:[
-	"I am the child"
-	self exec:'/bin/sh' withArguments:(Array with:'sh' 
-						 with:'-c' 
-						 with:aCommandString).
-	self exit:1.
-	"not reached"
-     ].
-     ^ id
+    ^ self 
+	exec:'/bin/sh' 
+	withArguments:(Array with:'sh' with:'-c' with:aCommandString)
+	fork:true.
 
     "
      |pid|
@@ -5327,6 +5335,6 @@
 !OperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Attic/Unix.st,v 1.96 1995-12-15 22:40:29 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Attic/Unix.st,v 1.97 1995-12-16 02:21:11 cg Exp $'
 ! !
 OperatingSystem initialize!