os: implement new Process api

Fixes #1004.
Fixes #1460.

R=mattn, r, niemeyer, rog, rsc
CC=golang-dev
https://golang.org/cl/4029053
diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go
index a6f509d..59529a6 100644
--- a/src/cmd/cgo/util.go
+++ b/src/cmd/cgo/util.go
@@ -32,10 +32,11 @@
 	if err != nil {
 		fatal("%s", err)
 	}
-	pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})
+	p, err := os.StartProcess(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})
 	if err != nil {
 		fatal("%s", err)
 	}
+	defer p.Release()
 	r0.Close()
 	w1.Close()
 	w2.Close()
@@ -55,7 +56,7 @@
 	<-c
 	<-c
 
-	w, err := os.Wait(pid, 0)
+	w, err := p.Wait(0)
 	if err != nil {
 		fatal("%s", err)
 	}
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index f1b11a7..968b8e0 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -83,20 +83,21 @@
 	if *verbose {
 		log.Printf("executing %v", args)
 	}
-	pid, err := os.ForkExec(bin, args, os.Environ(), *goroot, fds)
+	p, err := os.StartProcess(bin, args, os.Environ(), *goroot, fds)
 	defer r.Close()
 	w.Close()
 	if err != nil {
-		log.Printf("os.ForkExec(%q): %v", bin, err)
+		log.Printf("os.StartProcess(%q): %v", bin, err)
 		return 2
 	}
+	defer p.Release()
 
 	var buf bytes.Buffer
 	io.Copy(&buf, r)
-	wait, err := os.Wait(pid, 0)
+	wait, err := p.Wait(0)
 	if err != nil {
 		os.Stderr.Write(buf.Bytes())
-		log.Printf("os.Wait(%d, 0): %v", pid, err)
+		log.Printf("os.Wait(%d, 0): %v", p.Pid, err)
 		return 2
 	}
 	status = wait.ExitStatus()
diff --git a/src/pkg/exec/exec.go b/src/pkg/exec/exec.go
index 4f4c8c7..80f6f3c 100644
--- a/src/pkg/exec/exec.go
+++ b/src/pkg/exec/exec.go
@@ -22,12 +22,12 @@
 // Stdin, Stdout, and Stderr are Files representing pipes
 // connected to the running command's standard input, output, and error,
 // or else nil, depending on the arguments to Run.
-// Pid is the running command's operating system process ID.
+// Process represents the underlying operating system process.
 type Cmd struct {
-	Stdin  *os.File
-	Stdout *os.File
-	Stderr *os.File
-	Pid    int
+	Stdin   *os.File
+	Stdout  *os.File
+	Stderr  *os.File
+	Process *os.Process
 }
 
 // PathError records the name of a binary that was not
@@ -88,24 +88,24 @@
 // If a parameter is Pipe, then the corresponding field (Stdin, Stdout, Stderr)
 // of the returned Cmd is the other end of the pipe.
 // Otherwise the field in Cmd is nil.
-func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
-	p = new(Cmd)
+func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (c *Cmd, err os.Error) {
+	c = new(Cmd)
 	var fd [3]*os.File
 
-	if fd[0], p.Stdin, err = modeToFiles(stdin, 0); err != nil {
+	if fd[0], c.Stdin, err = modeToFiles(stdin, 0); err != nil {
 		goto Error
 	}
-	if fd[1], p.Stdout, err = modeToFiles(stdout, 1); err != nil {
+	if fd[1], c.Stdout, err = modeToFiles(stdout, 1); err != nil {
 		goto Error
 	}
 	if stderr == MergeWithStdout {
 		fd[2] = fd[1]
-	} else if fd[2], p.Stderr, err = modeToFiles(stderr, 2); err != nil {
+	} else if fd[2], c.Stderr, err = modeToFiles(stderr, 2); err != nil {
 		goto Error
 	}
 
 	// Run command.
-	p.Pid, err = os.ForkExec(name, argv, envv, dir, fd[0:])
+	c.Process, err = os.StartProcess(name, argv, envv, dir, fd[0:])
 	if err != nil {
 		goto Error
 	}
@@ -118,7 +118,7 @@
 	if fd[2] != os.Stderr && fd[2] != fd[1] {
 		fd[2].Close()
 	}
-	return p, nil
+	return c, nil
 
 Error:
 	if fd[0] != os.Stdin && fd[0] != nil {
@@ -130,63 +130,67 @@
 	if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] {
 		fd[2].Close()
 	}
-	if p.Stdin != nil {
-		p.Stdin.Close()
+	if c.Stdin != nil {
+		c.Stdin.Close()
 	}
-	if p.Stdout != nil {
-		p.Stdout.Close()
+	if c.Stdout != nil {
+		c.Stdout.Close()
 	}
-	if p.Stderr != nil {
-		p.Stderr.Close()
+	if c.Stderr != nil {
+		c.Stderr.Close()
+	}
+	if c.Process != nil {
+		c.Process.Release()
 	}
 	return nil, err
 }
 
-// Wait waits for the running command p,
-// returning the Waitmsg returned by os.Wait and an error.
-// The options are passed through to os.Wait.
-// Setting options to 0 waits for p to exit;
+// Wait waits for the running command c,
+// returning the Waitmsg returned when the process exits.
+// The options are passed to the process's Wait method.
+// Setting options to 0 waits for c to exit;
 // other options cause Wait to return for other
 // process events; see package os for details.
-func (p *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
-	if p.Pid <= 0 {
+func (c *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
+	if c.Process == nil {
 		return nil, os.ErrorString("exec: invalid use of Cmd.Wait")
 	}
-	w, err := os.Wait(p.Pid, options)
+	w, err := c.Process.Wait(options)
 	if w != nil && (w.Exited() || w.Signaled()) {
-		p.Pid = -1
+		c.Process.Release()
+		c.Process = nil
 	}
 	return w, err
 }
 
-// Close waits for the running command p to exit,
+// Close waits for the running command c to exit,
 // if it hasn't already, and then closes the non-nil file descriptors
-// p.Stdin, p.Stdout, and p.Stderr.
-func (p *Cmd) Close() os.Error {
-	if p.Pid > 0 {
+// c.Stdin, c.Stdout, and c.Stderr.
+func (c *Cmd) Close() os.Error {
+	if c.Process != nil {
 		// Loop on interrupt, but
 		// ignore other errors -- maybe
 		// caller has already waited for pid.
-		_, err := p.Wait(0)
+		_, err := c.Wait(0)
 		for err == os.EINTR {
-			_, err = p.Wait(0)
+			_, err = c.Wait(0)
 		}
 	}
 
 	// Close the FDs that are still open.
 	var err os.Error
-	if p.Stdin != nil && p.Stdin.Fd() >= 0 {
-		if err1 := p.Stdin.Close(); err1 != nil {
+	if c.Stdin != nil && c.Stdin.Fd() >= 0 {
+		if err1 := c.Stdin.Close(); err1 != nil {
 			err = err1
 		}
 	}
-	if p.Stdout != nil && p.Stdout.Fd() >= 0 {
-		if err1 := p.Stdout.Close(); err1 != nil && err != nil {
+	if c.Stdout != nil && c.Stdout.Fd() >= 0 {
+		if err1 := c.Stdout.Close(); err1 != nil && err != nil {
 			err = err1
 		}
 	}
-	if p.Stderr != nil && p.Stderr != p.Stdout && p.Stderr.Fd() >= 0 {
-		if err1 := p.Stderr.Close(); err1 != nil && err != nil {
+	if c.Stderr != nil && c.Stderr != c.Stdout && c.Stderr.Fd() >= 0 {
+		if err1 := c.Stderr.Close(); err1 != nil && err != nil {
 			err = err1
 		}
 	}
diff --git a/src/pkg/http/triv.go b/src/pkg/http/triv.go
index 03cfafa..52d521d 100644
--- a/src/pkg/http/triv.go
+++ b/src/pkg/http/triv.go
@@ -99,15 +99,16 @@
 		fmt.Fprintf(rw, "pipe: %s\n", err)
 		return
 	}
-	pid, err := os.ForkExec("/bin/date", []string{"date"}, os.Environ(), "", []*os.File{nil, w, w})
+	p, err := os.StartProcess("/bin/date", []string{"date"}, os.Environ(), "", []*os.File{nil, w, w})
 	defer r.Close()
 	w.Close()
 	if err != nil {
 		fmt.Fprintf(rw, "fork/exec: %s\n", err)
 		return
 	}
+	defer p.Release()
 	io.Copy(rw, r)
-	wait, err := os.Wait(pid, 0)
+	wait, err := p.Wait(0)
 	if err != nil {
 		fmt.Fprintf(rw, "wait: %s\n", err)
 		return
diff --git a/src/pkg/os/Makefile b/src/pkg/os/Makefile
index f6caf08..3a81afe 100644
--- a/src/pkg/os/Makefile
+++ b/src/pkg/os/Makefile
@@ -22,21 +22,25 @@
 	env_unix.go\
 	file_unix.go\
 	sys_bsd.go\
+	exec_unix.go\
 
 GOFILES_darwin=\
 	env_unix.go\
 	file_unix.go\
 	sys_bsd.go\
+	exec_unix.go\
 
 GOFILES_linux=\
 	env_unix.go\
 	file_unix.go\
 	sys_linux.go\
+	exec_unix.go\
 
 GOFILES_windows=\
 	env_windows.go\
 	file_windows.go\
 	sys_windows.go\
+	exec_windows.go\
 
 GOFILES+=$(GOFILES_$(GOOS))
 
diff --git a/src/pkg/os/exec.go b/src/pkg/os/exec.go
index 100d984..dbdfacc 100644
--- a/src/pkg/os/exec.go
+++ b/src/pkg/os/exec.go
@@ -5,17 +5,29 @@
 package os
 
 import (
+	"runtime"
 	"syscall"
 )
 
-// ForkExec forks the current process and invokes Exec with the program, arguments,
-// and environment specified by name, argv, and envv.  It returns the process
-// id of the forked process and an Error, if any.  The fd array specifies the
+// Process stores the information about a process created by StartProcess.
+type Process struct {
+	Pid    int
+	handle int
+}
+
+func newProcess(pid, handle int) *Process {
+	p := &Process{pid, handle}
+	runtime.SetFinalizer(p, (*Process).Release)
+	return p
+}
+
+// StartProcess starts a new process with the program, arguments,
+// and environment specified by name, argv, and envv. The fd array specifies the
 // 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.
 // If dir is not empty, the child chdirs into the directory before execing the program.
-func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
+func StartProcess(name string, argv []string, envv []string, dir string, fd []*File) (p *Process, err Error) {
 	if envv == nil {
 		envv = Environ()
 	}
@@ -29,17 +41,17 @@
 		}
 	}
 
-	p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
+	pid, h, e := syscall.StartProcess(name, argv, envv, dir, intfd)
 	if e != 0 {
-		return 0, &PathError{"fork/exec", name, Errno(e)}
+		return nil, &PathError{"fork/exec", name, Errno(e)}
 	}
-	return p, nil
+	return newProcess(pid, h), nil
 }
 
 // Exec replaces the current process with an execution of the
 // named binary, with arguments argv and environment envv.
 // If successful, Exec never returns.  If it fails, it returns an Error.
-// ForkExec is almost always a better way to execute a program.
+// StartProcess is almost always a better way to execute a program.
 func Exec(name string, argv []string, envv []string) Error {
 	if envv == nil {
 		envv = Environ()
@@ -65,37 +77,18 @@
 	Rusage             *syscall.Rusage // System-dependent resource usage info.
 }
 
-// Options for Wait.
-const (
-	WNOHANG   = syscall.WNOHANG   // Don't wait if no process has exited.
-	WSTOPPED  = syscall.WSTOPPED  // If set, status of stopped subprocesses is also reported.
-	WUNTRACED = syscall.WUNTRACED // Usually an alias for WSTOPPED.
-	WRUSAGE   = 1 << 20           // Record resource usage.
-)
-
-// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
-// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
-// the options
-
 // Wait waits for process pid to exit or stop, and then returns a
 // Waitmsg describing its status and an Error, if any. The options
 // (WNOHANG etc.) affect the behavior of the Wait call.
+// Wait is equivalent to calling FindProcess and then Wait
+// and Release on the result.
 func Wait(pid int, options int) (w *Waitmsg, err Error) {
-	var status syscall.WaitStatus
-	var rusage *syscall.Rusage
-	if options&WRUSAGE != 0 {
-		rusage = new(syscall.Rusage)
-		options ^= WRUSAGE
+	p, e := FindProcess(pid)
+	if e != nil {
+		return nil, e
 	}
-	pid1, e := syscall.Wait4(pid, &status, options, rusage)
-	if e != 0 {
-		return nil, NewSyscallError("wait", e)
-	}
-	w = new(Waitmsg)
-	w.Pid = pid1
-	w.WaitStatus = status
-	w.Rusage = rusage
-	return w, nil
+	defer p.Release()
+	return p.Wait(options)
 }
 
 // Convert i to decimal string.
diff --git a/src/pkg/os/exec_unix.go b/src/pkg/os/exec_unix.go
new file mode 100644
index 0000000..8990d6a
--- /dev/null
+++ b/src/pkg/os/exec_unix.go
@@ -0,0 +1,63 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+	"runtime"
+	"syscall"
+)
+
+// Options for Wait.
+const (
+	WNOHANG   = syscall.WNOHANG   // Don't wait if no process has exited.
+	WSTOPPED  = syscall.WSTOPPED  // If set, status of stopped subprocesses is also reported.
+	WUNTRACED = syscall.WUNTRACED // Usually an alias for WSTOPPED.
+	WRUSAGE   = 1 << 20           // Record resource usage.
+)
+
+// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
+// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
+// the options
+
+// Wait waits for the Process to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+	if p.Pid == -1 {
+		return nil, EINVAL
+	}
+	var status syscall.WaitStatus
+	var rusage *syscall.Rusage
+	if options&WRUSAGE != 0 {
+		rusage = new(syscall.Rusage)
+		options ^= WRUSAGE
+	}
+	pid1, e := syscall.Wait4(p.Pid, &status, options, rusage)
+	if e != 0 {
+		return nil, NewSyscallError("wait", e)
+	}
+	w = new(Waitmsg)
+	w.Pid = pid1
+	w.WaitStatus = status
+	w.Rusage = rusage
+	return w, nil
+}
+
+// Release releases any resources associated with the Process.
+func (p *Process) Release() Error {
+	// NOOP for unix.
+	p.Pid = -1
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(p, nil)
+	return nil
+}
+
+// FindProcess looks for a running process by its pid.
+// The Process it returns can be used to obtain information
+// about the underlying operating system process.
+func FindProcess(pid int) (p *Process, err Error) {
+	// NOOP for unix.
+	return newProcess(pid, 0), nil
+}
diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go
new file mode 100644
index 0000000..73c0104
--- /dev/null
+++ b/src/pkg/os/exec_windows.go
@@ -0,0 +1,50 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+	"runtime"
+	"syscall"
+)
+
+func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+	s, e := syscall.WaitForSingleObject(int32(p.handle), syscall.INFINITE)
+	switch s {
+	case syscall.WAIT_OBJECT_0:
+		break
+	case syscall.WAIT_FAILED:
+		return nil, NewSyscallError("WaitForSingleObject", e)
+	default:
+		return nil, ErrorString("os: unexpected result from WaitForSingleObject")
+	}
+	var ec uint32
+	if ok, e := syscall.GetExitCodeProcess(uint32(p.handle), &ec); !ok {
+		return nil, NewSyscallError("GetExitCodeProcess", e)
+	}
+	return &Waitmsg{p.Pid, syscall.WaitStatus{s, ec}, new(syscall.Rusage)}, nil
+}
+
+func (p *Process) Release() Error {
+	if p.handle == -1 {
+		return EINVAL
+	}
+	if ok, e := syscall.CloseHandle(int32(p.handle)); !ok {
+		return NewSyscallError("CloseHandle", e)
+	}
+	p.handle = -1
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(p, nil)
+	return nil
+}
+
+func FindProcess(pid int) (p *Process, err Error) {
+	const da = syscall.STANDARD_RIGHTS_READ |
+		syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
+	h, e := syscall.OpenProcess(da, false, uint32(pid))
+	if e != 0 {
+		return nil, NewSyscallError("OpenProcess", e)
+	}
+	return newProcess(pid, int(h)), nil
+}
diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go
index 49b58c8..2ea8acd 100644
--- a/src/pkg/os/os_test.go
+++ b/src/pkg/os/os_test.go
@@ -427,10 +427,11 @@
 		adir = "/"
 		expect = "/\n"
 	}
-	pid, err := ForkExec(cmd, args, nil, adir, []*File{nil, w, Stderr})
+	p, err := StartProcess(cmd, args, nil, adir, []*File{nil, w, Stderr})
 	if err != nil {
-		t.Fatalf("ForkExec: %v", err)
+		t.Fatalf("StartProcess: %v", err)
 	}
+	defer p.Release()
 	w.Close()
 
 	var b bytes.Buffer
@@ -440,7 +441,7 @@
 		args[0] = cmd
 		t.Errorf("exec %q returned %q wanted %q", strings.Join(args, " "), output, expect)
 	}
-	Wait(pid, 0)
+	p.Wait(0)
 }
 
 func checkMode(t *testing.T, path string, mode uint32) {
@@ -750,15 +751,16 @@
 	if err != nil {
 		t.Fatal(err)
 	}
-	pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
+	p, err := StartProcess("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
 	if err != nil {
 		t.Fatal(err)
 	}
+	defer p.Release()
 	w.Close()
 
 	var b bytes.Buffer
 	io.Copy(&b, r)
-	Wait(pid, 0)
+	p.Wait(0)
 	output := b.String()
 	if n := len(output); n > 0 && output[n-1] == '\n' {
 		output = output[0 : n-1]
diff --git a/src/pkg/syscall/exec_unix.go b/src/pkg/syscall/exec_unix.go
index c7f7893..04c0669 100644
--- a/src/pkg/syscall/exec_unix.go
+++ b/src/pkg/syscall/exec_unix.go
@@ -310,3 +310,9 @@
 		uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])))
 	return int(err1)
 }
+
+// StartProcess wraps ForkExec for package os.
+func StartProcess(argv0 string, argv []string, envv []string, dir string, fd []int) (pid, handle int, err int) {
+	pid, err = forkExec(argv0, argv, envv, false, dir, fd)
+	return pid, 0, err
+}
diff --git a/src/pkg/syscall/exec_windows.go b/src/pkg/syscall/exec_windows.go
index 64a0030..1ce2655 100644
--- a/src/pkg/syscall/exec_windows.go
+++ b/src/pkg/syscall/exec_windows.go
@@ -117,13 +117,9 @@
 
 // TODO(kardia): Add trace
 //The command and arguments are passed via the Command line parameter.
-func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
-	if traceme == true {
-		return 0, EWINDOWS
-	}
-
+func StartProcess(argv0 string, argv []string, envv []string, dir string, fd []int) (pid, handle int, err int) {
 	if len(fd) > 3 {
-		return 0, EWINDOWS
+		return 0, 0, EWINDOWS
 	}
 
 	//CreateProcess will throw an error if the dir is not set to a valid dir
@@ -153,19 +149,19 @@
 	var currentProc, _ = GetCurrentProcess()
 	if len(fd) > 0 && fd[0] > 0 {
 		if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
-			return 0, err
+			return 0, 0, err
 		}
 		defer CloseHandle(int32(startupInfo.StdInput))
 	}
 	if len(fd) > 1 && fd[1] > 0 {
 		if ok, err := DuplicateHandle(currentProc, int32(fd[1]), currentProc, &startupInfo.StdOutput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
-			return 0, err
+			return 0, 0, err
 		}
 		defer CloseHandle(int32(startupInfo.StdOutput))
 	}
 	if len(fd) > 2 && fd[2] > 0 {
 		if ok, err := DuplicateHandle(currentProc, int32(fd[2]), currentProc, &startupInfo.StdErr, 0, true, DUPLICATE_SAME_ACCESS); !ok {
-			return 0, err
+			return 0, 0, err
 		}
 		defer CloseHandle(int32(startupInfo.StdErr))
 	}
@@ -188,21 +184,12 @@
 
 	if ok {
 		pid = int(processInfo.ProcessId)
-		CloseHandle(processInfo.Process)
+		handle = int(processInfo.Process)
 		CloseHandle(processInfo.Thread)
 	}
 	return
 }
 
-func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
-	return forkExec(argv0, argv, envv, false, dir, fd)
-}
-
-// PtraceForkExec is like ForkExec, but starts the child in a traced state.
-func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
-	return forkExec(argv0, argv, envv, true, dir, fd)
-}
-
 // Ordinary exec.
 func Exec(argv0 string, argv []string, envv []string) (err int) {
 	return EWINDOWS
diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
index 267b306..f0b71dd 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -136,6 +136,8 @@
 //sys	GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (ok bool, errno int)
 //sys	CancelIo(s uint32) (ok bool, errno int)
 //sys	CreateProcess(appName *int16, commandLine *uint16, procSecurity *int16, threadSecurity *int16, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation)  (ok bool, errno int) = CreateProcessW
+//sys	OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int)
+//sys	GetExitCodeProcess(handle uint32, exitcode *uint32) (ok bool, errno int)
 //sys	GetStartupInfo(startupInfo *StartupInfo)  (ok bool, errno int) = GetStartupInfoW
 //sys	GetCurrentProcess() (pseudoHandle int32, errno int)
 //sys	DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (ok bool, errno int)
@@ -146,8 +148,6 @@
 //sys	CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW
 //sys	CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext
 //sys	CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno int) = advapi32.CryptGenRandom
-//sys OpenProcess(da uint32,b int, pid uint32) (handle uint32, errno int)
-//sys GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int)
 //sys	GetEnvironmentStrings() (envs *uint16, errno int) [failretval==nil] = kernel32.GetEnvironmentStringsW
 //sys	FreeEnvironmentStrings(envs *uint16) (ok bool, errno int) = kernel32.FreeEnvironmentStringsW
 //sys	GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) = kernel32.GetEnvironmentVariableW
@@ -672,6 +672,32 @@
 	return
 }
 
+// Invented structures to support what package os expects.
+type Rusage struct{}
+
+type WaitStatus struct {
+	Status   uint32
+	ExitCode uint32
+}
+
+func (w WaitStatus) Exited() bool { return true }
+
+func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
+
+func (w WaitStatus) Signal() int { return -1 }
+
+func (w WaitStatus) CoreDump() bool { return false }
+
+func (w WaitStatus) Stopped() bool { return false }
+
+func (w WaitStatus) Continued() bool { return false }
+
+func (w WaitStatus) StopSignal() int { return -1 }
+
+func (w WaitStatus) Signaled() bool { return true }
+
+func (w WaitStatus) TrapCause() int { return -1 }
+
 // TODO(brainman): fix all needed for net
 
 func Accept(fd int) (nfd int, sa Sockaddr, errno int)                        { return 0, nil, EWINDOWS }
@@ -735,67 +761,3 @@
 	SYS_EXIT
 	SYS_READ
 )
-
-type Rusage struct {
-	Utime    Timeval
-	Stime    Timeval
-	Maxrss   int32
-	Ixrss    int32
-	Idrss    int32
-	Isrss    int32
-	Minflt   int32
-	Majflt   int32
-	Nswap    int32
-	Inblock  int32
-	Oublock  int32
-	Msgsnd   int32
-	Msgrcv   int32
-	Nsignals int32
-	Nvcsw    int32
-	Nivcsw   int32
-}
-
-type WaitStatus struct {
-	Status   uint32
-	ExitCode uint32
-}
-
-func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
-	const da = STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | SYNCHRONIZE
-	handle, errno := OpenProcess(da, 0, uint32(pid))
-	if errno != 0 {
-		return 0, errno
-	}
-	defer CloseHandle(int32(handle))
-	e, errno := WaitForSingleObject(int32(handle), INFINITE)
-	var c uint32
-	if ok, errno := GetExitCodeProcess(handle, &c); !ok {
-		return 0, errno
-	}
-	*wstatus = WaitStatus{e, c}
-	return pid, 0
-}
-
-
-func (w WaitStatus) Exited() bool { return w.Status == WAIT_OBJECT_0 }
-
-func (w WaitStatus) ExitStatus() int {
-	if w.Status == WAIT_OBJECT_0 {
-		return int(w.ExitCode)
-	}
-	return -1
-}
-
-func (WaitStatus) Signal() int { return -1 }
-
-func (WaitStatus) CoreDump() bool { return false }
-
-func (WaitStatus) Stopped() bool { return false }
-
-func (WaitStatus) Continued() bool { return false }
-
-func (WaitStatus) StopSignal() int { return -1 }
-
-func (w WaitStatus) Signaled() bool { return w.Status == WAIT_OBJECT_0 }
-
-func (WaitStatus) TrapCause() int { return -1 }
diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go
index d5f170f..96c6098 100644
--- a/src/pkg/syscall/zsyscall_windows_386.go
+++ b/src/pkg/syscall/zsyscall_windows_386.go
@@ -45,6 +45,8 @@
 	procGetQueuedCompletionStatus  = getSysProcAddr(modkernel32, "GetQueuedCompletionStatus")
 	procCancelIo                   = getSysProcAddr(modkernel32, "CancelIo")
 	procCreateProcessW             = getSysProcAddr(modkernel32, "CreateProcessW")
+	procOpenProcess                = getSysProcAddr(modkernel32, "OpenProcess")
+	procGetExitCodeProcess         = getSysProcAddr(modkernel32, "GetExitCodeProcess")
 	procGetStartupInfoW            = getSysProcAddr(modkernel32, "GetStartupInfoW")
 	procGetCurrentProcess          = getSysProcAddr(modkernel32, "GetCurrentProcess")
 	procDuplicateHandle            = getSysProcAddr(modkernel32, "DuplicateHandle")
@@ -55,8 +57,6 @@
 	procCryptAcquireContextW       = getSysProcAddr(modadvapi32, "CryptAcquireContextW")
 	procCryptReleaseContext        = getSysProcAddr(modadvapi32, "CryptReleaseContext")
 	procCryptGenRandom             = getSysProcAddr(modadvapi32, "CryptGenRandom")
-	procOpenProcess                = getSysProcAddr(modkernel32, "OpenProcess")
-	procGetExitCodeProcess         = getSysProcAddr(modkernel32, "GetExitCodeProcess")
 	procGetEnvironmentStringsW     = getSysProcAddr(modkernel32, "GetEnvironmentStringsW")
 	procFreeEnvironmentStringsW    = getSysProcAddr(modkernel32, "FreeEnvironmentStringsW")
 	procGetEnvironmentVariableW    = getSysProcAddr(modkernel32, "GetEnvironmentVariableW")
@@ -550,6 +550,42 @@
 	return
 }
 
+func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int) {
+	var _p0 uint32
+	if inheritHandle {
+		_p0 = 1
+	} else {
+		_p0 = 0
+	}
+	r0, _, e1 := Syscall(procOpenProcess, 3, uintptr(da), uintptr(_p0), uintptr(pid))
+	handle = uint32(r0)
+	if handle == 0 {
+		if e1 != 0 {
+			errno = int(e1)
+		} else {
+			errno = EINVAL
+		}
+	} else {
+		errno = 0
+	}
+	return
+}
+
+func GetExitCodeProcess(handle uint32, exitcode *uint32) (ok bool, errno int) {
+	r0, _, e1 := Syscall(procGetExitCodeProcess, 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
+	ok = bool(r0 != 0)
+	if !ok {
+		if e1 != 0 {
+			errno = int(e1)
+		} else {
+			errno = EINVAL
+		}
+	} else {
+		errno = 0
+	}
+	return
+}
+
 func GetStartupInfo(startupInfo *StartupInfo) (ok bool, errno int) {
 	r0, _, e1 := Syscall(procGetStartupInfoW, 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
 	ok = bool(r0 != 0)
@@ -706,36 +742,6 @@
 	return
 }
 
-func OpenProcess(da uint32, b int, pid uint32) (handle uint32, errno int) {
-	r0, _, e1 := Syscall(procOpenProcess, 3, uintptr(da), uintptr(b), uintptr(pid))
-	handle = uint32(r0)
-	if handle == 0 {
-		if e1 != 0 {
-			errno = int(e1)
-		} else {
-			errno = EINVAL
-		}
-	} else {
-		errno = 0
-	}
-	return
-}
-
-func GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int) {
-	r0, _, e1 := Syscall(procGetExitCodeProcess, 2, uintptr(h), uintptr(unsafe.Pointer(c)), 0)
-	ok = bool(r0 != 0)
-	if !ok {
-		if e1 != 0 {
-			errno = int(e1)
-		} else {
-			errno = EINVAL
-		}
-	} else {
-		errno = 0
-	}
-	return
-}
-
 func GetEnvironmentStrings() (envs *uint16, errno int) {
 	r0, _, e1 := Syscall(procGetEnvironmentStringsW, 0, 0, 0, 0)
 	envs = (*uint16)(unsafe.Pointer(r0))