/******************************************************************************
* Icinga 2 *
- * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://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 *
#include <Shlwapi.h>
#include <iostream>
-#include "thresholds.h"
+#include "check_service.h"
-#include "boost/program_options.hpp"
-#define VERSION 1.0
+#define VERSION 1.1
namespace po = boost::program_options;
-using std::wcout; using std::endl;
-using std::cout; using std::wstring;
+static BOOL debug;
-struct printInfoStruct
-{
- bool warn;
- int ServiceState;
- wstring service;
-};
-
-static int parseArguments(int, wchar_t **, po::variables_map&, printInfoStruct&);
-static int printOutput(const printInfoStruct&);
-static int ServiceStatus(const printInfoStruct&);
-
-int wmain(int argc, wchar_t **argv)
+INT wmain(INT argc, WCHAR **argv)
{
po::variables_map vm;
printInfoStruct printInfo = { false, 0, L"" };
- int ret = parseArguments(argc, argv, vm, printInfo);
+ INT ret = parseArguments(argc, argv, vm, printInfo);
if (ret != -1)
return ret;
return printOutput(printInfo);
}
-int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo)
+INT parseArguments(INT ac, WCHAR **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")
- ("service,s", po::wvalue<wstring>(), "service to check (required)")
- ("warn,w", "return warning (1) instead of critical (2),\n when service is not running")
+ ("help,h", "Print help message and exit")
+ ("version,V", "Print version and exit")
+ ("debug,d", "Verbose/Debug output")
+ ("service,s", po::wvalue<std::wstring>(), "Service to check (required)")
+ ("warn,w", "Return warning (1) instead of critical (2),\n when service is not running")
;
- po::basic_command_line_parser<wchar_t> parser(ac, av);
+ po::basic_command_line_parser<WCHAR> parser(ac, av);
try {
po::store(
vm);
vm.notify();
} catch (std::exception& e) {
- cout << e.what() << endl << desc << endl;
+ 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 the status of a service.\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"\tSERVICE CRITICAL NOT_RUNNING|service=4;!4;!4;1;7\n\n"
+ L"\tSERVICE CRITICAL NOT_RUNNING | service=4;!4;!4;1;7\n\n"
L"\"SERVICE\" being the type of the check, \"CRITICAL\" the returned status\n"
L"and \"1\" is the returned value.\n"
L"A service is either running (Code 0x04) or not running (any other).\n"
L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
L"%s' thresholds work differently, since a service is either running or not\n"
L"all \"-w\" and \"-c\" do is say whether a not running service is a warning\n"
- L"or critical state respectively.\n"
+ L"or critical state respectively.\n\n"
, progName, progName);
- cout << endl;
+ std::cout << '\n';
return 0;
}
-
+
if (vm.count("version")) {
- cout << "Version: " << VERSION << endl;
+ std::cout << "Version: " << VERSION << '\n';
return 0;
}
-
- if (!vm.count("service")) {
- cout << "Missing argument: service" << endl << desc << endl;
+
+ if (!vm.count("service")) {
+ std::cout << "Missing argument: service" << '\n' << desc << '\n';
return 3;
}
if (vm.count("warn"))
printInfo.warn = true;
- printInfo.service = vm["service"].as<wstring>();
+ printInfo.service = vm["service"].as<std::wstring>();
+
+ if (vm.count("debug"))
+ debug = TRUE;
return -1;
}
-int printOutput(const printInfoStruct& printInfo)
+INT printOutput(CONST printInfoStruct& printInfo)
{
- wstring perf;
+ if (debug)
+ std::wcout << L"Constructing output string" << '\n';
+
+ std::wstring perf;
state state = OK;
+ if (!printInfo.ServiceState) {
+ std::wcout << L"SERVICE CRITICAL NOTFOUND | service=" << printInfo.ServiceState << ";;;1;7" << '\n';
+ return 3;
+ }
+
if (printInfo.ServiceState != 0x04)
printInfo.warn ? state = WARNING : state = CRITICAL;
switch (state) {
case OK:
- wcout << L"SERVICE OK RUNNING|service=4;!4;!4;1;7" << endl;
+ std::wcout << L"SERVICE OK RUNNING | service=4;;;1;7" << '\n';
break;
case WARNING:
- wcout << L"SERVICE WARNING NOT_RUNNING|service=" << printInfo.ServiceState << ";!4;!4;1;7" << endl;
+ std::wcout << L"SERVICE WARNING NOT RUNNING | service=" << printInfo.ServiceState << ";;;1;7" << '\n';
break;
case CRITICAL:
- wcout << L"SERVICE CRITICAL NOT_RUNNING|service=" << printInfo.ServiceState << ";!4;!4;1;7" << endl;
+ std::wcout << L"SERVICE CRITICAL NOT RUNNING | service=" << printInfo.ServiceState << ";;;1;7" << '\n';
break;
}
-
+
return state;
}
-int ServiceStatus(const printInfoStruct& printInfo)
+DWORD ServiceStatus(CONST printInfoStruct& printInfo)
{
- SC_HANDLE service_api = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
- if (service_api == NULL)
- goto die;
+ SC_HANDLE hSCM;
+ SC_HANDLE hService;
+ DWORD cbBufSize;
+ LPBYTE lpBuf = NULL;
- LPBYTE lpServices = NULL;
- DWORD cbBufSize = 0;
- DWORD *pcbBytesNeeded = NULL, *lpServicesReturned = NULL, *lpResumeHandle = NULL;
+ if (debug)
+ std::wcout << L"Opening SC Manager" << '\n';
- if (!EnumServicesStatusEx(service_api, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL,
- lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle, NULL)
- && GetLastError() != ERROR_MORE_DATA)
+ hSCM = OpenSCManager(NULL, NULL, GENERIC_READ);
+ if (hSCM == NULL)
goto die;
- lpServices = new BYTE[*pcbBytesNeeded];
- cbBufSize = *pcbBytesNeeded;
+ if (debug)
+ std::wcout << L"Getting Service Information" << '\n';
- if (!EnumServicesStatusEx(service_api, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL,
- lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle, NULL))
+ hService = OpenService(hSCM, printInfo.service.c_str(), SERVICE_QUERY_STATUS);
+ if (hService == NULL)
+ goto die;
+
+ QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, NULL, 0, &cbBufSize);
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto die;
- LPENUM_SERVICE_STATUS_PROCESS pInfo = (LPENUM_SERVICE_STATUS_PROCESS)lpServices;
-
- for (DWORD i = 0; i< *lpServicesReturned; i++) {
- if (!wcscmp(printInfo.service.c_str(), pInfo[i].lpServiceName)) {
- delete lpServices;
- return pInfo[i].ServiceStatusProcess.dwCurrentState;
- }
+ lpBuf = new BYTE[cbBufSize];
+ if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, lpBuf, cbBufSize, &cbBufSize)) {
+ LPSERVICE_STATUS_PROCESS pInfo = (LPSERVICE_STATUS_PROCESS)lpBuf;
+ return pInfo->dwCurrentState;
}
+
die:
- if (lpServices)
- delete lpServices;
- wcout << L"Service " << printInfo.service << L" could not be found" << endl;
+ die();
+ if (hSCM)
+ CloseServiceHandle(hSCM);
+ if (hService)
+ CloseServiceHandle(hService);
+ delete [] lpBuf;
+
return -1;
}