src/pkg/os/exec_posix.go - The Go Programming Language

Golang

Source file src/pkg/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 netbsd openbsd windows
     6	
     7	package os
     8	
     9	import (
    10		"syscall"
    11	)
    12	
    13	func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
    14		// Double-check existence of the directory we want
    15		// to chdir into.  We can make the error clearer this way.
    16		if attr != nil && attr.Dir != "" {
    17			if _, err := Stat(attr.Dir); err != nil {
    18				pe := err.(*PathError)
    19				pe.Op = "chdir"
    20				return nil, pe
    21			}
    22		}
    23	
    24		sysattr := &syscall.ProcAttr{
    25			Dir: attr.Dir,
    26			Env: attr.Env,
    27			Sys: attr.Sys,
    28		}
    29		if sysattr.Env == nil {
    30			sysattr.Env = Environ()
    31		}
    32		for _, f := range attr.Files {
    33			sysattr.Files = append(sysattr.Files, f.Fd())
    34		}
    35	
    36		pid, h, e := syscall.StartProcess(name, argv, sysattr)
    37		if e != nil {
    38			return nil, &PathError{"fork/exec", name, e}
    39		}
    40		return newProcess(pid, h), nil
    41	}
    42	
    43	func (p *Process) kill() error {
    44		return p.Signal(Kill)
    45	}
    46	
    47	// ProcessState stores information about a process, as reported by Wait.
    48	type ProcessState struct {
    49		pid    int                // The process's id.
    50		status syscall.WaitStatus // System-dependent status info.
    51		rusage *syscall.Rusage
    52	}
    53	
    54	// Pid returns the process id of the exited process.
    55	func (p *ProcessState) Pid() int {
    56		return p.pid
    57	}
    58	
    59	func (p *ProcessState) exited() bool {
    60		return p.status.Exited()
    61	}
    62	
    63	func (p *ProcessState) success() bool {
    64		return p.status.ExitStatus() == 0
    65	}
    66	
    67	func (p *ProcessState) sys() interface{} {
    68		return p.status
    69	}
    70	
    71	func (p *ProcessState) sysUsage() interface{} {
    72		return p.rusage
    73	}
    74	
    75	// Convert i to decimal string.
    76	func itod(i int) string {
    77		if i == 0 {
    78			return "0"
    79		}
    80	
    81		u := uint64(i)
    82		if i < 0 {
    83			u = -u
    84		}
    85	
    86		// Assemble decimal in reverse order.
    87		var b [32]byte
    88		bp := len(b)
    89		for ; u > 0; u /= 10 {
    90			bp--
    91			b[bp] = byte(u%10) + '0'
    92		}
    93	
    94		if i < 0 {
    95			bp--
    96			b[bp] = '-'
    97		}
    98	
    99		return string(b[bp:])
   100	}
   101	
   102	func (p *ProcessState) String() string {
   103		if p == nil {
   104			return "<nil>"
   105		}
   106		status := p.Sys().(syscall.WaitStatus)
   107		res := ""
   108		switch {
   109		case status.Exited():
   110			res = "exit status " + itod(status.ExitStatus())
   111		case status.Signaled():
   112			res = "signal " + itod(int(status.Signal()))
   113		case status.Stopped():
   114			res = "stop signal " + itod(int(status.StopSignal()))
   115			if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 {
   116				res += " (trap " + itod(status.TrapCause()) + ")"
   117			}
   118		case status.Continued():
   119			res = "continued"
   120		}
   121		if status.CoreDump() {
   122			res += " (core dumped)"
   123		}
   124		return res
   125	}