]> granicus.if.org Git - icinga2/blob - plugins/check_service.cpp
Update Window plugins' usage strings
[icinga2] / plugins / check_service.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
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 #include <Windows.h>
20 #include <Shlwapi.h>
21 #include <iostream>
22
23 #include "thresholds.h"
24
25 #include "boost/program_options.hpp"
26
27 #define VERSION 1.1
28
29 namespace po = boost::program_options;
30
31 using std::wcout; using std::endl;
32 using std::cout; using std::wstring;
33
34 static BOOL debug;
35
36 struct printInfoStruct 
37 {
38         bool warn;
39         DWORD ServiceState;
40         wstring service;
41 };
42
43 static int parseArguments(int, wchar_t **, po::variables_map&, printInfoStruct&);
44 static int printOutput(const printInfoStruct&);
45 static DWORD ServiceStatus(const printInfoStruct&);
46
47 int wmain(int argc, wchar_t **argv)
48 {
49         po::variables_map vm;
50         printInfoStruct printInfo = { false, 0, L"" };
51
52         int ret = parseArguments(argc, argv, vm, printInfo);
53         if (ret != -1)
54                 return ret;
55
56         printInfo.ServiceState = ServiceStatus(printInfo);
57         if (printInfo.ServiceState == -1)
58                 return 3;
59
60         return printOutput(printInfo);
61 }
62
63 int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo) 
64 {
65         wchar_t namePath[MAX_PATH];
66         GetModuleFileName(NULL, namePath, MAX_PATH);
67         wchar_t *progName = PathFindFileName(namePath);
68
69         po::options_description desc;
70
71         desc.add_options()
72                 ("help,h", "print help message and exit")
73                 ("version,V", "print version and exit")
74                 ("debug,d", "Verbose/Debug output")
75                 ("service,s", po::wvalue<wstring>(), "service to check (required)")
76                 ("warn,w", "return warning (1) instead of critical (2),\n when service is not running")
77                 ;
78
79         po::basic_command_line_parser<wchar_t> parser(ac, av);
80
81         try {
82                 po::store(
83                         parser
84                         .options(desc)
85                         .style(
86                         po::command_line_style::unix_style |
87                         po::command_line_style::allow_long_disguise)
88                         .run(),
89                         vm);
90                 vm.notify();
91         } catch (std::exception& e) {
92                 cout << e.what() << endl << desc << endl;
93                 return 3;
94         }
95
96         if (vm.count("help")) {
97                 wcout << progName << " Help\n\tVersion: " << VERSION << endl;
98                 wprintf(
99                         L"%s is a simple program to check the status of a service.\n"
100                         L"You can use the following options to define its behaviour:\n\n", progName);
101                 cout << desc;
102                 wprintf(
103                         L"\nIt will then output a string looking something like this:\n\n"
104                         L"\tSERVICE CRITICAL NOT_RUNNING | service=4;!4;!4;1;7\n\n"
105                         L"\"SERVICE\" being the type of the check, \"CRITICAL\" the returned status\n"
106                         L"and \"1\" is the returned value.\n"
107                         L"A service is either running (Code 0x04) or not running (any other).\n"
108                         L"For more information consult the msdn on service state transitions.\n\n"
109                         L"%s' exit codes denote the following:\n"
110                         L" 0\tOK,\n\tNo Thresholds were broken or the programs check part was not executed\n"
111                         L" 1\tWARNING,\n\tThe warning, but not the critical threshold was broken\n"
112                         L" 2\tCRITICAL,\n\tThe critical threshold was broken\n"
113                         L" 3\tUNKNOWN, \n\tThe program experienced an internal or input error\n\n"
114                         L"%s' thresholds work differently, since a service is either running or not\n"
115                         L"all \"-w\" and \"-c\" do is say whether a not running service is a warning\n"
116                         L"or critical state respectively.\n\n"
117                         , progName, progName);
118                 cout << endl;
119                 return 0;
120         }
121
122          if (vm.count("version")) {
123                 cout << "Version: " << VERSION << endl;
124                 return 0;
125         } 
126
127         if (!vm.count("service")) {
128                 cout << "Missing argument: service" << endl << desc << endl;
129                 return 3;
130         }
131
132         if (vm.count("warn"))
133                 printInfo.warn = true;
134         
135         printInfo.service = vm["service"].as<wstring>();
136
137         if (vm.count("debug"))
138                 debug = TRUE;
139         
140         return -1;
141 }
142
143 int printOutput(const printInfoStruct& printInfo) 
144 {
145         if (debug)
146                 wcout << L"Constructing output string" << endl;
147
148         wstring perf;
149         state state = OK;
150
151         if (!printInfo.ServiceState) {
152                 wcout << L"SERVICE CRITICAL NOTFOUND | service=" << printInfo.ServiceState << ";!4;!4;1;7" << endl;
153                 return 3;
154         }
155
156         if (printInfo.ServiceState != 0x04) 
157                 printInfo.warn ? state = WARNING : state = CRITICAL;
158
159         switch (state) {
160         case OK:
161                 wcout << L"SERVICE OK RUNNING | service=4;!4;!4;1;7" << endl;
162                 break;
163         case WARNING:
164                 wcout << L"SERVICE WARNING NOT RUNNING | service=" << printInfo.ServiceState << ";!4;!4;1;7" << endl;
165                 break;
166         case CRITICAL:
167                 wcout << L"SERVICE CRITICAL NOT RUNNING | service=" << printInfo.ServiceState << ";!4;!4;1;7" << endl;
168                 break;
169         }
170
171         return state;
172 }
173
174 DWORD ServiceStatus(const printInfoStruct& printInfo) 
175 {
176         SC_HANDLE hSCM;
177         SC_HANDLE hService;
178         DWORD cbBufSize;
179         LPBYTE lpBuf = NULL;
180
181         if (debug)
182                 wcout << L"Opening SC Manager" << endl;
183
184         hSCM = OpenSCManager(NULL, NULL, GENERIC_READ);
185         if (hSCM == NULL)
186                 goto die;
187
188         if (debug)
189                 wcout << L"Getting Service Information" << endl;
190
191         hService = OpenService(hSCM, printInfo.service.c_str(), SERVICE_QUERY_STATUS);
192         if (hService == NULL)
193                 goto die;
194         
195         QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, NULL, 0, &cbBufSize);
196         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
197                 goto die;
198
199         lpBuf = new BYTE[cbBufSize];
200         if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, lpBuf, cbBufSize, &cbBufSize)) {
201                 LPSERVICE_STATUS_PROCESS pInfo = (LPSERVICE_STATUS_PROCESS)lpBuf;
202                 return pInfo->dwCurrentState;
203         }
204
205
206 die:
207         die();
208         if (hSCM)
209                 CloseServiceHandle(hSCM);
210         if (hService)
211                 CloseServiceHandle(hService);
212         delete [] lpBuf;
213
214         return -1;
215 }