1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "plugins/thresholds.hpp"
4 #include <boost/program_options.hpp>
12 namespace po = boost::program_options;
14 struct printInfoStruct
23 static int parseArguments(int ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo)
25 WCHAR namePath[MAX_PATH];
26 GetModuleFileName(NULL, namePath, MAX_PATH);
27 WCHAR *progName = PathFindFileName(namePath);
29 po::options_description desc;
32 ("help,h", "Print help message and exit")
33 ("version,V", "Print version and exit")
34 ("debug,d", "Verbose/Debug output")
35 ("user,u", po::wvalue<std::wstring>(), "Count only processes of user")
36 ("warning,w", po::wvalue<std::wstring>(), "Warning threshold")
37 ("critical,c", po::wvalue<std::wstring>(), "Critical threshold")
40 po::wcommand_line_parser parser(ac, av);
47 po::command_line_style::unix_style |
48 po::command_line_style::allow_long_disguise)
52 } catch (const std::exception& e) {
53 std::cout << e.what() << '\n' << desc << '\n';
57 if (vm.count("help")) {
58 std::wcout << progName << " Help\n\tVersion: " << VERSION << '\n';
60 L"%s is a simple program to check a machines processes.\n"
61 L"You can use the following options to define its behaviour:\n\n", progName);
64 L"\nIt will then output a string looking something like this:\n\n"
65 L"\tPROCS WARNING 67 | load=67;50;90;0\n\n"
66 L"\"PROCS\" being the type of the check, \"WARNING\" the returned status\n"
67 L"and \"67\" is the returned value.\n"
68 L"The performance data is found behind the \"|\", in order:\n"
69 L"returned value, warning threshold, critical threshold, minimal value and,\n"
70 L"if applicable, the maximal value. Performance data will only be displayed when\n"
71 L"you set at least one threshold\n\n"
72 L"For \"-user\" option keep in mind you need root to see other users processes\n\n"
73 L"%s' exit codes denote the following:\n"
74 L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
75 L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
76 L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
77 L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
78 L"Threshold syntax:\n\n"
80 L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
81 L"(unless stated differently)\n\n"
83 L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
85 L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
87 L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
89 L"if the plugin accepts percentage based thresholds those will be used.\n"
90 L"Does nothing if the plugin does not accept percentages, or only uses\n"
91 L"percentage thresholds. Ranges can be used with \"%%\", but both range values need\n"
92 L"to end with a percentage sign.\n\n"
93 L"All of these options work with the critical threshold \"-c\" too."
99 if (vm.count("version")) {
100 std::wcout << "Version: " << VERSION << '\n';
104 if (vm.count("warning")) {
106 printInfo.warn = threshold(vm["warning"].as<std::wstring>());
107 } catch (const std::invalid_argument& e) {
108 std::cout << e.what() << '\n';
112 if (vm.count("critical")) {
114 printInfo.crit = threshold(vm["critical"].as<std::wstring>());
115 } catch (const std::invalid_argument& e) {
116 std::cout << e.what() << '\n';
121 if (vm.count("user"))
122 printInfo.user = vm["user"].as<std::wstring>();
124 l_Debug = vm.count("debug") > 0;
129 static int printOutput(const int numProcs, printInfoStruct& printInfo)
132 std::wcout << L"Constructing output string" << '\n';
136 if (printInfo.warn.rend(numProcs))
139 if (printInfo.crit.rend(numProcs))
143 if (!printInfo.user.empty())
144 user = L" processes of user " + printInfo.user;
146 std::wcout << L"PROCS ";
153 std::wcout << L"WARNING";
156 std::wcout << L"CRITICAL";
160 std::wcout << L" " << numProcs << user << L" | procs=" << numProcs << L";"
161 << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << '\n';
166 static int countProcs()
169 std::wcout << L"Counting all processes" << '\n';
172 std::wcout << L"Creating snapshot" << '\n';
174 HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
175 if (hProcessSnap == INVALID_HANDLE_VALUE)
179 pe32.dwSize = sizeof(PROCESSENTRY32);
182 std::wcout << L"Grabbing first proccess" << '\n';
184 if (!Process32First(hProcessSnap, &pe32)) {
185 CloseHandle(hProcessSnap);
190 std::wcout << L"Counting processes..." << '\n';
196 } while (Process32Next(hProcessSnap, &pe32));
199 std::wcout << L"Found " << numProcs << L" processes. Cleaning up udn returning" << '\n';
201 CloseHandle(hProcessSnap);
206 static int countProcs(const std::wstring& user)
209 std::wcout << L"Counting all processes of user" << user << '\n';
211 const WCHAR *wuser = user.c_str();
214 HANDLE hProcessSnap, hProcess = NULL, hToken = NULL;
216 DWORD dwReturnLength, dwAcctName, dwDomainName;
217 PTOKEN_USER pSIDTokenUser = NULL;
218 SID_NAME_USE sidNameUse;
219 LPWSTR AcctName, DomainName;
222 std::wcout << L"Creating snapshot" << '\n';
224 hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
225 if (hProcessSnap == INVALID_HANDLE_VALUE)
228 pe32.dwSize = sizeof(PROCESSENTRY32);
231 std::wcout << L"Grabbing first proccess" << '\n';
233 if (!Process32First(hProcessSnap, &pe32))
237 std::wcout << L"Counting processes..." << '\n';
241 std::wcout << L"Getting process token" << '\n';
244 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
245 if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
246 //Won't count pid 0 (system idle) and 4/8 (Sytem)
249 //Get dwReturnLength in first call
251 if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwReturnLength)
252 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
255 pSIDTokenUser = reinterpret_cast<PTOKEN_USER>(new BYTE[dwReturnLength]);
256 memset(pSIDTokenUser, 0, dwReturnLength);
259 std::wcout << L"Received token, saving information" << '\n';
261 //write Info in pSIDTokenUser
262 if (!GetTokenInformation(hToken, TokenUser, pSIDTokenUser, dwReturnLength, NULL))
271 std::wcout << L"Looking up SID" << '\n';
273 //get dwAcctName and dwDomainName size
274 if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName,
275 (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse)
276 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
279 AcctName = reinterpret_cast<LPWSTR>(new WCHAR[dwAcctName]);
280 DomainName = reinterpret_cast<LPWSTR>(new WCHAR[dwDomainName]);
282 if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName,
283 (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse))
287 std::wcout << L"Comparing " << AcctName << L" to " << wuser << '\n';
288 if (!wcscmp(AcctName, wuser)) {
291 std::wcout << L"Is process of " << wuser << L" (" << numProcs << L")" << '\n';
294 delete[] reinterpret_cast<LPWSTR>(AcctName);
295 delete[] reinterpret_cast<LPWSTR>(DomainName);
297 } while (Process32Next(hProcessSnap, &pe32));
301 CloseHandle(hProcessSnap);
303 CloseHandle(hProcess);
307 delete[] reinterpret_cast<PTOKEN_USER>(pSIDTokenUser);
311 int wmain(int argc, WCHAR **argv)
313 po::variables_map vm;
314 printInfoStruct printInfo = { };
316 int r = parseArguments(argc, argv, vm, printInfo);
321 if (!printInfo.user.empty())
322 return printOutput(countProcs(printInfo.user), printInfo);
324 return printOutput(countProcs(), printInfo);