]> granicus.if.org Git - icinga2/blobdiff - plugins/check_users.cpp
Merge pull request #7124 from Icinga/bugfix/namespace-thread-safe
[icinga2] / plugins / check_users.cpp
index 65379bda7d953588a71bef4ad1e4229cbb35aff7..9193551db957eb932bfafc1a505d38e8d00ecc88 100644 (file)
-/******************************************************************************
- * Icinga 2                                                                   *
- * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
- *                                                                            *
- * This program is free software; you can redistribute it and/or              *
- * modify it under the terms of the GNU General Public License                *
- * as published by the Free Software Foundation; either version 2             *
- * of the License, or (at your option) any later version.                     *
- *                                                                            *
- * This program is distributed in the hope that it will be useful,            *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
- * GNU General Public License for more details.                               *
- *                                                                            *
- * You should have received a copy of the GNU General Public License          *
- * along with this program; if not, write to the Free Software Foundation     *
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
- ******************************************************************************/
-#include <Windows.h>
-#include <Shlwapi.h>
-#include <wtsapi32.h>
-#include <iostream>
-
-#include "thresholds.h"
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
 
-#include "boost\program_options.hpp"
+#include "plugins/thresholds.hpp"
+#include <boost/program_options.hpp>
+#include <iostream>
+#include <windows.h>
+#include <shlwapi.h>
+#include <wtsapi32.h>
 
 #define VERSION 1.0
 
 namespace po = boost::program_options;
 
-using std::endl; using std::wcout;
-using std::cout; using std::wstring;
-
-struct printInfoStruct 
+struct printInfoStruct
 {
-       threshold warn, crit;
-       int users;
+       threshold warn;
+       threshold crit;
+       DOUBLE users;
 };
 
-static int parseArguments(int, wchar_t **, po::variables_map&, printInfoStruct&);
-static int printOutput(printInfoStruct&);
-static int check_users(printInfoStruct&);
+static bool l_Debug;
 
-int wmain(int argc, wchar_t **argv) 
+static int parseArguments(int ac, WCHAR **av, po::variables_map& vm, printInfoStruct& printInfo)
 {
-       printInfoStruct printInfo = { };
-       po::variables_map vm;
-
-       int ret = parseArguments(argc, argv, vm, printInfo);
-       if (ret != -1)
-               return ret;
-
-       ret = check_users(printInfo);
-       if (ret != -1)
-               return ret;
-
-       return printOutput(printInfo);
-}
-
-int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo) 
-{
-       wchar_t namePath[MAX_PATH];
+       WCHAR namePath[MAX_PATH];
        GetModuleFileName(NULL, namePath, MAX_PATH);
-       wchar_t *progName = PathFindFileName(namePath);
+       WCHAR *progName = PathFindFileName(namePath);
 
        po::options_description desc;
 
        desc.add_options()
-               (",h", "print help message and exit")
-               ("help", "print verbose help and exit")
-               ("version,v", "print version and exit")
-               ("warning,w", po::wvalue<wstring>(), "warning threshold")
-               ("critical,c", po::wvalue<wstring>(), "critical threshold")
+               ("help,h", "Print help message and exit")
+               ("version,V", "Print version and exit")
+               ("debug,d", "Verbose/Debug output")
+               ("warning,w", po::wvalue<std::wstring>(), "Warning threshold")
+               ("critical,c", po::wvalue<std::wstring>(), "Critical threshold")
                ;
 
-       po::basic_command_line_parser<wchar_t> parser(ac, av);
+       po::wcommand_line_parser parser(ac, av);
 
        try {
                po::store(
                        parser
                        .options(desc)
                        .style(
-                       po::command_line_style::unix_style |
-                       po::command_line_style::allow_long_disguise)
+                               po::command_line_style::unix_style |
+                               po::command_line_style::allow_long_disguise)
                        .run(),
                        vm);
                vm.notify();
-       } catch (std::exception& e) {
-               cout << e.what() << endl << desc << endl;
+       } catch (const std::exception& e) {
+               std::cout << e.what() << '\n' << desc << '\n';
                return 3;
        }
 
-       if (vm.count("h")) {
-               cout << desc << endl;
-               return 0;
-       }
-    
        if (vm.count("help")) {
-               wcout << progName << " Help\n\tVersion: " << VERSION << endl;
+               std::wcout << progName << " Help\n\tVersion: " << VERSION << '\n';
                wprintf(
                        L"%s is a simple program to check a machines logged in users.\n"
                        L"You can use the following options to define its behaviour:\n\n", progName);
-               cout << desc;
+               std::cout << desc;
                wprintf(
                        L"\nIt will then output a string looking something like this:\n\n"
-                       L"\tUSERS WARNING 48|users=48;10;50;0\n\n"
+                       L"\tUSERS WARNING 48 | users=48;10;50;0\n\n"
                        L"\"USERS\" being the type of the check, \"WARNING\" the returned status\n"
                        L"and \"48\" is the returned value.\n"
                        L"The performance data is found behind the \"|\", in order:\n"
@@ -133,35 +90,40 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
                        L"to end with a percentage sign.\n\n"
                        L"All of these options work with the critical threshold \"-c\" too."
                        , progName);
-               cout << endl;
+               std::cout << '\n';
                return 0;
        }
 
        if (vm.count("version"))
-               wcout << L"Version: " << VERSION << endl;
+               std::wcout << L"Version: " << VERSION << '\n';
 
        if (vm.count("warning")) {
                try {
-                       printInfo.warn = parse(vm["warning"].as<wstring>());
-               } catch (std::invalid_argument& e) {
-                       cout << e.what() << endl;
+                       printInfo.warn = threshold(vm["warning"].as<std::wstring>());
+               } catch (const std::invalid_argument& e) {
+                       std::cout << e.what() << '\n';
                        return 3;
                }
        }
        if (vm.count("critical")) {
                try {
-                       printInfo.crit = parse(vm["critical"].as<wstring>());
-               } catch (std::invalid_argument& e) {
-                       cout << e.what() << endl;
+                       printInfo.crit = threshold(vm["critical"].as<std::wstring>());
+               } catch (const std::invalid_argument& e) {
+                       std::cout << e.what() << '\n';
                        return 3;
                }
        }
 
+       l_Debug = vm.count("debug") > 0;
+
        return -1;
 }
 
-int printOutput(printInfoStruct& printInfo) 
+static int printOutput(printInfoStruct& printInfo)
 {
+       if (l_Debug)
+               std::wcout << L"Constructing output string" << '\n';
+
        state state = OK;
 
        if (printInfo.warn.rend(printInfo.users))
@@ -172,43 +134,58 @@ int printOutput(printInfoStruct& printInfo)
 
        switch (state) {
        case OK:
-               wcout << L"USERS OK " << printInfo.users << L"User|users=" << printInfo.users << L";" 
-                       << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0" << endl;
+               std::wcout << L"USERS OK " << printInfo.users << L" User(s) logged in | 'users'=" << printInfo.users << L";"
+                       << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << '\n';
                break;
        case WARNING:
-               wcout << L"USERS WARNING " << printInfo.users << L"User|users=" << printInfo.users << L";"
-                       << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0" << endl;
+               std::wcout << L"USERS WARNING " << printInfo.users << L" User(s) logged in | 'users'=" << printInfo.users << L";"
+                       << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << '\n';
                break;
        case CRITICAL:
-               wcout << L"USERS CRITICAL " << printInfo.users << L"User|users=" << printInfo.users << L";"
-                       << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0" << endl;
+               std::wcout << L"USERS CRITICAL " << printInfo.users << L" User(s) logged in | 'users'=" << printInfo.users << L";"
+                       << printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << '\n';
                break;
        }
 
        return state;
 }
 
-int check_users(printInfoStruct& printInfo) 
+static int check_users(printInfoStruct& printInfo)
 {
-       int users = 0;
-       WTS_SESSION_INFOW *pSessionInfo;
+       DOUBLE users = 0;
+       WTS_SESSION_INFOW *pSessionInfo = NULL;
        DWORD count;
        DWORD index;
 
+       if (l_Debug)
+               std::wcout << L"Trying to enumerate terminal sessions" << '\n';
+
        if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &count)) {
-               wcout << L"Failed to enumerate terminal sessions" << endl;
+               std::wcout << L"Failed to enumerate terminal sessions" << '\n';
+               printErrorInfo();
+               if (pSessionInfo)
+                       WTSFreeMemory(pSessionInfo);
                return 3;
        }
 
+       if (l_Debug)
+               std::wcout << L"Got all sessions (" << count << L"), traversing and counting active ones" << '\n';
+
        for (index = 0; index < count; index++) {
                LPWSTR name;
                DWORD size;
                int len;
 
+               if (l_Debug)
+                       std::wcout << L"Querrying session number " << index << '\n';
+
                if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, pSessionInfo[index].SessionId,
                        WTSUserName, &name, &size))
                        continue;
 
+               if (l_Debug)
+                       std::wcout << L"Found \"" << name << L"\". Checking whether it's a real session" << '\n';
+
                len = lstrlenW(name);
 
                WTSFreeMemory(name);
@@ -216,12 +193,33 @@ int check_users(printInfoStruct& printInfo)
                if (!len)
                        continue;
 
-               if (pSessionInfo[index].State == WTSActive || pSessionInfo[index].State == WTSDisconnected)
+               if (pSessionInfo[index].State == WTSActive || pSessionInfo[index].State == WTSDisconnected) {
                        users++;
+                       if (l_Debug)
+                               std::wcout << L"\"" << name << L"\" is a real session, counting it. Now " << users << '\n';
+               }
        }
 
+       if (l_Debug)
+               std::wcout << "Finished coutning user sessions (" << users << "). Freeing memory and returning" << '\n';
+
        WTSFreeMemory(pSessionInfo);
        printInfo.users = users;
        return -1;
+}
 
-}
\ No newline at end of file
+int wmain(int argc, WCHAR **argv)
+{
+       printInfoStruct printInfo = { };
+       po::variables_map vm;
+
+       int ret = parseArguments(argc, argv, vm, printInfo);
+       if (ret != -1)
+               return ret;
+
+       ret = check_users(printInfo);
+       if (ret != -1)
+               return ret;
+
+       return printOutput(printInfo);
+}