]> Cypherpunks repositories - gostls13.git/commitdiff
add directory argument to os.ForkExec
authorRuss Cox <rsc@golang.org>
Fri, 15 May 2009 17:32:05 +0000 (10:32 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 15 May 2009 17:32:05 +0000 (10:32 -0700)
R=iant
DELTA=41  (35 added, 0 deleted, 6 changed)
OCL=28892
CL=28895

src/lib/exec/exec.go
src/lib/os/exec.go
src/lib/os/os_test.go
src/lib/syscall/exec.go

index c13bad3e07ba5ffb0ff8c048901e1451ee2f944a..29f25df651bce568281b6a49bd0c034fd7edbe96 100644 (file)
@@ -96,7 +96,7 @@ func Run(argv0 string, argv, envv []string, stdin, stdout, stderr int) (p *Cmd,
        }
 
        // Run command.
-       p.Pid, err = os.ForkExec(argv0, argv, envv, &fd);
+       p.Pid, err = os.ForkExec(argv0, argv, envv, "", &fd);
        if err != nil {
                goto Error;
        }
index 6c0b35578583705d24fb596d6a364163000aa8d3..1fbd7e7aae223a86f7c386c0cf4dc4069184d0b2 100644 (file)
@@ -15,7 +15,8 @@ import (
 // file descriptors to be set up in the new process: fd[0] will be Unix file
 // descriptor 0 (standard input), fd[1] descriptor 1, and so on.  A nil entry
 // will cause the child to have no open file descriptor with that index.
-func ForkExec(argv0 string, argv []string, envv []string, fd []*File)
+// If dir is not empty, the child chdirs into the directory before execing the program.
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File)
        (pid int, err Error)
 {
        // Create array of integer (system) fds.
@@ -28,7 +29,7 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []*File)
                }
        }
 
-       p, e := syscall.ForkExec(argv0, argv, envv, intfd);
+       p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd);
        return int(p), ErrnoToError(e);
 }
 
index e1e2d4b4b3976950140ca10fbd24987848877e15..7c503bfe6258dc499ff19ca603abab5316ecf9aa 100644 (file)
@@ -6,6 +6,7 @@ package os
 
 import (
        "fmt";
+       "io";
        "os";
        "testing";
 )
@@ -299,3 +300,24 @@ func TestLongSymlink(t *testing.T) {
                t.Fatalf("after symlink %q != %q", r, s);
        }
 }
+
+func TestForkExec(t *testing.T) {
+       r, w, err := Pipe();
+       if err != nil {
+               t.Fatalf("Pipe: %v", err);
+       }
+       pid, err := ForkExec("/bin/pwd", []string{"pwd"}, nil, "/", []*File{nil, w, os.Stderr});
+       if err != nil {
+               t.Fatalf("ForkExec: %v", err);
+       }
+       w.Close();
+
+       var b io.ByteBuffer;
+       io.Copy(r, &b);
+       output := string(b.Data());
+       expect := "/\n";
+       if output != expect {
+               t.Errorf("exec /bin/pwd returned %q wanted %q", output, expect);
+       }
+       Wait(pid, 0);
+}
index 809cd8c578d6873f89b371364b17415417de3236..63d7821089accf48b83fc6e0d3018bff52d81e7e 100644 (file)
@@ -99,7 +99,7 @@ func Wait4(pid int64, wstatus *WaitStatus, options int64, rusage *Rusage)
 // no rescheduling, no malloc calls, and no new stack segments.
 // The calls to RawSyscall are okay because they are assembly
 // functions that do not grow the stack.
-func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, fd []int64, pipe int64)
+func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, dir *byte, fd []int64, pipe int64)
        (pid int64, err int64)
 {
        // Declare all variables at top in case any
@@ -132,6 +132,14 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, fd []int64, pip
 
        // Fork succeeded, now in child.
 
+       // Chdir
+       if dir != nil {
+               r1, r2, err = RawSyscall(SYS_CHDIR, int64(uintptr(unsafe.Pointer(dir))), 0, 0);
+               if err != 0 {
+                       goto childerror;
+               }
+       }
+
        // Pass 1: look for fd[i] < i and move those up above len(fd)
        // so that pass 2 won't stomp on an fd it needs later.
        nextfd = int64(len(fd));
@@ -210,7 +218,7 @@ childerror:
 }
 
 // Combination of fork and exec, careful to be thread safe.
-func ForkExec(argv0 string, argv []string, envv []string, fd []int64)
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int64)
        (pid int64, err int64)
 {
        var p [2]int64;
@@ -225,6 +233,10 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []int64)
        argv0p := StringBytePtr(argv0);
        argvp := StringArrayPtr(argv);
        envvp := StringArrayPtr(envv);
+       var dirp *byte;
+       if len(dir) > 0 {
+               dirp = StringBytePtr(dir);
+       }
 
        // Acquire the fork lock so that no other threads
        // create new fds that are not yet close-on-exec
@@ -243,7 +255,7 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []int64)
        }
 
        // Kick off child.
-       pid, err = forkAndExecInChild(argv0p, argvp, envvp, fd, p[1]);
+       pid, err = forkAndExecInChild(argv0p, argvp, envvp, dirp, fd, p[1]);
        if err != 0 {
        error:
                if p[0] >= 0 {