diff options
Diffstat (limited to 'libgo/go/exec/exec.go')
-rw-r--r-- | libgo/go/exec/exec.go | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/libgo/go/exec/exec.go b/libgo/go/exec/exec.go index aaad508..ebdfd54 100644 --- a/libgo/go/exec/exec.go +++ b/libgo/go/exec/exec.go @@ -9,6 +9,7 @@ package exec import ( "bytes" + "errors" "io" "os" "strconv" @@ -18,12 +19,12 @@ import ( // Error records the name of a binary that failed to be be executed // and the reason it failed. type Error struct { - Name string - Error os.Error + Name string + Err error } -func (e *Error) String() string { - return "exec: " + strconv.Quote(e.Name) + ": " + e.Error.String() +func (e *Error) Error() string { + return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error() } // Cmd represents an external command being prepared or run. @@ -75,13 +76,13 @@ type Cmd struct { // Process is the underlying process, once started. Process *os.Process - err os.Error // last error (from LookPath, stdin, stdout, stderr) - finished bool // when Wait was called + err error // last error (from LookPath, stdin, stdout, stderr) + finished bool // when Wait was called childFiles []*os.File closeAfterStart []io.Closer closeAfterWait []io.Closer - goroutine []func() os.Error - errch chan os.Error // one send per goroutine + goroutine []func() error + errch chan error // one send per goroutine } // Command returns the Cmd struct to execute the named program with @@ -132,7 +133,7 @@ func (c *Cmd) argv() []string { return []string{c.Path} } -func (c *Cmd) stdin() (f *os.File, err os.Error) { +func (c *Cmd) stdin() (f *os.File, err error) { if c.Stdin == nil { f, err = os.Open(os.DevNull) c.closeAfterStart = append(c.closeAfterStart, f) @@ -150,7 +151,7 @@ func (c *Cmd) stdin() (f *os.File, err os.Error) { c.closeAfterStart = append(c.closeAfterStart, pr) c.closeAfterWait = append(c.closeAfterWait, pw) - c.goroutine = append(c.goroutine, func() os.Error { + c.goroutine = append(c.goroutine, func() error { _, err := io.Copy(pw, c.Stdin) if err1 := pw.Close(); err == nil { err = err1 @@ -160,18 +161,18 @@ func (c *Cmd) stdin() (f *os.File, err os.Error) { return pr, nil } -func (c *Cmd) stdout() (f *os.File, err os.Error) { +func (c *Cmd) stdout() (f *os.File, err error) { return c.writerDescriptor(c.Stdout) } -func (c *Cmd) stderr() (f *os.File, err os.Error) { +func (c *Cmd) stderr() (f *os.File, err error) { if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) { return c.childFiles[1], nil } return c.writerDescriptor(c.Stderr) } -func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) { +func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) { if w == nil { f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0) c.closeAfterStart = append(c.closeAfterStart, f) @@ -189,7 +190,7 @@ func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) { c.closeAfterStart = append(c.closeAfterStart, pw) c.closeAfterWait = append(c.closeAfterWait, pr) - c.goroutine = append(c.goroutine, func() os.Error { + c.goroutine = append(c.goroutine, func() error { _, err := io.Copy(w, pr) return err }) @@ -203,9 +204,9 @@ func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) { // status. // // If the command fails to run or doesn't complete successfully, the -// error is of type *os.Waitmsg. Other error types may be +// error is of type *ExitError. Other error types may be // returned for I/O problems. -func (c *Cmd) Run() os.Error { +func (c *Cmd) Run() error { if err := c.Start(); err != nil { return err } @@ -213,15 +214,15 @@ func (c *Cmd) Run() os.Error { } // Start starts the specified command but does not wait for it to complete. -func (c *Cmd) Start() os.Error { +func (c *Cmd) Start() error { if c.err != nil { return c.err } if c.Process != nil { - return os.NewError("exec: already started") + return errors.New("exec: already started") } - type F func(*Cmd) (*os.File, os.Error) + type F func(*Cmd) (*os.File, error) for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { fd, err := setupFd(c) if err != nil { @@ -231,7 +232,7 @@ func (c *Cmd) Start() os.Error { } c.childFiles = append(c.childFiles, c.ExtraFiles...) - var err os.Error + var err error c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ Dir: c.Dir, Files: c.childFiles, @@ -246,9 +247,9 @@ func (c *Cmd) Start() os.Error { fd.Close() } - c.errch = make(chan os.Error, len(c.goroutine)) + c.errch = make(chan error, len(c.goroutine)) for _, fn := range c.goroutine { - go func(fn func() os.Error) { + go func(fn func() error) { c.errch <- fn() }(fn) } @@ -256,6 +257,15 @@ func (c *Cmd) Start() os.Error { return nil } +// An ExitError reports an unsuccessful exit by a command. +type ExitError struct { + *os.Waitmsg +} + +func (e *ExitError) Error() string { + return e.Waitmsg.String() +} + // Wait waits for the command to exit. // It must have been started by Start. // @@ -264,19 +274,19 @@ func (c *Cmd) Start() os.Error { // status. // // If the command fails to run or doesn't complete successfully, the -// error is of type *os.Waitmsg. Other error types may be +// error is of type *ExitError. Other error types may be // returned for I/O problems. -func (c *Cmd) Wait() os.Error { +func (c *Cmd) Wait() error { if c.Process == nil { - return os.NewError("exec: not started") + return errors.New("exec: not started") } if c.finished { - return os.NewError("exec: Wait was already called") + return errors.New("exec: Wait was already called") } c.finished = true msg, err := c.Process.Wait(0) - var copyError os.Error + var copyError error for _ = range c.goroutine { if err := <-c.errch; err != nil && copyError == nil { copyError = err @@ -290,16 +300,16 @@ func (c *Cmd) Wait() os.Error { if err != nil { return err } else if !msg.Exited() || msg.ExitStatus() != 0 { - return msg + return &ExitError{msg} } return copyError } // Output runs the command and returns its standard output. -func (c *Cmd) Output() ([]byte, os.Error) { +func (c *Cmd) Output() ([]byte, error) { if c.Stdout != nil { - return nil, os.NewError("exec: Stdout already set") + return nil, errors.New("exec: Stdout already set") } var b bytes.Buffer c.Stdout = &b @@ -309,12 +319,12 @@ func (c *Cmd) Output() ([]byte, os.Error) { // CombinedOutput runs the command and returns its combined standard // output and standard error. -func (c *Cmd) CombinedOutput() ([]byte, os.Error) { +func (c *Cmd) CombinedOutput() ([]byte, error) { if c.Stdout != nil { - return nil, os.NewError("exec: Stdout already set") + return nil, errors.New("exec: Stdout already set") } if c.Stderr != nil { - return nil, os.NewError("exec: Stderr already set") + return nil, errors.New("exec: Stderr already set") } var b bytes.Buffer c.Stdout = &b @@ -325,12 +335,12 @@ func (c *Cmd) CombinedOutput() ([]byte, os.Error) { // StdinPipe returns a pipe that will be connected to the command's // standard input when the command starts. -func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) { +func (c *Cmd) StdinPipe() (io.WriteCloser, error) { if c.Stdin != nil { - return nil, os.NewError("exec: Stdin already set") + return nil, errors.New("exec: Stdin already set") } if c.Process != nil { - return nil, os.NewError("exec: StdinPipe after process started") + return nil, errors.New("exec: StdinPipe after process started") } pr, pw, err := os.Pipe() if err != nil { @@ -345,12 +355,12 @@ func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) { // StdoutPipe returns a pipe that will be connected to the command's // standard output when the command starts. // The pipe will be closed automatically after Wait sees the command exit. -func (c *Cmd) StdoutPipe() (io.ReadCloser, os.Error) { +func (c *Cmd) StdoutPipe() (io.ReadCloser, error) { if c.Stdout != nil { - return nil, os.NewError("exec: Stdout already set") + return nil, errors.New("exec: Stdout already set") } if c.Process != nil { - return nil, os.NewError("exec: StdoutPipe after process started") + return nil, errors.New("exec: StdoutPipe after process started") } pr, pw, err := os.Pipe() if err != nil { @@ -365,12 +375,12 @@ func (c *Cmd) StdoutPipe() (io.ReadCloser, os.Error) { // StderrPipe returns a pipe that will be connected to the command's // standard error when the command starts. // The pipe will be closed automatically after Wait sees the command exit. -func (c *Cmd) StderrPipe() (io.ReadCloser, os.Error) { +func (c *Cmd) StderrPipe() (io.ReadCloser, error) { if c.Stderr != nil { - return nil, os.NewError("exec: Stderr already set") + return nil, errors.New("exec: Stderr already set") } if c.Process != nil { - return nil, os.NewError("exec: StderrPipe after process started") + return nil, errors.New("exec: StderrPipe after process started") } pr, pw, err := os.Pipe() if err != nil { |