summaryrefslogtreecommitdiffstats
path: root/plugins/check_users.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_users.c')
-rw-r--r--plugins/check_users.c268
1 files changed, 142 insertions, 126 deletions
diff --git a/plugins/check_users.c b/plugins/check_users.c
index f1e1c39d..3b2e265e 100644
--- a/plugins/check_users.c
+++ b/plugins/check_users.c
@@ -34,8 +34,15 @@ const char *progname = "check_users";
34const char *copyright = "2000-2024"; 34const char *copyright = "2000-2024";
35const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
36 36
37#include "common.h" 37#include "check_users.d/users.h"
38#include "utils.h" 38#include "output.h"
39#include "perfdata.h"
40#include "states.h"
41#include "utils_base.h"
42#include "./common.h"
43#include "./utils.h"
44#include "check_users.d/config.h"
45#include "thresholds.h"
39 46
40#if HAVE_WTSAPI32_H 47#if HAVE_WTSAPI32_H
41# include <windows.h> 48# include <windows.h>
@@ -44,8 +51,6 @@ const char *email = "devel@monitoring-plugins.org";
44# define ERROR -1 51# define ERROR -1
45#elif HAVE_UTMPX_H 52#elif HAVE_UTMPX_H
46# include <utmpx.h> 53# include <utmpx.h>
47#else
48# include "popen.h"
49#endif 54#endif
50 55
51#ifdef HAVE_LIBSYSTEMD 56#ifdef HAVE_LIBSYSTEMD
@@ -53,29 +58,16 @@ const char *email = "devel@monitoring-plugins.org";
53# include <systemd/sd-login.h> 58# include <systemd/sd-login.h>
54#endif 59#endif
55 60
56#define possibly_set(a, b) ((a) == 0 ? (b) : 0) 61typedef struct process_argument_wrapper {
62 int errorcode;
63 check_users_config config;
64} check_users_config_wrapper;
65check_users_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
57 66
58static int process_arguments(int, char **); 67void print_help(void);
59static void print_help(void);
60void print_usage(void); 68void print_usage(void);
61 69
62static char *warning_range = NULL;
63static char *critical_range = NULL;
64static thresholds *thlds = NULL;
65
66int main(int argc, char **argv) { 70int main(int argc, char **argv) {
67 int users = -1;
68 int result = STATE_UNKNOWN;
69#if HAVE_WTSAPI32_H
70 WTS_SESSION_INFO *wtsinfo;
71 DWORD wtscount;
72 DWORD index;
73#elif HAVE_UTMPX_H
74 struct utmpx *putmpx;
75#else
76 char input_buffer[MAX_INPUT_BUFFER];
77#endif
78
79 setlocale(LC_ALL, ""); 71 setlocale(LC_ALL, "");
80 bindtextdomain(PACKAGE, LOCALEDIR); 72 bindtextdomain(PACKAGE, LOCALEDIR);
81 textdomain(PACKAGE); 73 textdomain(PACKAGE);
@@ -83,121 +75,104 @@ int main(int argc, char **argv) {
83 /* Parse extra opts if any */ 75 /* Parse extra opts if any */
84 argv = np_extra_opts(&argc, argv, progname); 76 argv = np_extra_opts(&argc, argv, progname);
85 77
86 if (process_arguments(argc, argv) == ERROR) 78 check_users_config_wrapper tmp_config = process_arguments(argc, argv);
87 usage4(_("Could not parse arguments"));
88
89 users = 0;
90
91#ifdef HAVE_LIBSYSTEMD
92 if (sd_booted() > 0)
93 users = sd_get_sessions(NULL);
94 else {
95#endif
96#if HAVE_WTSAPI32_H
97 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &wtsinfo, &wtscount)) {
98 printf(_("Could not enumerate RD sessions: %d\n"), GetLastError());
99 return STATE_UNKNOWN;
100 }
101
102 for (index = 0; index < wtscount; index++) {
103 LPTSTR username;
104 DWORD size;
105 int len;
106
107 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wtsinfo[index].SessionId, WTSUserName, &username, &size))
108 continue;
109
110 len = lstrlen(username);
111
112 WTSFreeMemory(username);
113
114 if (len == 0)
115 continue;
116
117 if (wtsinfo[index].State == WTSActive || wtsinfo[index].State == WTSDisconnected)
118 users++;
119 }
120
121 WTSFreeMemory(wtsinfo);
122#elif HAVE_UTMPX_H
123 /* get currently logged users from utmpx */
124 setutxent();
125
126 while ((putmpx = getutxent()) != NULL)
127 if (putmpx->ut_type == USER_PROCESS)
128 users++;
129 79
130 endutxent(); 80 if (tmp_config.errorcode == ERROR) {
131#else 81 usage4(_("Could not parse arguments"));
132 /* run the command */
133 child_process = spopen(WHO_COMMAND);
134 if (child_process == NULL) {
135 printf(_("Could not open pipe: %s\n"), WHO_COMMAND);
136 return STATE_UNKNOWN;
137 } 82 }
138 83
139 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r"); 84 check_users_config config = tmp_config.config;
140 if (child_stderr == NULL)
141 printf(_("Could not open stderr for %s\n"), WHO_COMMAND);
142
143 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
144 /* increment 'users' on all lines except total user count */
145 if (input_buffer[0] != '#') {
146 users++;
147 continue;
148 }
149 85
150 /* get total logged in users */ 86#ifdef _WIN32
151 if (sscanf(input_buffer, _("# users=%d"), &users) == 1) 87# if HAVE_WTSAPI32_H
152 break; 88 get_num_of_users_wrapper user_wrapper = get_num_of_users_windows();
89# else
90# error Did not find WTSAPI32
91# endif // HAVE_WTSAPI32_H
92#else
93# ifdef HAVE_LIBSYSTEMD
94 get_num_of_users_wrapper user_wrapper = get_num_of_users_systemd();
95# elif HAVE_UTMPX_H
96 get_num_of_users_wrapper user_wrapper = get_num_of_users_utmp();
97# else // !HAVE_LIBSYSTEMD && !HAVE_UTMPX_H
98 get_num_of_users_wrapper user_wrapper = get_num_of_users_who_command();
99# endif // HAVE_LIBSYSTEMD
100#endif // _WIN32
101
102 mp_check overall = mp_check_init();
103 if (config.output_format_is_set) {
104 mp_set_format(config.output_format);
153 } 105 }
106 mp_subcheck sc_users = mp_subcheck_init();
154 107
155 /* check STDERR */ 108 if (user_wrapper.errorcode != 0) {
156 if (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) 109 sc_users = mp_set_subcheck_state(sc_users, STATE_UNKNOWN);
157 result = possibly_set(result, STATE_UNKNOWN); 110 sc_users.output = "Failed to retrieve number of users";
158 (void)fclose(child_stderr); 111 mp_add_subcheck_to_check(&overall, sc_users);
159 112 mp_exit(overall);
160 /* close the pipe */
161 if (spclose(child_process))
162 result = possibly_set(result, STATE_UNKNOWN);
163#endif
164#ifdef HAVE_LIBSYSTEMD
165 } 113 }
166#endif
167
168 /* check the user count against warning and critical thresholds */ 114 /* check the user count against warning and critical thresholds */
169 result = get_status((double)users, thlds);
170 115
171 if (result == STATE_UNKNOWN) 116 mp_perfdata users_pd = {
172 printf("%s\n", _("Unable to read output")); 117 .label = "users",
173 else { 118 .value = mp_create_pd_value(user_wrapper.users),
174 printf(_("USERS %s - %d users currently logged in |%s\n"), state_text(result), users, 119 };
175 sperfdata_int("users", users, "", warning_range, critical_range, true, 0, false, 0)); 120
121 users_pd = mp_pd_set_thresholds(users_pd, config.thresholds);
122 mp_add_perfdata_to_subcheck(&sc_users, users_pd);
123
124 int tmp_status = mp_get_pd_status(users_pd);
125 sc_users = mp_set_subcheck_state(sc_users, tmp_status);
126
127 switch (tmp_status) {
128 case STATE_WARNING:
129 xasprintf(&sc_users.output,
130 "%d users currently logged in. This violates the warning threshold",
131 user_wrapper.users);
132 break;
133 case STATE_CRITICAL:
134 xasprintf(&sc_users.output,
135 "%d users currently logged in. This violates the critical threshold",
136 user_wrapper.users);
137 break;
138 default:
139 xasprintf(&sc_users.output, "%d users currently logged in", user_wrapper.users);
176 } 140 }
177 141
178 return result; 142 mp_add_subcheck_to_check(&overall, sc_users);
143 mp_exit(overall);
179} 144}
180 145
146#define output_format_index CHAR_MAX + 1
147
181/* process command-line arguments */ 148/* process command-line arguments */
182int process_arguments(int argc, char **argv) { 149check_users_config_wrapper process_arguments(int argc, char **argv) {
183 static struct option longopts[] = {{"critical", required_argument, 0, 'c'}, 150 static struct option longopts[] = {{"critical", required_argument, 0, 'c'},
184 {"warning", required_argument, 0, 'w'}, 151 {"warning", required_argument, 0, 'w'},
185 {"version", no_argument, 0, 'V'}, 152 {"version", no_argument, 0, 'V'},
186 {"help", no_argument, 0, 'h'}, 153 {"help", no_argument, 0, 'h'},
154 {"output-format", required_argument, 0, output_format_index},
187 {0, 0, 0, 0}}; 155 {0, 0, 0, 0}};
188 156
189 if (argc < 2) 157 if (argc < 2) {
190 usage("\n"); 158 usage(progname);
159 }
160
161 char *warning_range = NULL;
162 char *critical_range = NULL;
163 check_users_config_wrapper result = {
164 .config = check_users_config_init(),
165 .errorcode = OK,
166 };
191 167
192 int option_char;
193 while (true) { 168 while (true) {
194 int option = 0; 169 int counter = getopt_long(argc, argv, "+hVvc:w:", longopts, NULL);
195 option_char = getopt_long(argc, argv, "+hVvc:w:", longopts, &option);
196 170
197 if (option_char == -1 || option_char == EOF || option_char == 1) 171 if (counter == -1 || counter == EOF || counter == 1) {
198 break; 172 break;
173 }
199 174
200 switch (option_char) { 175 switch (counter) {
201 case '?': /* print short usage statement if args not parsable */ 176 case '?': /* print short usage statement if args not parsable */
202 usage5(); 177 usage5();
203 case 'h': /* help */ 178 case 'h': /* help */
@@ -212,29 +187,66 @@ int process_arguments(int argc, char **argv) {
212 case 'w': /* warning */ 187 case 'w': /* warning */
213 warning_range = optarg; 188 warning_range = optarg;
214 break; 189 break;
190 case output_format_index: {
191 parsed_output_format parser = mp_parse_output_format(optarg);
192 if (!parser.parsing_success) {
193 // TODO List all available formats here, maybe add anothoer usage function
194 printf("Invalid output format: %s\n", optarg);
195 exit(STATE_UNKNOWN);
196 }
197
198 result.config.output_format_is_set = true;
199 result.config.output_format = parser.output_format;
200 break;
201 }
215 } 202 }
216 } 203 }
217 204
218 option_char = optind; 205 int option_char = optind;
219 206
220 if (warning_range == NULL && argc > option_char) 207 if (warning_range == NULL && argc > option_char) {
221 warning_range = argv[option_char++]; 208 warning_range = argv[option_char++];
209 }
222 210
223 if (critical_range == NULL && argc > option_char) 211 if (critical_range == NULL && argc > option_char) {
224 critical_range = argv[option_char++]; 212 critical_range = argv[option_char++];
213 }
214
215 // TODO add proper verification for ranges here!
216 mp_range_parsed tmp;
217 if (warning_range) {
218 tmp = mp_parse_range_string(warning_range);
219 } else {
220 printf("Warning threshold missing\n");
221 print_usage();
222 exit(STATE_UNKNOWN);
223 }
225 224
226 /* this will abort in case of invalid ranges */ 225 if (tmp.error == MP_PARSING_SUCCES) {
227 set_thresholds(&thlds, warning_range, critical_range); 226 result.config.thresholds.warning = tmp.range;
227 result.config.thresholds.warning_is_set = true;
228 } else {
229 printf("Failed to parse warning range: %s", warning_range);
230 exit(STATE_UNKNOWN);
231 }
228 232
229 if (!thlds->warning) { 233 if (critical_range) {
230 usage4(_("Warning threshold must be a valid range expression")); 234 tmp = mp_parse_range_string(critical_range);
235 } else {
236 printf("Critical threshold missing\n");
237 print_usage();
238 exit(STATE_UNKNOWN);
231 } 239 }
232 240
233 if (!thlds->critical) { 241 if (tmp.error == MP_PARSING_SUCCES) {
234 usage4(_("Critical threshold must be a valid range expression")); 242 result.config.thresholds.critical = tmp.range;
243 result.config.thresholds.critical_is_set = true;
244 } else {
245 printf("Failed to parse critical range: %s", critical_range);
246 exit(STATE_UNKNOWN);
235 } 247 }
236 248
237 return OK; 249 return result;
238} 250}
239 251
240void print_help(void) { 252void print_help(void) {
@@ -244,7 +256,8 @@ void print_help(void) {
244 printf(COPYRIGHT, copyright, email); 256 printf(COPYRIGHT, copyright, email);
245 257
246 printf("%s\n", _("This plugin checks the number of users currently logged in on the local")); 258 printf("%s\n", _("This plugin checks the number of users currently logged in on the local"));
247 printf("%s\n", _("system and generates an error if the number exceeds the thresholds specified.")); 259 printf("%s\n",
260 _("system and generates an error if the number exceeds the thresholds specified."));
248 261
249 printf("\n\n"); 262 printf("\n\n");
250 263
@@ -254,9 +267,12 @@ void print_help(void) {
254 printf(UT_EXTRA_OPTS); 267 printf(UT_EXTRA_OPTS);
255 268
256 printf(" %s\n", "-w, --warning=RANGE_EXPRESSION"); 269 printf(" %s\n", "-w, --warning=RANGE_EXPRESSION");
257 printf(" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION")); 270 printf(" %s\n",
271 _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION"));
258 printf(" %s\n", "-c, --critical=RANGE_EXPRESSION"); 272 printf(" %s\n", "-c, --critical=RANGE_EXPRESSION");
259 printf(" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION")); 273 printf(" %s\n",
274 _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION"));
275 printf(UT_OUTPUT_FORMAT);
260 276
261 printf(UT_SUPPORT); 277 printf(UT_SUPPORT);
262} 278}