OSDN Git Service

libgo: Update to weekly.2011-11-02.
[pf3gnuchains/gcc-fork.git] / libgo / go / os / exec_posix.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 // +build darwin freebsd linux openbsd windows
6
7 package os
8
9 import (
10         "runtime"
11         "syscall"
12 )
13
14 type UnixSignal int32
15
16 func (sig UnixSignal) String() string {
17         s := runtime.Signame(int32(sig))
18         if len(s) > 0 {
19                 return s
20         }
21         return "UnixSignal"
22 }
23
24 // StartProcess starts a new process with the program, arguments and attributes
25 // specified by name, argv and attr.
26 //
27 // StartProcess is a low-level interface. The exec package provides
28 // higher-level interfaces.
29 func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
30         sysattr := &syscall.ProcAttr{
31                 Dir: attr.Dir,
32                 Env: attr.Env,
33                 Sys: attr.Sys,
34         }
35         if sysattr.Env == nil {
36                 sysattr.Env = Environ()
37         }
38         for _, f := range attr.Files {
39                 sysattr.Files = append(sysattr.Files, f.Fd())
40         }
41
42         pid, h, e := syscall.StartProcess(name, argv, sysattr)
43         if iserror(e) {
44                 return nil, &PathError{"fork/exec", name, Errno(e)}
45         }
46         return newProcess(pid, h), nil
47 }
48
49 // Kill causes the Process to exit immediately.
50 func (p *Process) Kill() error {
51         return p.Signal(SIGKILL)
52 }
53
54 // Exec replaces the current process with an execution of the
55 // named binary, with arguments argv and environment envv.
56 // If successful, Exec never returns.  If it fails, it returns an error.
57 //
58 // To run a child process, see StartProcess (for a low-level interface)
59 // or the exec package (for higher-level interfaces).
60 func Exec(name string, argv []string, envv []string) error {
61         if envv == nil {
62                 envv = Environ()
63         }
64         e := syscall.Exec(name, argv, envv)
65         if iserror(e) {
66                 return &PathError{"exec", name, Errno(e)}
67         }
68         return nil
69 }
70
71 // TODO(rsc): Should os implement its own syscall.WaitStatus
72 // wrapper with the methods, or is exposing the underlying one enough?
73 //
74 // TODO(rsc): Certainly need to have Rusage struct,
75 // since syscall one might have different field types across
76 // different OS.
77
78 // Waitmsg stores the information about an exited process as reported by Wait.
79 type Waitmsg struct {
80         Pid                int             // The process's id.
81         syscall.WaitStatus                 // System-dependent status info.
82         Rusage             *syscall.Rusage // System-dependent resource usage info.
83 }
84
85 // Wait waits for process pid to exit or stop, and then returns a
86 // Waitmsg describing its status and an error, if any. The options
87 // (WNOHANG etc.) affect the behavior of the Wait call.
88 // Wait is equivalent to calling FindProcess and then Wait
89 // and Release on the result.
90 func Wait(pid int, options int) (w *Waitmsg, err error) {
91         p, e := FindProcess(pid)
92         if e != nil {
93                 return nil, e
94         }
95         defer p.Release()
96         return p.Wait(options)
97 }
98
99 // Convert i to decimal string.
100 func itod(i int) string {
101         if i == 0 {
102                 return "0"
103         }
104
105         u := uint64(i)
106         if i < 0 {
107                 u = -u
108         }
109
110         // Assemble decimal in reverse order.
111         var b [32]byte
112         bp := len(b)
113         for ; u > 0; u /= 10 {
114                 bp--
115                 b[bp] = byte(u%10) + '0'
116         }
117
118         if i < 0 {
119                 bp--
120                 b[bp] = '-'
121         }
122
123         return string(b[bp:])
124 }
125
126 func (w *Waitmsg) String() string {
127         if w == nil {
128                 return "<nil>"
129         }
130         // TODO(austin) Use signal names when possible?
131         res := ""
132         switch {
133         case w.Exited():
134                 res = "exit status " + itod(w.ExitStatus())
135         case w.Signaled():
136                 res = "signal " + itod(w.Signal())
137         case w.Stopped():
138                 res = "stop signal " + itod(w.StopSignal())
139                 if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
140                         res += " (trap " + itod(w.TrapCause()) + ")"
141                 }
142         case w.Continued():
143                 res = "continued"
144         }
145         if w.CoreDump() {
146                 res += " (core dumped)"
147         }
148         return res
149 }