Commit b725e32c authored by Russ Cox's avatar Russ Cox

add directory argument to os.ForkExec

R=iant
DELTA=41  (35 added, 0 deleted, 6 changed)
OCL=28892
CL=28895
parent a854c7f9
...@@ -96,7 +96,7 @@ func Run(argv0 string, argv, envv []string, stdin, stdout, stderr int) (p *Cmd, ...@@ -96,7 +96,7 @@ func Run(argv0 string, argv, envv []string, stdin, stdout, stderr int) (p *Cmd,
} }
// Run command. // Run command.
p.Pid, err = os.ForkExec(argv0, argv, envv, &fd); p.Pid, err = os.ForkExec(argv0, argv, envv, "", &fd);
if err != nil { if err != nil {
goto Error; goto Error;
} }
......
...@@ -15,7 +15,8 @@ import ( ...@@ -15,7 +15,8 @@ import (
// file descriptors to be set up in the new process: fd[0] will be Unix file // 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 // 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. // 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) (pid int, err Error)
{ {
// Create array of integer (system) fds. // Create array of integer (system) fds.
...@@ -28,7 +29,7 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []*File) ...@@ -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); return int(p), ErrnoToError(e);
} }
......
...@@ -6,6 +6,7 @@ package os ...@@ -6,6 +6,7 @@ package os
import ( import (
"fmt"; "fmt";
"io";
"os"; "os";
"testing"; "testing";
) )
...@@ -299,3 +300,24 @@ func TestLongSymlink(t *testing.T) { ...@@ -299,3 +300,24 @@ func TestLongSymlink(t *testing.T) {
t.Fatalf("after symlink %q != %q", r, s); 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);
}
...@@ -99,7 +99,7 @@ func Wait4(pid int64, wstatus *WaitStatus, options int64, rusage *Rusage) ...@@ -99,7 +99,7 @@ func Wait4(pid int64, wstatus *WaitStatus, options int64, rusage *Rusage)
// no rescheduling, no malloc calls, and no new stack segments. // no rescheduling, no malloc calls, and no new stack segments.
// The calls to RawSyscall are okay because they are assembly // The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack. // 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) (pid int64, err int64)
{ {
// Declare all variables at top in case any // Declare all variables at top in case any
...@@ -132,6 +132,14 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, fd []int64, pip ...@@ -132,6 +132,14 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, fd []int64, pip
// Fork succeeded, now in child. // 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) // 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. // so that pass 2 won't stomp on an fd it needs later.
nextfd = int64(len(fd)); nextfd = int64(len(fd));
...@@ -210,7 +218,7 @@ childerror: ...@@ -210,7 +218,7 @@ childerror:
} }
// Combination of fork and exec, careful to be thread safe. // 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) (pid int64, err int64)
{ {
var p [2]int64; var p [2]int64;
...@@ -225,6 +233,10 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []int64) ...@@ -225,6 +233,10 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []int64)
argv0p := StringBytePtr(argv0); argv0p := StringBytePtr(argv0);
argvp := StringArrayPtr(argv); argvp := StringArrayPtr(argv);
envvp := StringArrayPtr(envv); envvp := StringArrayPtr(envv);
var dirp *byte;
if len(dir) > 0 {
dirp = StringBytePtr(dir);
}
// Acquire the fork lock so that no other threads // Acquire the fork lock so that no other threads
// create new fds that are not yet close-on-exec // create new fds that are not yet close-on-exec
...@@ -243,7 +255,7 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []int64) ...@@ -243,7 +255,7 @@ func ForkExec(argv0 string, argv []string, envv []string, fd []int64)
} }
// Kick off child. // 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 { if err != 0 {
error: error:
if p[0] >= 0 { if p[0] >= 0 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment