"Fossies" - the Fresh Open Source Software Archive

Member "icinga2-2.10.5/plugins/check_procs.cpp" (23 May 2019, 10215 Bytes) of package /linux/misc/icinga2-2.10.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "check_procs.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.10.0_vs_2.10.1.

    1 /******************************************************************************
    2  * Icinga 2                                                                   *
    3  * Copyright (C) 2012-2018 Icinga Development Team (https://icinga.com/)      *
    4  *                                                                            *
    5  * This program is free software; you can redistribute it and/or              *
    6  * modify it under the terms of the GNU General Public License                *
    7  * as published by the Free Software Foundation; either version 2             *
    8  * of the License, or (at your option) any later version.                     *
    9  *                                                                            *
   10  * This program is distributed in the hope that it will be useful,            *
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
   13  * GNU General Public License for more details.                               *
   14  *                                                                            *
   15  * You should have received a copy of the GNU General Public License          *
   16  * along with this program; if not, write to the Free Software Foundation     *
   17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
   18  ******************************************************************************/
   19 
   20 #include "plugins/thresholds.hpp"
   21 #include <boost/program_options.hpp>
   22 #include <iostream>
   23 #include <windows.h>
   24 #include <shlwapi.h>
   25 #include <tlhelp32.h>
   26 
   27 #define VERSION 1.0
   28 
   29 namespace po = boost::program_options;
   30 
   31 struct printInfoStruct
   32 {
   33     threshold warn;
   34     threshold crit;
   35     std::wstring user;
   36 };
   37 
   38 static bool l_Debug;
   39 
   40 static int parseArguments(int ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo)
   41 {
   42     WCHAR namePath[MAX_PATH];
   43     GetModuleFileName(NULL, namePath, MAX_PATH);
   44     WCHAR *progName = PathFindFileName(namePath);
   45 
   46     po::options_description desc;
   47 
   48     desc.add_options()
   49         ("help,h", "Print help message and exit")
   50         ("version,V", "Print version and exit")
   51         ("debug,d", "Verbose/Debug output")
   52         ("user,u", po::wvalue<std::wstring>(), "Count only processes of user")
   53         ("warning,w", po::wvalue<std::wstring>(), "Warning threshold")
   54         ("critical,c", po::wvalue<std::wstring>(), "Critical threshold")
   55         ;
   56 
   57     po::wcommand_line_parser parser(ac, av);
   58 
   59     try {
   60         po::store(
   61             parser
   62             .options(desc)
   63             .style(
   64                 po::command_line_style::unix_style |
   65                 po::command_line_style::allow_long_disguise)
   66             .run(),
   67             vm);
   68         vm.notify();
   69     } catch (const std::exception& e) {
   70         std::cout << e.what() << '\n' << desc << '\n';
   71         return 3;
   72     }
   73 
   74     if (vm.count("help")) {
   75         std::wcout << progName << " Help\n\tVersion: " << VERSION << '\n';
   76         wprintf(
   77             L"%s is a simple program to check a machines processes.\n"
   78             L"You can use the following options to define its behaviour:\n\n", progName);
   79         std::cout << desc;
   80         wprintf(
   81             L"\nIt will then output a string looking something like this:\n\n"
   82             L"\tPROCS WARNING 67 | load=67;50;90;0\n\n"
   83             L"\"PROCS\" being the type of the check, \"WARNING\" the returned status\n"
   84             L"and \"67\" is the returned value.\n"
   85             L"The performance data is found behind the \"|\", in order:\n"
   86             L"returned value, warning threshold, critical threshold, minimal value and,\n"
   87             L"if applicable, the maximal value. Performance data will only be displayed when\n"
   88             L"you set at least one threshold\n\n"
   89             L"For \"-user\" option keep in mind you need root to see other users processes\n\n"
   90             L"%s' exit codes denote the following:\n"
   91             L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
   92             L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
   93             L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
   94             L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
   95             L"Threshold syntax:\n\n"
   96             L"-w THRESHOLD\n"
   97             L"warn if threshold is broken, which means VALUE > THRESHOLD\n"
   98             L"(unless stated differently)\n\n"
   99             L"-w !THRESHOLD\n"
  100             L"inverts threshold check, VALUE < THRESHOLD (analogous to above)\n\n"
  101             L"-w [THR1-THR2]\n"
  102             L"warn is VALUE is inside the range spanned by THR1 and THR2\n\n"
  103             L"-w ![THR1-THR2]\n"
  104             L"warn if VALUE is outside the range spanned by THR1 and THR2\n\n"
  105             L"-w THRESHOLD%%\n"
  106             L"if the plugin accepts percentage based thresholds those will be used.\n"
  107             L"Does nothing if the plugin does not accept percentages, or only uses\n"
  108             L"percentage thresholds. Ranges can be used with \"%%\", but both range values need\n"
  109             L"to end with a percentage sign.\n\n"
  110             L"All of these options work with the critical threshold \"-c\" too."
  111             , progName);
  112         std::cout << '\n';
  113         return 0;
  114     }
  115 
  116     if (vm.count("version")) {
  117         std::wcout << "Version: " << VERSION << '\n';
  118         return 0;
  119     }
  120 
  121     if (vm.count("warning")) {
  122         try {
  123             printInfo.warn = threshold(vm["warning"].as<std::wstring>());
  124         } catch (const std::invalid_argument& e) {
  125             std::cout << e.what() << '\n';
  126             return 3;
  127         }
  128     }
  129     if (vm.count("critical")) {
  130         try {
  131             printInfo.crit = threshold(vm["critical"].as<std::wstring>());
  132         } catch (const std::invalid_argument& e) {
  133             std::cout << e.what() << '\n';
  134             return 3;
  135         }
  136     }
  137 
  138     if (vm.count("user"))
  139         printInfo.user = vm["user"].as<std::wstring>();
  140 
  141     l_Debug = vm.count("debug") > 0;
  142 
  143     return -1;
  144 }
  145 
  146 static int printOutput(const int numProcs, printInfoStruct& printInfo)
  147 {
  148     if (l_Debug)
  149         std::wcout << L"Constructing output string" << '\n';
  150 
  151     state state = OK;
  152 
  153     if (printInfo.warn.rend(numProcs))
  154         state = WARNING;
  155 
  156     if (printInfo.crit.rend(numProcs))
  157         state = CRITICAL;
  158 
  159     std::wstring user;
  160     if (!printInfo.user.empty())
  161         user = L" processes of user " + printInfo.user;
  162 
  163     std::wcout << L"PROCS ";
  164 
  165     switch (state) {
  166     case OK:
  167         std::wcout << L"OK";
  168         break;
  169     case WARNING:
  170         std::wcout << L"WARNING";
  171         break;
  172     case CRITICAL:
  173         std::wcout << L"CRITICAL";
  174         break;
  175     }
  176 
  177     std::wcout << L" " << numProcs << user << L" | procs=" << numProcs << L";"
  178         << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << '\n';
  179 
  180     return state;
  181 }
  182 
  183 static int countProcs()
  184 {
  185     if (l_Debug)
  186         std::wcout << L"Counting all processes" << '\n';
  187 
  188     if (l_Debug)
  189         std::wcout << L"Creating snapshot" << '\n';
  190 
  191     HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  192     if (hProcessSnap == INVALID_HANDLE_VALUE)
  193         return -1;
  194 
  195     PROCESSENTRY32 pe32;
  196     pe32.dwSize = sizeof(PROCESSENTRY32);
  197 
  198     if (l_Debug)
  199         std::wcout << L"Grabbing first proccess" << '\n';
  200 
  201     if (!Process32First(hProcessSnap, &pe32)) {
  202         CloseHandle(hProcessSnap);
  203         return -1;
  204     }
  205 
  206     if (l_Debug)
  207         std::wcout << L"Counting processes..." << '\n';
  208 
  209     int numProcs = 0;
  210 
  211     do {
  212         ++numProcs;
  213     } while (Process32Next(hProcessSnap, &pe32));
  214 
  215     if (l_Debug)
  216         std::wcout << L"Found " << numProcs << L" processes. Cleaning up udn returning" << '\n';
  217 
  218     CloseHandle(hProcessSnap);
  219 
  220     return numProcs;
  221 }
  222 
  223 static int countProcs(const std::wstring& user)
  224 {
  225     if (l_Debug)
  226         std::wcout << L"Counting all processes of user" << user << '\n';
  227 
  228     const WCHAR *wuser = user.c_str();
  229     int numProcs = 0;
  230 
  231     HANDLE hProcessSnap, hProcess = NULL, hToken = NULL;
  232     PROCESSENTRY32 pe32;
  233     DWORD dwReturnLength, dwAcctName, dwDomainName;
  234     PTOKEN_USER pSIDTokenUser = NULL;
  235     SID_NAME_USE sidNameUse;
  236     LPWSTR AcctName, DomainName;
  237 
  238     if (l_Debug)
  239         std::wcout << L"Creating snapshot" << '\n';
  240 
  241     hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  242     if (hProcessSnap == INVALID_HANDLE_VALUE)
  243         goto die;
  244 
  245     pe32.dwSize = sizeof(PROCESSENTRY32);
  246 
  247     if (l_Debug)
  248         std::wcout << L"Grabbing first proccess" << '\n';
  249 
  250     if (!Process32First(hProcessSnap, &pe32))
  251         goto die;
  252 
  253     if (l_Debug)
  254         std::wcout << L"Counting processes..." << '\n';
  255 
  256     do {
  257         if (l_Debug)
  258             std::wcout << L"Getting process token" << '\n';
  259 
  260         //get ProcessToken
  261         hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
  262         if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
  263             //Won't count pid 0 (system idle) and 4/8 (Sytem)
  264             continue;
  265 
  266         //Get dwReturnLength in first call
  267         dwReturnLength = 1;
  268         if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwReturnLength)
  269             && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  270             continue;
  271 
  272         pSIDTokenUser = reinterpret_cast<PTOKEN_USER>(new BYTE[dwReturnLength]);
  273         memset(pSIDTokenUser, 0, dwReturnLength);
  274 
  275         if (l_Debug)
  276             std::wcout << L"Received token, saving information" << '\n';
  277 
  278         //write Info in pSIDTokenUser
  279         if (!GetTokenInformation(hToken, TokenUser, pSIDTokenUser, dwReturnLength, NULL))
  280             continue;
  281 
  282         AcctName = NULL;
  283         DomainName = NULL;
  284         dwAcctName = 1;
  285         dwDomainName = 1;
  286 
  287         if (l_Debug)
  288             std::wcout << L"Looking up SID" << '\n';
  289 
  290         //get dwAcctName and dwDomainName size
  291         if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName,
  292             (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse)
  293             && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  294             continue;
  295 
  296         AcctName = reinterpret_cast<LPWSTR>(new WCHAR[dwAcctName]);
  297         DomainName = reinterpret_cast<LPWSTR>(new WCHAR[dwDomainName]);
  298 
  299         if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName,
  300             (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse))
  301             continue;
  302 
  303         if (l_Debug)
  304             std::wcout << L"Comparing " << AcctName << L" to " << wuser << '\n';
  305         if (!wcscmp(AcctName, wuser)) {
  306             ++numProcs;
  307             if (l_Debug)
  308                 std::wcout << L"Is process of " << wuser << L" (" << numProcs << L")" << '\n';
  309         }
  310 
  311         delete[] reinterpret_cast<LPWSTR>(AcctName);
  312         delete[] reinterpret_cast<LPWSTR>(DomainName);
  313 
  314     } while (Process32Next(hProcessSnap, &pe32));
  315 
  316 die:
  317     if (hProcessSnap)
  318         CloseHandle(hProcessSnap);
  319     if (hProcess)
  320         CloseHandle(hProcess);
  321     if (hToken)
  322         CloseHandle(hToken);
  323     if (pSIDTokenUser)
  324         delete[] reinterpret_cast<PTOKEN_USER>(pSIDTokenUser);
  325     return numProcs;
  326 }
  327 
  328 int wmain(int argc, WCHAR **argv)
  329 {
  330     po::variables_map vm;
  331     printInfoStruct printInfo = { };
  332 
  333     int r = parseArguments(argc, argv, vm, printInfo);
  334 
  335     if (r != -1)
  336         return r;
  337 
  338     if (!printInfo.user.empty())
  339         return printOutput(countProcs(printInfo.user), printInfo);
  340 
  341     return printOutput(countProcs(), printInfo);
  342 }