-
Notifications
You must be signed in to change notification settings - Fork 0
/
Process.h
239 lines (208 loc) · 6.62 KB
/
Process.h
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Stephen Foulds
#pragma once
#include <chrono>
#include <regex>
#include <string>
#include <vector>
/**
* Often commands will be prefixed with the interpreter to use (e.g. /bin/sh -c echo "hello world"). Strip
* these off to reveal the "true" command
*/
static std::vector<std::string> prefixesToStrip =
{"/bin/sh -c ", "/bin/sh ", "/bin/bash -c ", "/bin/bash ", "sh -c",
"sh ", "/bin/busybox sh -c", "/bin/busybox sh ", "/bin/busybox bash "};
static std::regex envVarRegex(R"(^[A-Z_]+=(`.*`|\$\(.*\)|[\w\/\${}:]+);?)");
struct processInfo
{
pid_t pid;
pid_t parentPid;
pid_t grandparentPid;
std::chrono::time_point<std::chrono::system_clock> endTime;
std::chrono::time_point<std::chrono::system_clock> startTime;
uint32_t exitCode;
std::string commandLine;
std::string parentCommandLine;
std::string grandparentCommandLine;
std::string systemdServiceName;
/**
* Use some heuristics to try and get a suitable name for the timeline group
*
* @return
*/
[[nodiscard]] std::string GetGroupName()
{
if (GetStrippedParentName().empty())
{
return GetStrippedGrandparentName();
}
/* for (const auto& prefix : prefixesToStrip)
{
if (parentCommandLine.rfind(prefix, 0) == 0)
{
return GetStrippedGrandparentName();
}
}*/
return GetStrippedParentName();
}
[[nodiscard]] std::string GetName() { return GetNameFromCommandLine(commandLine); }
/**
* Get the name of the process, with any leading interpreter removed
*
* Removes any arguments passed to the process, just leaving the name of the process (including directory)
*
* Examples:
* * "/bin/sh -c ls" becomes "ls"
* * "ls -alh" becomes "ls"
* * "/lib/rdk/script.sh --foo --bar" becomes "/lib/rdk/script.sh"
*
* @return stripped process name string
*/
[[nodiscard]] std::string GetStrippedName()
{
if (mStrippedName.empty())
{
mStrippedName = GetNameFromCommandLine(GetStrippedCommandLine());
}
return mStrippedName;
}
/**
* Get the command line of the process, with any leading interpreter removed
*
* Examples:
* * "/bin/sh -c ls -alh" becomes "ls -alh"
* * "ls -alh" becomes "ls -alh"
* * "/lib/rdk/script.sh --foo --bar" becomes "/lib/rdk/script.sh --foo --bar"
*
* @return stripped process command line string
*/
[[nodiscard]] std::string GetStrippedCommandLine()
{
if (mStrippedCmdline.empty())
{
mStrippedCmdline = StripPrefix(commandLine);
}
return mStrippedCmdline;
}
/**
* Get the name of the parent process, with any leading interpreter removed
*
* @return stripped parent process name
*/
[[nodiscard]] std::string GetStrippedParentName()
{
if (mStrippedParentName.empty())
{
mStrippedParentName = GetNameFromCommandLine(GetStrippedParentCommandLine());
}
return mStrippedParentName;
}
/**
* Get the name of the grandparent process if possible, with any leading interpreter removed
*
* @return stripped grandparent process name
*/
[[nodiscard]] std::string GetStrippedGrandparentName()
{
if (mStrippedGrandparentName.empty())
{
mStrippedGrandparentName = GetNameFromCommandLine(GetStrippedGrandparentCommandLine());
}
return mStrippedGrandparentName;
}
/**
* Get the command line of the grandparent process, with any leading interpreter removed
*
* @return stripped grandparent command line string
*/
[[nodiscard]] std::string GetStrippedParentCommandLine()
{
if (mStrippedParentCmdline.empty())
{
mStrippedParentCmdline = StripPrefix(parentCommandLine);
}
return mStrippedParentCmdline;
}
/**
* Get the command line of the parent process, with any leading interpreter removed
*
* @return stripped parent command line string
*/
[[nodiscard]] std::string GetStrippedGrandparentCommandLine()
{
if (mStrippedGrandparentCmdline.empty())
{
mStrippedGrandparentCmdline = StripPrefix(grandparentCommandLine);
}
return mStrippedGrandparentCmdline;
}
private:
/**
* Remove the interpreter prefix from a given process commandline
*
* @param cmdline
* @return
*/
[[nodiscard]] static std::string StripPrefix(const std::string &cmdline)
{
for (const auto &prefix : prefixesToStrip)
{
if (/*cmdline.length() > prefix.length() && */ cmdline.rfind(prefix, 0) == 0)
{
auto tmp = cmdline;
tmp.erase(tmp.begin(), tmp.begin() + prefix.size());
if (tmp[0] == ' ')
{
tmp.erase(0, 1);
}
return tmp;
}
}
return cmdline;
}
/**
* Attempts to work out the name of the process, given a full command line.
*
* This will return the first part of a given path, removing any arguments supplied
*
* E.G
* * "/bin/ls -alh" becomes "/bin/ls"
* * "/bin/sh -c ls -alh" becomes "/bin/sh"
*
* You might want to strip the provided command line of any prefix before passing it to this function to get
* a more accurate name
*
* @param commandLine
* @return
*/
[[nodiscard]] static std::string GetNameFromCommandLine(const std::string &commandLine)
{
std::string name = commandLine;
// Remove any leading spaces
if (name[0] == ' ')
{
name.erase(0, 1);
}
// Remove environment variable(s)
name = std::regex_replace(name, envVarRegex, "");
if (name[0] == ' ')
{
name.erase(0, 1);
}
// First the first space - name is everything before that
auto spacePos = name.find_first_of(' ');
if (spacePos != std::string::npos)
{
auto it = name.begin();
std::advance(it, spacePos);
name.erase(it, name.end());
}
return name;
}
std::string mStrippedName;
std::string mStrippedParentName;
std::string mStrippedGrandparentName;
std::string mStrippedCmdline;
std::string mStrippedParentCmdline;
std::string mStrippedGrandparentCmdline;
};