os: Plan 9 support.

R=rsc, ality, r, r2
CC=golang-dev
https://golang.org/cl/4149046
diff --git a/src/pkg/os/exec_plan9.go b/src/pkg/os/exec_plan9.go
new file mode 100644
index 0000000..11874ab
--- /dev/null
+++ b/src/pkg/os/exec_plan9.go
@@ -0,0 +1,114 @@
+// 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"
+)
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+	sysattr := &syscall.ProcAttr{
+		Dir: attr.Dir,
+		Env: attr.Env,
+	}
+
+	// Create array of integer (system) fds.
+	intfd := make([]int, len(attr.Files))
+	for i, f := range attr.Files {
+		if f == nil {
+			intfd[i] = -1
+		} else {
+			intfd[i] = f.Fd()
+		}
+	}
+
+	sysattr.Files = intfd
+
+	pid, h, e := syscall.StartProcess(name, argv, sysattr)
+	if iserror(e) {
+		return nil, &PathError{"fork/exec", name, e}
+	}
+
+	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.
+func Exec(name string, argv []string, envv []string) Error {
+	e := syscall.Exec(name, argv, envv)
+	if iserror(e) {
+		return &PathError{"exec", name, e}
+	}
+
+	return nil
+}
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg syscall.Waitmsg
+
+// 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) {
+	var waitmsg syscall.Waitmsg
+
+	if p.Pid == -1 {
+		return nil, EINVAL
+	}
+
+	for true {
+		err = syscall.Await(&waitmsg)
+
+		if iserror(err) {
+			return nil, NewSyscallError("wait", err)
+		}
+
+		if waitmsg.Pid == p.Pid {
+			break
+		}
+	}
+
+	return (*Waitmsg)(&waitmsg), nil
+}
+
+// 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) {
+	p, e := FindProcess(pid)
+	if e != nil {
+		return nil, e
+	}
+	defer p.Release()
+	return p.Wait(options)
+}
+
+// Release releases any resources associated with the Process.
+func (p *Process) Release() Error {
+	// NOOP for Plan 9.
+	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 Plan 9.
+	return newProcess(pid, 0), nil
+}
+
+func (w Waitmsg) String() string {
+	return "exit status: " + w.Msg
+}