1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 // ForkExec forks the current process and invokes Exec with the program, arguments,
12 // and environment specified by name, argv, and envv. It returns the process
13 // id of the forked process and an Error, if any. The fd array specifies the
14 // file descriptors to be set up in the new process: fd[0] will be Unix file
15 // descriptor 0 (standard input), fd[1] descriptor 1, and so on. A nil entry
16 // will cause the child to have no open file descriptor with that index.
17 // If dir is not empty, the child chdirs into the directory before execing the program.
18 func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
22 // Create array of integer (system) fds.
23 intfd := make([]int, len(fd))
24 for i, f := range fd {
32 p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
34 return 0, &PathError{"fork/exec", name, Errno(e)}
39 // Exec replaces the current process with an execution of the
40 // named binary, with arguments argv and environment envv.
41 // If successful, Exec never returns. If it fails, it returns an Error.
42 // ForkExec is almost always a better way to execute a program.
43 func Exec(name string, argv []string, envv []string) Error {
47 e := syscall.Exec(name, argv, envv)
49 return &PathError{"exec", name, Errno(e)}
54 // TODO(rsc): Should os implement its own syscall.WaitStatus
55 // wrapper with the methods, or is exposing the underlying one enough?
57 // TODO(rsc): Certainly need to have Rusage struct,
58 // since syscall one might have different field types across
61 // Waitmsg stores the information about an exited process as reported by Wait.
63 Pid int // The process's id.
64 syscall.WaitStatus // System-dependent status info.
65 Rusage *syscall.Rusage // System-dependent resource usage info.
70 WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
71 WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
73 WRUSAGE = 1 << 20 // Record resource usage.
76 // WRUSAGE must not be too high a bit, to avoid clashing with Linux's
77 // WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
80 // Wait waits for process pid to exit or stop, and then returns a
81 // Waitmsg describing its status and an Error, if any. The options
82 // (WNOHANG etc.) affect the behavior of the Wait call.
83 func Wait(pid int, options int) (w *Waitmsg, err Error) {
84 var status syscall.WaitStatus
85 var rusage *syscall.Rusage
86 if options&WRUSAGE != 0 {
87 rusage = new(syscall.Rusage)
90 pid1, e := syscall.Wait4(pid, &status, options, rusage)
92 return nil, NewSyscallError("wait", e)
101 // Convert i to decimal string.
102 func itod(i int) string {
112 // Assemble decimal in reverse order.
115 for ; u > 0; u /= 10 {
117 b[bp] = byte(u%10) + '0'
125 return string(b[bp:])
128 func (w Waitmsg) String() string {
129 // TODO(austin) Use signal names when possible?
133 res = "exit status " + itod(w.ExitStatus())
135 res = "signal " + itod(w.Signal())
137 res = "stop signal " + itod(w.StopSignal())
138 if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
139 res += " (trap " + itod(w.TrapCause()) + ")"
145 res += " (core dumped)"
150 // Getpid returns the process id of the caller.
151 func Getpid() int { return syscall.Getpid() }
153 // Getppid returns the process id of the caller's parent.
154 func Getppid() int { return syscall.Getppid() }