OSDN Git Service

Add Go frontend, libgo library, and Go testsuite.
[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         "syscall"
9 )
10
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) {
19         if envv == nil {
20                 envv = Environ()
21         }
22         // Create array of integer (system) fds.
23         intfd := make([]int, len(fd))
24         for i, f := range fd {
25                 if f == nil {
26                         intfd[i] = -1
27                 } else {
28                         intfd[i] = f.Fd()
29                 }
30         }
31
32         p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
33         if e != 0 {
34                 return 0, &PathError{"fork/exec", name, Errno(e)}
35         }
36         return p, nil
37 }
38
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 {
44         if envv == nil {
45                 envv = Environ()
46         }
47         e := syscall.Exec(name, argv, envv)
48         if e != 0 {
49                 return &PathError{"exec", name, Errno(e)}
50         }
51         return nil
52 }
53
54 // TODO(rsc): Should os implement its own syscall.WaitStatus
55 // wrapper with the methods, or is exposing the underlying one enough?
56 //
57 // TODO(rsc): Certainly need to have Rusage struct,
58 // since syscall one might have different field types across
59 // different OS.
60
61 // Waitmsg stores the information about an exited process as reported by Wait.
62 type Waitmsg struct {
63         Pid                int             // The process's id.
64         syscall.WaitStatus                 // System-dependent status info.
65         Rusage             *syscall.Rusage // System-dependent resource usage info.
66 }
67
68 // Options for Wait.
69 const (
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.
72         WUNTRACED = WSTOPPED
73         WRUSAGE   = 1 << 20 // Record resource usage.
74 )
75
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
78 // the options
79
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)
88                 options ^= WRUSAGE
89         }
90         pid1, e := syscall.Wait4(pid, &status, options, rusage)
91         if e != 0 {
92                 return nil, NewSyscallError("wait", e)
93         }
94         w = new(Waitmsg)
95         w.Pid = pid1
96         w.WaitStatus = status
97         w.Rusage = rusage
98         return w, nil
99 }
100
101 // Convert i to decimal string.
102 func itod(i int) string {
103         if i == 0 {
104                 return "0"
105         }
106
107         u := uint64(i)
108         if i < 0 {
109                 u = -u
110         }
111
112         // Assemble decimal in reverse order.
113         var b [32]byte
114         bp := len(b)
115         for ; u > 0; u /= 10 {
116                 bp--
117                 b[bp] = byte(u%10) + '0'
118         }
119
120         if i < 0 {
121                 bp--
122                 b[bp] = '-'
123         }
124
125         return string(b[bp:])
126 }
127
128 func (w Waitmsg) String() string {
129         // TODO(austin) Use signal names when possible?
130         res := ""
131         switch {
132         case w.Exited():
133                 res = "exit status " + itod(w.ExitStatus())
134         case w.Signaled():
135                 res = "signal " + itod(w.Signal())
136         case w.Stopped():
137                 res = "stop signal " + itod(w.StopSignal())
138                 if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
139                         res += " (trap " + itod(w.TrapCause()) + ")"
140                 }
141         case w.Continued():
142                 res = "continued"
143         }
144         if w.CoreDump() {
145                 res += " (core dumped)"
146         }
147         return res
148 }
149
150 // Getpid returns the process id of the caller.
151 func Getpid() int { return syscall.Getpid() }
152
153 // Getppid returns the process id of the caller's parent.
154 func Getppid() int { return syscall.Getppid() }