summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-02-25 15:02:55 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-03-07 23:38:50 +0100
commitd35c43e95f9efed3ef89bee288b8ec8f65ad2014 (patch)
tree0c2b22b8bf2dbf54347aa760fc88e0e1f25ebb1e
parent53247ae748174ddb639bb5fd9a19c8a6ad121717 (diff)
downloadmonitoring-plugins-d35c43e95f9efed3ef89bee288b8ec8f65ad2014.tar.gz
Revert "Migrate check_users to new ouput infrastructure"
This reverts commit 10086edbf03fd807794bcfb3fff626da69a9fdb2.
-rw-r--r--plugins/Makefile.am1
-rw-r--r--plugins/check_users.c249
-rw-r--r--plugins/check_users.d/config.h19
-rw-r--r--plugins/check_users.d/users.c166
-rw-r--r--plugins/check_users.d/users.h18
5 files changed, 130 insertions, 323 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index e0069653..d43c1971 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -125,7 +125,6 @@ check_time_LDADD = $(NETLIBS)
125check_ntp_time_LDADD = $(NETLIBS) $(MATHLIBS) 125check_ntp_time_LDADD = $(NETLIBS) $(MATHLIBS)
126check_ups_LDADD = $(NETLIBS) 126check_ups_LDADD = $(NETLIBS)
127check_users_LDADD = $(BASEOBJS) $(WTSAPI32LIBS) $(SYSTEMDLIBS) 127check_users_LDADD = $(BASEOBJS) $(WTSAPI32LIBS) $(SYSTEMDLIBS)
128check_users_SOURCES = check_users.c check_users.d/users.c
129check_by_ssh_LDADD = $(NETLIBS) 128check_by_ssh_LDADD = $(NETLIBS)
130check_ide_smart_LDADD = $(BASEOBJS) 129check_ide_smart_LDADD = $(BASEOBJS)
131negate_LDADD = $(BASEOBJS) 130negate_LDADD = $(BASEOBJS)
diff --git a/plugins/check_users.c b/plugins/check_users.c
index 6ec87d21..f1e1c39d 100644
--- a/plugins/check_users.c
+++ b/plugins/check_users.c
@@ -3,7 +3,7 @@
3 * Monitoring check_users plugin 3 * Monitoring check_users plugin
4 * 4 *
5 * License: GPL 5 * License: GPL
6 * Copyright (c) 2000-2025 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7 * 7 *
8 * Description: 8 * Description:
9 * 9 *
@@ -30,19 +30,12 @@
30 * 30 *
31 *****************************************************************************/ 31 *****************************************************************************/
32 32
33#include "check_users.d/config.h"
34#include "thresholds.h"
35const char *progname = "check_users"; 33const char *progname = "check_users";
36const char *copyright = "2000-2025"; 34const char *copyright = "2000-2024";
37const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
38 36
39#include "check_users.d/users.h" 37#include "common.h"
40#include "output.h" 38#include "utils.h"
41#include "perfdata.h"
42#include "states.h"
43#include "utils_base.h"
44#include "./common.h"
45#include "./utils.h"
46 39
47#if HAVE_WTSAPI32_H 40#if HAVE_WTSAPI32_H
48# include <windows.h> 41# include <windows.h>
@@ -60,16 +53,29 @@ const char *email = "devel@monitoring-plugins.org";
60# include <systemd/sd-login.h> 53# include <systemd/sd-login.h>
61#endif 54#endif
62 55
63typedef struct process_argument_wrapper { 56#define possibly_set(a, b) ((a) == 0 ? (b) : 0)
64 int errorcode;
65 check_users_config config;
66} process_argument_wrapper;
67 57
68process_argument_wrapper process_arguments(int /*argc*/, char ** /*argv*/); 58static int process_arguments(int, char **);
69void print_help(void); 59static void print_help(void);
70void print_usage(void); 60void print_usage(void);
71 61
62static char *warning_range = NULL;
63static char *critical_range = NULL;
64static thresholds *thlds = NULL;
65
72int main(int argc, char **argv) { 66int 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
73 setlocale(LC_ALL, ""); 79 setlocale(LC_ALL, "");
74 bindtextdomain(PACKAGE, LOCALEDIR); 80 bindtextdomain(PACKAGE, LOCALEDIR);
75 textdomain(PACKAGE); 81 textdomain(PACKAGE);
@@ -77,106 +83,121 @@ int main(int argc, char **argv) {
77 /* Parse extra opts if any */ 83 /* Parse extra opts if any */
78 argv = np_extra_opts(&argc, argv, progname); 84 argv = np_extra_opts(&argc, argv, progname);
79 85
80 process_argument_wrapper tmp = process_arguments(argc, argv); 86 if (process_arguments(argc, argv) == ERROR)
81
82 if (tmp.errorcode == ERROR) {
83 usage4(_("Could not parse arguments")); 87 usage4(_("Could not parse arguments"));
84 }
85 88
86 check_users_config config = tmp.config; 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;
87 106
88#ifdef _WIN32 107 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wtsinfo[index].SessionId, WTSUserName, &username, &size))
89# if HAVE_WTSAPI32_H 108 continue;
90 get_num_of_users_wrapper user_wrapper = get_num_of_users_windows(); 109
91# else 110 len = lstrlen(username);
92# error Did not find WTSAPI32 111
93# endif // HAVE_WTSAPI32_H 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
130 endutxent();
94#else 131#else
95# ifdef HAVE_LIBSYSTEMD 132 /* run the command */
96 get_num_of_users_wrapper user_wrapper = get_num_of_users_systemd(); 133 child_process = spopen(WHO_COMMAND);
97# elif HAVE_UTMPX_H 134 if (child_process == NULL) {
98 get_num_of_users_wrapper user_wrapper = get_num_of_users_utmp(); 135 printf(_("Could not open pipe: %s\n"), WHO_COMMAND);
99# else // !HAVE_LIBSYSTEMD && !HAVE_UTMPX_H 136 return STATE_UNKNOWN;
100 get_num_of_users_wrapper user_wrapper = get_num_of_users_who_command();
101# endif // HAVE_LIBSYSTEMD
102#endif // _WIN32
103
104 mp_check overall = mp_check_init();
105 mp_subcheck sc_users = mp_subcheck_init();
106
107 if (user_wrapper.errorcode != 0) {
108 sc_users = mp_set_subcheck_state(sc_users, STATE_UNKNOWN);
109 sc_users.output = "Failed to retrieve number of users";
110 mp_add_subcheck_to_check(&overall, sc_users);
111 mp_exit(overall);
112 } 137 }
138
139 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
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
150 /* get total logged in users */
151 if (sscanf(input_buffer, _("# users=%d"), &users) == 1)
152 break;
153 }
154
155 /* check STDERR */
156 if (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
157 result = possibly_set(result, STATE_UNKNOWN);
158 (void)fclose(child_stderr);
159
160 /* close the pipe */
161 if (spclose(child_process))
162 result = possibly_set(result, STATE_UNKNOWN);
163#endif
164#ifdef HAVE_LIBSYSTEMD
165 }
166#endif
167
113 /* check the user count against warning and critical thresholds */ 168 /* check the user count against warning and critical thresholds */
169 result = get_status((double)users, thlds);
114 170
115 mp_perfdata users_pd = { 171 if (result == STATE_UNKNOWN)
116 .label = "users", 172 printf("%s\n", _("Unable to read output"));
117 .value = mp_create_pd_value(user_wrapper.users), 173 else {
118 }; 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 users_pd = mp_pd_set_thresholds(users_pd, config.thresholds);
121 mp_add_perfdata_to_subcheck(&sc_users, users_pd);
122
123 int tmp_status = mp_get_pd_status(users_pd);
124 sc_users = mp_set_subcheck_state(sc_users, tmp_status);
125
126 switch (tmp_status) {
127 case STATE_WARNING:
128 xasprintf(&sc_users.output, "%d users currently logged in. This violates the warning threshold", user_wrapper.users);
129 break;
130 case STATE_CRITICAL:
131 xasprintf(&sc_users.output, "%d users currently logged in. This violates the critical threshold", user_wrapper.users);
132 break;
133 default:
134 xasprintf(&sc_users.output, "%d users currently logged in", user_wrapper.users);
135 } 176 }
136 177
137 mp_add_subcheck_to_check(&overall, sc_users); 178 return result;
138 mp_exit(overall);
139} 179}
140 180
141#define output_format_index CHAR_MAX + 1
142
143/* process command-line arguments */ 181/* process command-line arguments */
144process_argument_wrapper process_arguments(int argc, char **argv) { 182int process_arguments(int argc, char **argv) {
145 static struct option longopts[] = {{"critical", required_argument, 0, 'c'}, 183 static struct option longopts[] = {{"critical", required_argument, 0, 'c'},
146 {"warning", required_argument, 0, 'w'}, 184 {"warning", required_argument, 0, 'w'},
147 {"version", no_argument, 0, 'V'}, 185 {"version", no_argument, 0, 'V'},
148 {"help", no_argument, 0, 'h'}, 186 {"help", no_argument, 0, 'h'},
149 {"output-format", required_argument, 0, output_format_index},
150 {0, 0, 0, 0}}; 187 {0, 0, 0, 0}};
151 188
152 if (argc < 2) { 189 if (argc < 2)
153 usage("\n"); 190 usage("\n");
154 }
155
156 char *warning_range = NULL;
157 char *critical_range = NULL;
158 check_users_config config = check_users_config_init();
159 191
192 int option_char;
160 while (true) { 193 while (true) {
161 int counter = getopt_long(argc, argv, "+hVvc:w:", longopts, NULL); 194 int option = 0;
195 option_char = getopt_long(argc, argv, "+hVvc:w:", longopts, &option);
162 196
163 if (counter == -1 || counter == EOF || counter == 1) { 197 if (option_char == -1 || option_char == EOF || option_char == 1)
164 break; 198 break;
165 }
166 199
167 switch (counter) { 200 switch (option_char) {
168 case output_format_index: {
169 parsed_output_format parser = mp_parse_output_format(optarg);
170 if (!parser.parsing_success) {
171 // TODO List all available formats here, maybe add anothoer usage function
172 printf("Invalid output format: %s\n", optarg);
173 exit(STATE_UNKNOWN);
174 }
175
176 config.output_format_is_set = true;
177 config.output_format = parser.output_format;
178 break;
179 }
180 case '?': /* print short usage statement if args not parsable */ 201 case '?': /* print short usage statement if args not parsable */
181 usage5(); 202 usage5();
182 case 'h': /* help */ 203 case 'h': /* help */
@@ -194,35 +215,26 @@ process_argument_wrapper process_arguments(int argc, char **argv) {
194 } 215 }
195 } 216 }
196 217
197 // TODO add proper verification for ranges here! 218 option_char = optind;
198 if (warning_range) {
199 mp_range_parsed tmp = mp_parse_range_string(warning_range);
200 if (tmp.error == MP_PARSING_SUCCES) {
201 config.thresholds.warning = tmp.range;
202 config.thresholds.warning_is_set = true;
203 } else {
204 printf("Failed to parse warning range: %s", warning_range);
205 exit(STATE_UNKNOWN);
206 }
207 }
208 219
209 if (critical_range) { 220 if (warning_range == NULL && argc > option_char)
210 mp_range_parsed tmp = mp_parse_range_string(critical_range); 221 warning_range = argv[option_char++];
211 if (tmp.error == MP_PARSING_SUCCES) { 222
212 config.thresholds.critical = tmp.range; 223 if (critical_range == NULL && argc > option_char)
213 config.thresholds.critical_is_set = true; 224 critical_range = argv[option_char++];
214 } else { 225
215 printf("Failed to parse critical range: %s", critical_range); 226 /* this will abort in case of invalid ranges */
216 exit(STATE_UNKNOWN); 227 set_thresholds(&thlds, warning_range, critical_range);
217 } 228
229 if (!thlds->warning) {
230 usage4(_("Warning threshold must be a valid range expression"));
218 } 231 }
219 232
220 process_argument_wrapper result = { 233 if (!thlds->critical) {
221 .errorcode = OK, 234 usage4(_("Critical threshold must be a valid range expression"));
222 .config = config, 235 }
223 };
224 236
225 return result; 237 return OK;
226} 238}
227 239
228void print_help(void) { 240void print_help(void) {
@@ -245,7 +257,6 @@ void print_help(void) {
245 printf(" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION")); 257 printf(" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION"));
246 printf(" %s\n", "-c, --critical=RANGE_EXPRESSION"); 258 printf(" %s\n", "-c, --critical=RANGE_EXPRESSION");
247 printf(" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION")); 259 printf(" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION"));
248 printf(UT_OUTPUT_FORMAT);
249 260
250 printf(UT_SUPPORT); 261 printf(UT_SUPPORT);
251} 262}
diff --git a/plugins/check_users.d/config.h b/plugins/check_users.d/config.h
deleted file mode 100644
index 35b7b7f8..00000000
--- a/plugins/check_users.d/config.h
+++ /dev/null
@@ -1,19 +0,0 @@
1#pragma once
2
3#include "output.h"
4#include "thresholds.h"
5typedef struct check_users_config {
6 mp_thresholds thresholds;
7
8 bool output_format_is_set;
9 mp_output_format output_format;
10} check_users_config;
11
12check_users_config check_users_config_init() {
13 check_users_config tmp = {
14 .thresholds = mp_thresholds_init(),
15
16 .output_format_is_set = false,
17 };
18 return tmp;
19}
diff --git a/plugins/check_users.d/users.c b/plugins/check_users.d/users.c
deleted file mode 100644
index 7969ae79..00000000
--- a/plugins/check_users.d/users.c
+++ /dev/null
@@ -1,166 +0,0 @@
1#include "./users.h"
2
3#ifdef _WIN32
4# ifdef HAVE_WTSAPI32_H
5# include <windows.h>
6# include <wtsapi32.h>
7# undef ERROR
8# define ERROR -1
9
10get_num_of_users_wrapper get_num_of_users_windows() {
11 WTS_SESSION_INFO *wtsinfo;
12 DWORD wtscount;
13
14 get_num_of_users_wrapper result = {};
15
16 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &wtsinfo, &wtscount)) {
17 // printf(_("Could not enumerate RD sessions: %d\n"), GetLastError());
18 result.error = WINDOWS_COULD_NOT_ENUMERATE_SESSIONS;
19 return result;
20 }
21
22 for (DWORD index = 0; index < wtscount; index++) {
23 LPTSTR username;
24 DWORD size;
25
26 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wtsinfo[index].SessionId, WTSUserName, &username, &size)) {
27 continue;
28 }
29
30 int len = lstrlen(username);
31
32 WTSFreeMemory(username);
33
34 if (len == 0) {
35 continue;
36 }
37
38 if (wtsinfo[index].State == WTSActive || wtsinfo[index].State == WTSDisconnected) {
39 result.users++;
40 }
41 }
42
43 WTSFreeMemory(wtsinfo);
44 return result;
45}
46# else // HAVE_WTSAPI32_H
47# error On windows but without the WTSAPI32 lib
48# endif // HAVE_WTSAPI32_H
49
50#else // _WIN32
51
52# include "../../config.h"
53
54# ifdef HAVE_LIBSYSTEMD
55# include <systemd/sd-daemon.h>
56# include <systemd/sd-login.h>
57
58get_num_of_users_wrapper get_num_of_users_systemd() {
59 get_num_of_users_wrapper result = {};
60
61 // Test whether we booted with systemd
62 if (sd_booted() > 0) {
63 int users = sd_get_sessions(NULL);
64 if (users >= 0) {
65 // Success
66 result.users = users;
67 return result;
68 }
69
70 // Failure! return the error code
71 result.errorcode = users;
72 return result;
73 }
74
75 // Looks like we are not running systemd,
76 // return with error here
77 result.errorcode = NO_SYSTEMD_ERROR;
78 return result;
79}
80# endif
81
82# ifdef HAVE_UTMPX_H
83# include <utmpx.h>
84
85get_num_of_users_wrapper get_num_of_users_utmp() {
86 int users = 0;
87
88 /* get currently logged users from utmpx */
89 setutxent();
90
91 struct utmpx *putmpx;
92 while ((putmpx = getutxent()) != NULL) {
93 if (putmpx->ut_type == USER_PROCESS) {
94 users++;
95 }
96 }
97
98 endutxent();
99
100 get_num_of_users_wrapper result = {
101 .errorcode = 0,
102 .users = users,
103 };
104
105 return result;
106}
107# endif
108
109# ifndef HAVE_WTSAPI32_H
110# ifndef HAVE_LIBSYSTEMD
111# ifndef HAVE_UTMPX_H
112// Fall back option here for the others (probably still not on windows)
113
114# include "../popen.h"
115# include "../common.h"
116# include "../utils.h"
117
118get_num_of_users_wrapper get_num_of_users_who_command() {
119 /* run the command */
120 child_process = spopen(WHO_COMMAND);
121 if (child_process == NULL) {
122 // printf(_("Could not open pipe: %s\n"), WHO_COMMAND);
123 get_num_of_users_wrapper result = {
124 .errorcode = COULD_NOT_OPEN_PIPE,
125 };
126 return result;
127 }
128
129 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
130 if (child_stderr == NULL) {
131 // printf(_("Could not open stderr for %s\n"), WHO_COMMAND);
132 // TODO this error should probably be reported
133 }
134
135 get_num_of_users_wrapper result = {};
136 char input_buffer[MAX_INPUT_BUFFER];
137 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
138 /* increment 'users' on all lines except total user count */
139 if (input_buffer[0] != '#') {
140 result.users++;
141 continue;
142 }
143
144 /* get total logged in users */
145 if (sscanf(input_buffer, _("# users=%d"), &result.users) == 1) {
146 break;
147 }
148 }
149
150 /* check STDERR */
151 if (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
152 // if this fails, something broke and the result can not be relied upon or so is the theorie here
153 result.errorcode = STDERR_COULD_NOT_BE_READ;
154 }
155 (void)fclose(child_stderr);
156
157 /* close the pipe */
158 spclose(child_process);
159
160 return result;
161}
162
163# endif
164# endif
165# endif
166#endif
diff --git a/plugins/check_users.d/users.h b/plugins/check_users.d/users.h
deleted file mode 100644
index aacba775..00000000
--- a/plugins/check_users.d/users.h
+++ /dev/null
@@ -1,18 +0,0 @@
1#pragma once
2
3typedef struct get_num_of_users_wrapper {
4 int errorcode;
5 int users;
6} get_num_of_users_wrapper;
7
8enum {
9 NO_SYSTEMD_ERROR = 64,
10 WINDOWS_COULD_NOT_ENUMERATE_SESSIONS,
11 COULD_NOT_OPEN_PIPE,
12 STDERR_COULD_NOT_BE_READ,
13};
14
15get_num_of_users_wrapper get_num_of_users_systemd();
16get_num_of_users_wrapper get_num_of_users_utmp();
17get_num_of_users_wrapper get_num_of_users_windows();
18get_num_of_users_wrapper get_num_of_users_who_command();