OSDN Git Service

Update to current version of Go library.
[pf3gnuchains/gcc-fork.git] / libgo / go / os / exec.go
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.
4
5 package os
6
7 import (
8         "runtime"
9         "syscall"
10 )
11
12 // Process stores the information about a process created by StartProcess.
13 type Process struct {
14         Pid    int
15         handle int
16 }
17
18 func newProcess(pid, handle int) *Process {
19         p := &Process{pid, handle}
20         runtime.SetFinalizer(p, (*Process).Release)
21         return p
22 }
23
24 // ProcAttr holds the attributes that will be applied to a new process
25 // started by StartProcess.
26 type ProcAttr struct {
27         // If Dir is non-empty, the child changes into the directory before
28         // creating the process.
29         Dir string
30         // If Env is non-nil, it gives the environment variables for the
31         // new process in the form returned by Environ.
32         // If it is nil, the result of Environ will be used.
33         Env []string
34         // Files specifies the open files inherited by the new process.  The
35         // first three entries correspond to standard input, standard output, and
36         // standard error.  An implementation may support additional entries,
37         // depending on the underlying operating system.  A nil entry corresponds
38         // to that file being closed when the process starts.
39         Files []*File
40 }
41
42 // StartProcess starts a new process with the program, arguments and attributes
43 // specified by name, argv and attr.
44 func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
45         sysattr := &syscall.ProcAttr{
46                 Dir: attr.Dir,
47                 Env: attr.Env,
48         }
49         if sysattr.Env == nil {
50                 sysattr.Env = Environ()
51         }
52         // Create array of integer (system) fds.
53         intfd := make([]int, len(attr.Files))
54         for i, f := range attr.Files {
55                 if f == nil {
56                         intfd[i] = -1
57                 } else {
58                         intfd[i] = f.Fd()
59                 }
60         }
61         sysattr.Files = intfd
62
63         pid, h, e := syscall.StartProcess(name, argv, sysattr)
64         if e != 0 {
65                 return nil, &PathError{"fork/exec", name, Errno(e)}
66         }
67         return newProcess(pid, h), nil
68 }
69
70 // Exec replaces the current process with an execution of the
71 // named binary, with arguments argv and environment envv.
72 // If successful, Exec never returns.  If it fails, it returns an Error.
73 // StartProcess is almost always a better way to execute a program.
74 func Exec(name string, argv []string, envv []string) Error {
75         if envv == nil {
76                 envv = Environ()
77         }
78         e := syscall.Exec(name, argv, envv)
79         if e != 0 {
80                 return &PathError{"exec", name, Errno(e)}
81         }
82         return nil
83 }
84
85 // TODO(rsc): Should os implement its own syscall.WaitStatus
86 // wrapper with the methods, or is exposing the underlying one enough?
87 //
88 // TODO(rsc): Certainly need to have Rusage struct,
89 // since syscall one might have different field types across
90 // different OS.
91
92 // Waitmsg stores the information about an exited process as reported by Wait.
93 type Waitmsg struct {
94         Pid                int             // The process's id.
95         syscall.WaitStatus                 // System-dependent status info.
96         Rusage             *syscall.Rusage // System-dependent resource usage info.
97 }
98
99 // Wait waits for process pid to exit or stop, and then returns a
100 // Waitmsg describing its status and an Error, if any. The options
101 // (WNOHANG etc.) affect the behavior of the Wait call.
102 // Wait is equivalent to calling FindProcess and then Wait
103 // and Release on the result.
104 func Wait(pid int, options int) (w *Waitmsg, err Error) {
105         p, e := FindProcess(pid)
106         if e != nil {
107                 return nil, e
108         }
109         defer p.Release()
110         return p.Wait(options)
111 }
112
113 // Convert i to decimal string.
114 func itod(i int) string {
115         if i == 0 {
116                 return "0"
117         }
118
119         u := uint64(i)
120         if i < 0 {
121                 u = -u
122         }
123
124         // Assemble decimal in reverse order.
125         var b [32]byte
126         bp := len(b)
127         for ; u > 0; u /= 10 {
128                 bp--
129                 b[bp] = byte(u%10) + '0'
130         }
131
132         if i < 0 {
133                 bp--
134                 b[bp] = '-'
135         }
136
137         return string(b[bp:])
138 }
139
140 func (w Waitmsg) String() string {
141         // TODO(austin) Use signal names when possible?
142         res := ""
143         switch {
144         case w.Exited():
145                 res = "exit status " + itod(w.ExitStatus())
146         case w.Signaled():
147                 res = "signal " + itod(w.Signal())
148         case w.Stopped():
149                 res = "stop signal " + itod(w.StopSignal())
150                 if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
151                         res += " (trap " + itod(w.TrapCause()) + ")"
152                 }
153         case w.Continued():
154                 res = "continued"
155         }
156         if w.CoreDump() {
157                 res += " (core dumped)"
158         }
159         return res
160 }
161
162 // Getpid returns the process id of the caller.
163 func Getpid() int { return syscall.Getpid() }
164
165 // Getppid returns the process id of the caller's parent.
166 func Getppid() int { return syscall.Getppid() }