os: add Process.Kill and Process.Signal

R=alex.brainman, r, rsc, krasin, iant, rsc, r
CC=golang-dev
https://golang.org/cl/4437091
diff --git a/src/pkg/os/Makefile b/src/pkg/os/Makefile
index c781df7..497e5a9 100644
--- a/src/pkg/os/Makefile
+++ b/src/pkg/os/Makefile
@@ -27,6 +27,7 @@
 	sys_bsd.go\
 	exec_posix.go\
 	exec_unix.go\
+	signal_unix.go\
 
 GOFILES_darwin=\
 	dir_unix.go\
@@ -38,6 +39,7 @@
 	sys_bsd.go\
 	exec_posix.go\
 	exec_unix.go\
+	signal_unix.go\
 
 GOFILES_linux=\
 	dir_unix.go\
@@ -49,6 +51,7 @@
 	sys_linux.go\
 	exec_posix.go\
 	exec_unix.go\
+	signal_unix.go\
 
 GOFILES_windows=\
 	dir_windows.go\
@@ -60,6 +63,7 @@
 	sys_windows.go\
 	exec_posix.go\
 	exec_windows.go\
+	signal_windows.go\
 
 GOFILES_plan9=\
 	dir_plan9.go\
@@ -72,4 +76,12 @@
 
 GOFILES+=$(GOFILES_$(GOOS))
 
+CLEANFILES+=signal_unix.go signal_windows.go
+
 include ../../Make.pkg
+
+signal_unix.go: ../syscall/zerrors_$(GOOS)_$(GOARCH).go
+	./mkunixsignals.sh $< > $@ || rm -f $@
+
+signal_windows.go: ../syscall/ztypes_$(GOOS)_$(GOARCH).go
+	./mkunixsignals.sh $< > $@ || rm -f $@
diff --git a/src/pkg/os/exec_posix.go b/src/pkg/os/exec_posix.go
index 9102dc0..bf992ef 100644
--- a/src/pkg/os/exec_posix.go
+++ b/src/pkg/os/exec_posix.go
@@ -4,7 +4,25 @@
 
 package os
 
-import "syscall"
+import (
+	"runtime"
+	"syscall"
+)
+
+// A Signal can represent any operating system signal.
+type Signal interface {
+	String() string
+}
+
+type UnixSignal int32
+
+func (sig UnixSignal) String() string {
+	s := runtime.Signame(int32(sig))
+	if len(s) > 0 {
+		return s
+	}
+	return "UnixSignal"
+}
 
 // StartProcess starts a new process with the program, arguments and attributes
 // specified by name, argv and attr.
@@ -34,6 +52,11 @@
 	return newProcess(pid, h), nil
 }
 
+// Kill causes the Process to exit immediately.
+func (p *Process) Kill() Error {
+	return p.Signal(SIGKILL)
+}
+
 // Exec replaces the current process with an execution of the
 // named binary, with arguments argv and environment envv.
 // If successful, Exec never returns.  If it fails, it returns an Error.
diff --git a/src/pkg/os/exec_unix.go b/src/pkg/os/exec_unix.go
index 8990d6a..cf5ea9b 100644
--- a/src/pkg/os/exec_unix.go
+++ b/src/pkg/os/exec_unix.go
@@ -45,6 +45,14 @@
 	return w, nil
 }
 
+// Signal sends a signal to the Process.
+func (p *Process) Signal(sig Signal) Error {
+	if e := syscall.Kill(p.Pid, int(sig.(UnixSignal))); e != 0 {
+		return Errno(e)
+	}
+	return nil
+}
+
 // Release releases any resources associated with the Process.
 func (p *Process) Release() Error {
 	// NOOP for unix.
diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go
index ae8ffea..bac33b9 100644
--- a/src/pkg/os/exec_windows.go
+++ b/src/pkg/os/exec_windows.go
@@ -20,13 +20,23 @@
 		return nil, ErrorString("os: unexpected result from WaitForSingleObject")
 	}
 	var ec uint32
-	e = syscall.GetExitCodeProcess(uint32(p.handle), &ec)
+	e = syscall.GetExitCodeProcess(int32(p.handle), &ec)
 	if e != 0 {
 		return nil, NewSyscallError("GetExitCodeProcess", e)
 	}
 	return &Waitmsg{p.Pid, syscall.WaitStatus{s, ec}, new(syscall.Rusage)}, nil
 }
 
+// Signal sends a signal to the Process.
+func (p *Process) Signal(sig Signal) Error {
+	switch sig.(UnixSignal) {
+	case SIGKILL:
+		e := syscall.TerminateProcess(int32(p.handle), 1)
+		return NewSyscallError("TerminateProcess", e)
+	}
+	return Errno(syscall.EWINDOWS)
+}
+
 func (p *Process) Release() Error {
 	if p.handle == -1 {
 		return EINVAL
diff --git a/src/pkg/os/signal/mkunix.sh b/src/pkg/os/mkunixsignals.sh
similarity index 96%
rename from src/pkg/os/signal/mkunix.sh
rename to src/pkg/os/mkunixsignals.sh
index 653b016..6ec764c 100755
--- a/src/pkg/os/signal/mkunix.sh
+++ b/src/pkg/os/mkunixsignals.sh
@@ -8,7 +8,7 @@
 echo
 
 cat <<EOH
-package signal
+package os
 
 import (
   "syscall"
diff --git a/src/pkg/os/signal/Makefile b/src/pkg/os/signal/Makefile
index 013b91a..26f5876 100644
--- a/src/pkg/os/signal/Makefile
+++ b/src/pkg/os/signal/Makefile
@@ -7,11 +7,5 @@
 TARG=os/signal
 GOFILES=\
 	signal.go\
-	unix.go\
-
-CLEANFILES+=unix.go
 
 include ../../../Make.pkg
-
-unix.go: ../../syscall/zerrors_$(GOOS)_$(GOARCH).go
-	./mkunix.sh $< > $@ || rm -f $@
diff --git a/src/pkg/os/signal/signal.go b/src/pkg/os/signal/signal.go
index 666c03e..520f3f8 100644
--- a/src/pkg/os/signal/signal.go
+++ b/src/pkg/os/signal/signal.go
@@ -6,35 +6,20 @@
 package signal
 
 import (
+	"os"
 	"runtime"
-	"strconv"
 )
 
-// A Signal can represent any operating system signal.
-type Signal interface {
-	String() string
-}
-
-type UnixSignal int32
-
-func (sig UnixSignal) String() string {
-	s := runtime.Signame(int32(sig))
-	if len(s) > 0 {
-		return s
-	}
-	return "Signal " + strconv.Itoa(int(sig))
-}
-
 // Incoming is the global signal channel.
 // All signals received by the program will be delivered to this channel.
-var Incoming <-chan Signal
+var Incoming <-chan os.Signal
 
-func process(ch chan<- Signal) {
+func process(ch chan<- os.Signal) {
 	for {
 		var mask uint32 = runtime.Sigrecv()
 		for sig := uint(0); sig < 32; sig++ {
 			if mask&(1<<sig) != 0 {
-				ch <- UnixSignal(sig)
+				ch <- os.UnixSignal(sig)
 			}
 		}
 	}
@@ -42,7 +27,7 @@
 
 func init() {
 	runtime.Siginit()
-	ch := make(chan Signal) // Done here so Incoming can have type <-chan Signal
+	ch := make(chan os.Signal) // Done here so Incoming can have type <-chan Signal
 	Incoming = ch
 	go process(ch)
 }
diff --git a/src/pkg/os/signal/signal_test.go b/src/pkg/os/signal/signal_test.go
index f2679f1..00eb295 100644
--- a/src/pkg/os/signal/signal_test.go
+++ b/src/pkg/os/signal/signal_test.go
@@ -5,6 +5,7 @@
 package signal
 
 import (
+	"os"
 	"syscall"
 	"testing"
 )
@@ -13,7 +14,7 @@
 	// Send this process a SIGHUP.
 	syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0)
 
-	if sig := (<-Incoming).(UnixSignal); sig != SIGHUP {
-		t.Errorf("signal was %v, want %v", sig, SIGHUP)
+	if sig := (<-Incoming).(os.UnixSignal); sig != os.SIGHUP {
+		t.Errorf("signal was %v, want %v", sig, os.SIGHUP)
 	}
 }
diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
index bb93533..d01664d 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -141,8 +141,9 @@
 //sys	GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (errno int)
 //sys	CancelIo(s uint32) (errno int)
 //sys	CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (errno int) = CreateProcessW
-//sys	OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int)
-//sys	GetExitCodeProcess(handle uint32, exitcode *uint32) (errno int)
+//sys	OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle int32, errno int)
+//sys	TerminateProcess(handle int32, exitcode uint32) (errno int)
+//sys	GetExitCodeProcess(handle int32, exitcode *uint32) (errno int)
 //sys	GetStartupInfo(startupInfo *StartupInfo) (errno int) = GetStartupInfoW
 //sys	GetCurrentProcess() (pseudoHandle int32, errno int)
 //sys	DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (errno int)
@@ -697,10 +698,6 @@
 
 // TODO(brainman): fix all needed for os
 
-const (
-	SIGTRAP = 5
-)
-
 func Getpid() (pid int)   { return -1 }
 func Getppid() (ppid int) { return -1 }
 
diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go
index ce36ab6..447b090 100644
--- a/src/pkg/syscall/zsyscall_windows_386.go
+++ b/src/pkg/syscall/zsyscall_windows_386.go
@@ -46,6 +46,7 @@
 	procCancelIo                   = getSysProcAddr(modkernel32, "CancelIo")
 	procCreateProcessW             = getSysProcAddr(modkernel32, "CreateProcessW")
 	procOpenProcess                = getSysProcAddr(modkernel32, "OpenProcess")
+	procTerminateProcess           = getSysProcAddr(modkernel32, "TerminateProcess")
 	procGetExitCodeProcess         = getSysProcAddr(modkernel32, "GetExitCodeProcess")
 	procGetStartupInfoW            = getSysProcAddr(modkernel32, "GetStartupInfoW")
 	procGetCurrentProcess          = getSysProcAddr(modkernel32, "GetCurrentProcess")
@@ -542,7 +543,7 @@
 	return
 }
 
-func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int) {
+func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle int32, errno int) {
 	var _p0 uint32
 	if inheritHandle {
 		_p0 = 1
@@ -550,7 +551,7 @@
 		_p0 = 0
 	}
 	r0, _, e1 := Syscall(procOpenProcess, 3, uintptr(da), uintptr(_p0), uintptr(pid))
-	handle = uint32(r0)
+	handle = int32(r0)
 	if handle == 0 {
 		if e1 != 0 {
 			errno = int(e1)
@@ -563,7 +564,21 @@
 	return
 }
 
-func GetExitCodeProcess(handle uint32, exitcode *uint32) (errno int) {
+func TerminateProcess(handle int32, exitcode uint32) (errno int) {
+	r1, _, e1 := Syscall(procTerminateProcess, 2, uintptr(handle), uintptr(exitcode), 0)
+	if int(r1) == 0 {
+		if e1 != 0 {
+			errno = int(e1)
+		} else {
+			errno = EINVAL
+		}
+	} else {
+		errno = 0
+	}
+	return
+}
+
+func GetExitCodeProcess(handle int32, exitcode *uint32) (errno int) {
 	r1, _, e1 := Syscall(procGetExitCodeProcess, 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
diff --git a/src/pkg/syscall/ztypes_windows_386.go b/src/pkg/syscall/ztypes_windows_386.go
index 7b15ea4..b04fea5 100644
--- a/src/pkg/syscall/ztypes_windows_386.go
+++ b/src/pkg/syscall/ztypes_windows_386.go
@@ -49,6 +49,23 @@
 )
 
 const (
+	// More invented values for signals
+	SIGHUP  = 0x1
+	SIGINT  = 0x2
+	SIGQUIT = 0x3
+	SIGILL  = 0x4
+	SIGTRAP = 0x5
+	SIGABRT = 0x6
+	SIGBUS  = 0x7
+	SIGFPE  = 0x8
+	SIGKILL = 0x9
+	SIGSEGV = 0xb
+	SIGPIPE = 0xd
+	SIGALRM = 0xe
+	SIGTERM = 0xf
+)
+
+const (
 	GENERIC_READ    = 0x80000000
 	GENERIC_WRITE   = 0x40000000
 	GENERIC_EXECUTE = 0x20000000