master
go 56 lines 1.07 KB
Raw
1 package main
2
3 import (
4 "context"
5 "fmt"
6 "os"
7 "os/exec"
8 "strconv"
9 "syscall"
10 "time"
11 )
12
13 func main() {
14 if len(os.Args) < 3 {
15 fmt.Fprintf(os.Stderr,
16 "Usage: %s <timeout-in-sec> <command ...>\n", os.Args[0])
17 os.Exit(1)
18 }
19 timeout, err := strconv.ParseUint(os.Args[1], 10, 32)
20 if err != nil {
21 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
22 os.Exit(1)
23 }
24 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
25 defer cancel()
26
27 cmd := exec.CommandContext(ctx, os.Args[2], os.Args[3:]...)
28 cmd.Stdin = os.Stdin
29 cmd.Stdout = os.Stdout
30 cmd.Stderr = os.Stderr
31 err = cmd.Start()
32 if err != nil {
33 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
34 }
35 err = cmd.Wait()
36
37 if err != nil {
38 if ctx.Err() != nil {
39 os.Exit(124)
40 } else {
41 exitErr, ok := err.(*exec.ExitError)
42 if !ok {
43 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
44 os.Exit(255)
45 }
46 waits, ok := exitErr.Sys().(syscall.WaitStatus)
47 if !ok {
48 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
49 os.Exit(255)
50 }
51 os.Exit(waits.ExitStatus())
52 }
53 } else {
54 os.Exit(0)
55 }
56 }