libgo: Update to Go 1.3 release.
[official-gcc.git] / libgo / go / os / exec / exec.go
bloba70ed0d20cbba995f25de65692138301d89c14ea
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.
5 // Package exec runs external commands. It wraps os.StartProcess to make it
6 // easier to remap stdin and stdout, connect I/O with pipes, and do other
7 // adjustments.
8 package exec
10 import (
11 "bytes"
12 "errors"
13 "io"
14 "os"
15 "path/filepath"
16 "runtime"
17 "strconv"
18 "strings"
19 "sync"
20 "syscall"
23 // Error records the name of a binary that failed to be executed
24 // and the reason it failed.
25 type Error struct {
26 Name string
27 Err error
30 func (e *Error) Error() string {
31 return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error()
34 // Cmd represents an external command being prepared or run.
35 type Cmd struct {
36 // Path is the path of the command to run.
38 // This is the only field that must be set to a non-zero
39 // value. If Path is relative, it is evaluated relative
40 // to Dir.
41 Path string
43 // Args holds command line arguments, including the command as Args[0].
44 // If the Args field is empty or nil, Run uses {Path}.
46 // In typical use, both Path and Args are set by calling Command.
47 Args []string
49 // Env specifies the environment of the process.
50 // If Env is nil, Run uses the current process's environment.
51 Env []string
53 // Dir specifies the working directory of the command.
54 // If Dir is the empty string, Run runs the command in the
55 // calling process's current directory.
56 Dir string
58 // Stdin specifies the process's standard input. If Stdin is
59 // nil, the process reads from the null device (os.DevNull).
60 Stdin io.Reader
62 // Stdout and Stderr specify the process's standard output and error.
64 // If either is nil, Run connects the corresponding file descriptor
65 // to the null device (os.DevNull).
67 // If Stdout and Stderr are the same writer, at most one
68 // goroutine at a time will call Write.
69 Stdout io.Writer
70 Stderr io.Writer
72 // ExtraFiles specifies additional open files to be inherited by the
73 // new process. It does not include standard input, standard output, or
74 // standard error. If non-nil, entry i becomes file descriptor 3+i.
76 // BUG: on OS X 10.6, child processes may sometimes inherit unwanted fds.
77 // http://golang.org/issue/2603
78 ExtraFiles []*os.File
80 // SysProcAttr holds optional, operating system-specific attributes.
81 // Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
82 SysProcAttr *syscall.SysProcAttr
84 // Process is the underlying process, once started.
85 Process *os.Process
87 // ProcessState contains information about an exited process,
88 // available after a call to Wait or Run.
89 ProcessState *os.ProcessState
91 lookPathErr error // LookPath error, if any.
92 finished bool // when Wait was called
93 childFiles []*os.File
94 closeAfterStart []io.Closer
95 closeAfterWait []io.Closer
96 goroutine []func() error
97 errch chan error // one send per goroutine
100 // Command returns the Cmd struct to execute the named program with
101 // the given arguments.
103 // It sets only the Path and Args in the returned structure.
105 // If name contains no path separators, Command uses LookPath to
106 // resolve the path to a complete name if possible. Otherwise it uses
107 // name directly.
109 // The returned Cmd's Args field is constructed from the command name
110 // followed by the elements of arg, so arg should not include the
111 // command name itself. For example, Command("echo", "hello")
112 func Command(name string, arg ...string) *Cmd {
113 cmd := &Cmd{
114 Path: name,
115 Args: append([]string{name}, arg...),
117 if filepath.Base(name) == name {
118 if lp, err := LookPath(name); err != nil {
119 cmd.lookPathErr = err
120 } else {
121 cmd.Path = lp
124 return cmd
127 // interfaceEqual protects against panics from doing equality tests on
128 // two interfaces with non-comparable underlying types.
129 func interfaceEqual(a, b interface{}) bool {
130 defer func() {
131 recover()
133 return a == b
136 func (c *Cmd) envv() []string {
137 if c.Env != nil {
138 return c.Env
140 return os.Environ()
143 func (c *Cmd) argv() []string {
144 if len(c.Args) > 0 {
145 return c.Args
147 return []string{c.Path}
150 func (c *Cmd) stdin() (f *os.File, err error) {
151 if c.Stdin == nil {
152 f, err = os.Open(os.DevNull)
153 if err != nil {
154 return
156 c.closeAfterStart = append(c.closeAfterStart, f)
157 return
160 if f, ok := c.Stdin.(*os.File); ok {
161 return f, nil
164 pr, pw, err := os.Pipe()
165 if err != nil {
166 return
169 c.closeAfterStart = append(c.closeAfterStart, pr)
170 c.closeAfterWait = append(c.closeAfterWait, pw)
171 c.goroutine = append(c.goroutine, func() error {
172 _, err := io.Copy(pw, c.Stdin)
173 if err1 := pw.Close(); err == nil {
174 err = err1
176 return err
178 return pr, nil
181 func (c *Cmd) stdout() (f *os.File, err error) {
182 return c.writerDescriptor(c.Stdout)
185 func (c *Cmd) stderr() (f *os.File, err error) {
186 if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
187 return c.childFiles[1], nil
189 return c.writerDescriptor(c.Stderr)
192 func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
193 if w == nil {
194 f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
195 if err != nil {
196 return
198 c.closeAfterStart = append(c.closeAfterStart, f)
199 return
202 if f, ok := w.(*os.File); ok {
203 return f, nil
206 pr, pw, err := os.Pipe()
207 if err != nil {
208 return
211 c.closeAfterStart = append(c.closeAfterStart, pw)
212 c.closeAfterWait = append(c.closeAfterWait, pr)
213 c.goroutine = append(c.goroutine, func() error {
214 _, err := io.Copy(w, pr)
215 return err
217 return pw, nil
220 func (c *Cmd) closeDescriptors(closers []io.Closer) {
221 for _, fd := range closers {
222 fd.Close()
226 // Run starts the specified command and waits for it to complete.
228 // The returned error is nil if the command runs, has no problems
229 // copying stdin, stdout, and stderr, and exits with a zero exit
230 // status.
232 // If the command fails to run or doesn't complete successfully, the
233 // error is of type *ExitError. Other error types may be
234 // returned for I/O problems.
235 func (c *Cmd) Run() error {
236 if err := c.Start(); err != nil {
237 return err
239 return c.Wait()
242 // lookExtensions finds windows executable by its dir and path.
243 // It uses LookPath to try appropriate extensions.
244 // lookExtensions does not search PATH, instead it converts `prog` into `.\prog`.
245 func lookExtensions(path, dir string) (string, error) {
246 if filepath.Base(path) == path {
247 path = filepath.Join(".", path)
249 if dir == "" {
250 return LookPath(path)
252 if filepath.VolumeName(path) != "" {
253 return LookPath(path)
255 if len(path) > 1 && os.IsPathSeparator(path[0]) {
256 return LookPath(path)
258 dirandpath := filepath.Join(dir, path)
259 // We assume that LookPath will only add file extension.
260 lp, err := LookPath(dirandpath)
261 if err != nil {
262 return "", err
264 ext := strings.TrimPrefix(lp, dirandpath)
265 return path + ext, nil
268 // Start starts the specified command but does not wait for it to complete.
270 // The Wait method will return the exit code and release associated resources
271 // once the command exits.
272 func (c *Cmd) Start() error {
273 if c.lookPathErr != nil {
274 c.closeDescriptors(c.closeAfterStart)
275 c.closeDescriptors(c.closeAfterWait)
276 return c.lookPathErr
278 if runtime.GOOS == "windows" {
279 lp, err := lookExtensions(c.Path, c.Dir)
280 if err != nil {
281 c.closeDescriptors(c.closeAfterStart)
282 c.closeDescriptors(c.closeAfterWait)
283 return err
285 c.Path = lp
287 if c.Process != nil {
288 return errors.New("exec: already started")
291 type F func(*Cmd) (*os.File, error)
292 for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
293 fd, err := setupFd(c)
294 if err != nil {
295 c.closeDescriptors(c.closeAfterStart)
296 c.closeDescriptors(c.closeAfterWait)
297 return err
299 c.childFiles = append(c.childFiles, fd)
301 c.childFiles = append(c.childFiles, c.ExtraFiles...)
303 var err error
304 c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
305 Dir: c.Dir,
306 Files: c.childFiles,
307 Env: c.envv(),
308 Sys: c.SysProcAttr,
310 if err != nil {
311 c.closeDescriptors(c.closeAfterStart)
312 c.closeDescriptors(c.closeAfterWait)
313 return err
316 c.closeDescriptors(c.closeAfterStart)
318 c.errch = make(chan error, len(c.goroutine))
319 for _, fn := range c.goroutine {
320 go func(fn func() error) {
321 c.errch <- fn()
322 }(fn)
325 return nil
328 // An ExitError reports an unsuccessful exit by a command.
329 type ExitError struct {
330 *os.ProcessState
333 func (e *ExitError) Error() string {
334 return e.ProcessState.String()
337 // Wait waits for the command to exit.
338 // It must have been started by Start.
340 // The returned error is nil if the command runs, has no problems
341 // copying stdin, stdout, and stderr, and exits with a zero exit
342 // status.
344 // If the command fails to run or doesn't complete successfully, the
345 // error is of type *ExitError. Other error types may be
346 // returned for I/O problems.
348 // Wait releases any resources associated with the Cmd.
349 func (c *Cmd) Wait() error {
350 if c.Process == nil {
351 return errors.New("exec: not started")
353 if c.finished {
354 return errors.New("exec: Wait was already called")
356 c.finished = true
357 state, err := c.Process.Wait()
358 c.ProcessState = state
360 var copyError error
361 for _ = range c.goroutine {
362 if err := <-c.errch; err != nil && copyError == nil {
363 copyError = err
367 c.closeDescriptors(c.closeAfterWait)
369 if err != nil {
370 return err
371 } else if !state.Success() {
372 return &ExitError{state}
375 return copyError
378 // Output runs the command and returns its standard output.
379 func (c *Cmd) Output() ([]byte, error) {
380 if c.Stdout != nil {
381 return nil, errors.New("exec: Stdout already set")
383 var b bytes.Buffer
384 c.Stdout = &b
385 err := c.Run()
386 return b.Bytes(), err
389 // CombinedOutput runs the command and returns its combined standard
390 // output and standard error.
391 func (c *Cmd) CombinedOutput() ([]byte, error) {
392 if c.Stdout != nil {
393 return nil, errors.New("exec: Stdout already set")
395 if c.Stderr != nil {
396 return nil, errors.New("exec: Stderr already set")
398 var b bytes.Buffer
399 c.Stdout = &b
400 c.Stderr = &b
401 err := c.Run()
402 return b.Bytes(), err
405 // StdinPipe returns a pipe that will be connected to the command's
406 // standard input when the command starts.
407 // The pipe will be closed automatically after Wait sees the command exit.
408 // A caller need only call Close to force the pipe to close sooner.
409 // For example, if the command being run will not exit until standard input
410 // is closed, the caller must close the pipe.
411 func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
412 if c.Stdin != nil {
413 return nil, errors.New("exec: Stdin already set")
415 if c.Process != nil {
416 return nil, errors.New("exec: StdinPipe after process started")
418 pr, pw, err := os.Pipe()
419 if err != nil {
420 return nil, err
422 c.Stdin = pr
423 c.closeAfterStart = append(c.closeAfterStart, pr)
424 wc := &closeOnce{File: pw}
425 c.closeAfterWait = append(c.closeAfterWait, wc)
426 return wc, nil
429 type closeOnce struct {
430 *os.File
432 once sync.Once
433 err error
436 func (c *closeOnce) Close() error {
437 c.once.Do(c.close)
438 return c.err
441 func (c *closeOnce) close() {
442 c.err = c.File.Close()
445 // StdoutPipe returns a pipe that will be connected to the command's
446 // standard output when the command starts.
448 // Wait will close the pipe after seeing the command exit, so most callers
449 // need not close the pipe themselves; however, an implication is that
450 // it is incorrect to call Wait before all reads from the pipe have completed.
451 // For the same reason, it is incorrect to call Run when using StdoutPipe.
452 // See the example for idiomatic usage.
453 func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
454 if c.Stdout != nil {
455 return nil, errors.New("exec: Stdout already set")
457 if c.Process != nil {
458 return nil, errors.New("exec: StdoutPipe after process started")
460 pr, pw, err := os.Pipe()
461 if err != nil {
462 return nil, err
464 c.Stdout = pw
465 c.closeAfterStart = append(c.closeAfterStart, pw)
466 c.closeAfterWait = append(c.closeAfterWait, pr)
467 return pr, nil
470 // StderrPipe returns a pipe that will be connected to the command's
471 // standard error when the command starts.
473 // Wait will close the pipe after seeing the command exit, so most callers
474 // need not close the pipe themselves; however, an implication is that
475 // it is incorrect to call Wait before all reads from the pipe have completed.
476 // For the same reason, it is incorrect to use Run when using StderrPipe.
477 // See the StdoutPipe example for idiomatic usage.
478 func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
479 if c.Stderr != nil {
480 return nil, errors.New("exec: Stderr already set")
482 if c.Process != nil {
483 return nil, errors.New("exec: StderrPipe after process started")
485 pr, pw, err := os.Pipe()
486 if err != nil {
487 return nil, err
489 c.Stderr = pw
490 c.closeAfterStart = append(c.closeAfterStart, pw)
491 c.closeAfterWait = append(c.closeAfterWait, pr)
492 return pr, nil