-
Notifications
You must be signed in to change notification settings - Fork 1
/
time_wrapper.go
132 lines (112 loc) · 2.81 KB
/
time_wrapper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"syscall"
"time"
)
var verbose bool
var days string
var daysList []string
var hourFrom int
var hourTo int
var timeZone string
var location *time.Location
var tail []string
var version string
var printHelp bool
var printVersion bool
func initArgs() {
flag.BoolVar(&printHelp, "help", false, "print help and exit")
flag.BoolVar(&printVersion, "V", false, "print version and exit")
flag.BoolVar(&verbose, "v", false, "be verbose")
flag.StringVar(&days, "days", "0,1,2,3,4,5,6", "days from Sun - Sat")
flag.IntVar(&hourFrom, "from", 0, "active from, as an hour, 0-23 (default 0)")
flag.IntVar(&hourTo, "to", 24, "active until, as an hour, 0-24")
flag.StringVar(&timeZone, "timezone", "UTC", "timezone e.g. 'Europe/Berlin'")
flag.Parse()
if printHelp {
flag.PrintDefaults()
os.Exit(0)
}
if printVersion {
fmt.Println("time_wrapper Version:", version)
os.Exit(0)
}
if hourFrom < 0 || hourFrom > 23 {
fmt.Println("Invalid hour for 'from':", hourFrom)
os.Exit(3)
}
if hourTo < 0 || hourTo > 24 {
fmt.Println("Invalid hour for 'to':", hourTo)
os.Exit(3)
}
// this is the binary to run, if the time's right
tail = flag.Args()
if len(tail) < 1 {
os.Exit(3)
}
var err error
if location, err = time.LoadLocation(timeZone); err != nil {
fmt.Println(err)
os.Exit(3)
}
}
func main() {
initArgs()
now := time.Now().In(location)
nowDay := strconv.Itoa(int(now.Weekday()))
nowHour := now.Hour()
daysList := strings.Split(days, ",")
// defaulting to not execute to make the next part easier
willExecute := false
for _, _day := range daysList {
if string(_day) == nowDay {
willExecute = true
}
}
// don't run if it's too soon
if nowHour < hourFrom {
willExecute = false
}
// don't run if it's too late
if nowHour >= hourTo {
willExecute = false
}
if verbose {
fmt.Println("days : ", days)
fmt.Println("from : ", hourFrom)
fmt.Println("to : ", hourTo)
fmt.Println("tail : ", tail)
fmt.Println("timezone : ", location)
fmt.Println("now : ", now)
fmt.Println("nowD : ", nowDay)
fmt.Println("nowH : ", nowHour)
fmt.Println("run? : ", willExecute)
}
if !willExecute {
os.Exit(0)
}
// get the real path of the executable
binary, lookErr := exec.LookPath(tail[0])
if lookErr != nil {
fmt.Println(lookErr)
os.Exit(3)
}
env := os.Environ()
// execute, incl. stdout, stderr and exit code \o/
// > Exec invokes the execve(2) system call.
// this is why we leave tail alone and don't shift the first element
// > execve() does not return on success, and the text, data, bss,
// > and stack of the calling process are overwritten by that of
// > the program loaded.
execErr := syscall.Exec(binary, tail, env)
if execErr != nil {
fmt.Println(execErr)
os.Exit(2)
}
}