-/******************************************************************************
- * 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"
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))
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);
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);
+}