diff --git a/kill/kill.go b/kill/kill.go new file mode 100644 index 0000000..d130271 --- /dev/null +++ b/kill/kill.go @@ -0,0 +1,102 @@ +package main + +import ( + "errors" + "fmt" + "os" + "syscall" + + "github.com/alexflint/go-arg" + common "source.heropunch.io/tomo/go-coreutils" +) + +var BadSignalName = errors.New("bad signal name") + +func selectSignal(signame string) (syscall.Signal, error) { + switch signame { + case "TERM": + return syscall.SIGTERM, nil + case "KILL": + return syscall.SIGKILL, nil + case "PIPE": + return syscall.SIGPIPE, nil + case "INT": + return syscall.SIGINT, nil + case "QUIT": + return syscall.SIGQUIT, nil + case "SEGV": + return syscall.SIGSEGV, nil + case "STOP": + return syscall.SIGSTOP, nil + case "CONT": + return syscall.SIGCONT, nil + case "0": + return 0, nil + case "ABRT": + return syscall.SIGABRT, nil + case "ALRM": + return syscall.SIGALRM, nil + case "BUS": + return syscall.SIGBUS, nil + case "CHLD": + return syscall.SIGCHLD, nil + case "FPE": + return syscall.SIGFPE, nil + case "HUP": + return syscall.SIGHUP, nil + case "ILL": + return syscall.SIGILL, nil + case "TSTP": + return syscall.SIGTSTP, nil + case "TTIN": + return syscall.SIGTTIN, nil + case "TTOU": + return syscall.SIGTTOU, nil + case "USR1": + return syscall.SIGUSR1, nil + case "USR2": + return syscall.SIGUSR2, nil + case "URG": + return syscall.SIGURG, nil + default: + return -1, BadSignalName + } +} + +func main() { + var args struct { + SignalName string `arg:"-s"` + List int `arg:"-l"` + PIDs []int `arg:"positional"` + } + + args.SignalName = "TERM" + args.List = -1 + + p := arg.MustParse(&args) + if len(os.Args) == 1 { + p.WriteUsage(os.Stderr) + os.Exit(1) + } + + sig, err := selectSignal(args.SignalName) + common.ExitIfError(err) + + exitCode := 0 + if len(args.PIDs) > 0 { + for _, pid := range args.PIDs { + process, err := os.FindProcess(pid) + if err != nil { + common.PrintToStderr(fmt.Sprintf("error finding process %v: %v", pid, err)) + exitCode = 1 + continue + } + err = process.Signal(sig) + if err != nil { + common.PrintToStderr(fmt.Sprintf("kill %v: %v", pid, err)) + exitCode = 1 + } + } + } + os.Exit(exitCode) +}