| // 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 |
| } |