-
Notifications
You must be signed in to change notification settings - Fork 9
/
command.go
118 lines (99 loc) · 2.6 KB
/
command.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
package modgearman
import (
"strings"
shellwords "github.com/mattn/go-shellwords"
)
// CommandExecType is used to set the execution path
type CommandExecType int
const (
// Shell uses /bin/sh
Shell CommandExecType = iota
// Exec uses exec without a shell
Exec
// EPN is the embedded perl interpreter
EPN
// Internal is for internal checks
Internal
)
type command struct {
ExecType CommandExecType
Command string
Args []string
Env map[string]string
Negate *Negate
InternalCheck InternalCheck
}
func parseCommand(rawCommand string, config *configurationStruct) *command {
parsed := &command{
ExecType: Shell,
Command: rawCommand,
Args: make([]string, 0),
Env: make(map[string]string),
}
// adjust command to run with a shell
defer func() {
if parsed.ExecType == Shell {
parsed.Args = []string{"-c", parsed.Command}
parsed.Command = "/bin/sh"
}
}()
if strings.ContainsAny(rawCommand, "!$^&*()~[]\\|{};<>?`") {
return parsed
}
var envs []string
var args []string
var err error
if !strings.ContainsAny(rawCommand, `'"`) {
envs, args = parseShellArgsWithoutQuotes(rawCommand)
} else {
// don't try to parse super long command lines, shellwords is pretty slow
if len(rawCommand) > 100000 {
return parsed
}
envs, args, err = shellwords.ParseWithEnvs(rawCommand)
if err != nil {
logger.Debugf("failed to parse shell words: %w: %s", err, err.Error())
return parsed
}
}
parsed.Command = args[0]
parsed.Args = args[1:]
parsed.ExecType = Exec
for _, env := range envs {
splitted := strings.SplitN(env, "=", 2)
parsed.Env[splitted[0]] = splitted[1]
}
if fileUsesEmbeddedPerl(parsed.Command, config) {
parsed.ExecType = EPN
}
// use internal negate implementation
if config.internalNegate && strings.HasSuffix(parsed.Command, "/negate") {
ParseNegate(parsed)
}
// use internal check_dummy implementation
if config.internalCheckDummy && strings.HasSuffix(parsed.Command, "/check_dummy") {
parsed.InternalCheck = &InternalCheckDummy{}
parsed.ExecType = Internal
}
// use internal check_nsc_web implementation
if config.internalCheckNscWeb && strings.HasSuffix(parsed.Command, "/check_nsc_web") {
parsed.InternalCheck = &InternalCheckNSCWeb{}
parsed.ExecType = Internal
}
return parsed
}
func parseShellArgsWithoutQuotes(rawCommand string) (envs []string, args []string) {
splitted := strings.Fields(rawCommand)
inEnv := true
for _, s := range splitted {
if inEnv {
if strings.Contains(s, "=") {
envs = append(envs, s)
continue
}
inEnv = false
}
args = append(args, s)
}
return
}