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 }