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