1 /*****************************************************************************
3 * Monitoring check_users plugin
6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
10 * This file contains the check_users plugin
12 * This plugin checks the number of users currently logged in on the local
13 * system and generates an error if the number exceeds the thresholds
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 *****************************************************************************/
33 const char *progname
= "check_users";
34 const char *copyright
= "2000-2024";
35 const char *email
= "devel@monitoring-plugins.org";
42 # include <wtsapi32.h>
51 #ifdef HAVE_LIBSYSTEMD
52 # include <systemd/sd-daemon.h>
53 # include <systemd/sd-login.h>
56 #define possibly_set(a, b) ((a) == 0 ? (b) : 0)
58 static int process_arguments(int, char **);
59 static void print_help(void);
60 void print_usage(void);
62 static char *warning_range
= NULL
;
63 static char *critical_range
= NULL
;
64 static thresholds
*thlds
= NULL
;
66 int main(int argc
, char **argv
) {
68 int result
= STATE_UNKNOWN
;
70 WTS_SESSION_INFO
*wtsinfo
;
76 char input_buffer
[MAX_INPUT_BUFFER
];
79 setlocale(LC_ALL
, "");
80 bindtextdomain(PACKAGE
, LOCALEDIR
);
83 /* Parse extra opts if any */
84 argv
= np_extra_opts(&argc
, argv
, progname
);
86 if (process_arguments(argc
, argv
) == ERROR
)
87 usage4(_("Could not parse arguments"));
91 #ifdef HAVE_LIBSYSTEMD
93 users
= sd_get_sessions(NULL
);
97 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE
, 0, 1, &wtsinfo
, &wtscount
)) {
98 printf(_("Could not enumerate RD sessions: %d\n"), GetLastError());
102 for (index
= 0; index
< wtscount
; index
++) {
107 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE
, wtsinfo
[index
].SessionId
, WTSUserName
, &username
, &size
))
110 len
= lstrlen(username
);
112 WTSFreeMemory(username
);
117 if (wtsinfo
[index
].State
== WTSActive
|| wtsinfo
[index
].State
== WTSDisconnected
)
121 WTSFreeMemory(wtsinfo
);
123 /* get currently logged users from utmpx */
126 while ((putmpx
= getutxent()) != NULL
)
127 if (putmpx
->ut_type
== USER_PROCESS
)
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
;
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
);
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] != '#') {
150 /* get total logged in users */
151 if (sscanf(input_buffer
, _("# users=%d"), &users
) == 1)
156 if (fgets(input_buffer
, MAX_INPUT_BUFFER
- 1, child_stderr
))
157 result
= possibly_set(result
, STATE_UNKNOWN
);
158 (void)fclose(child_stderr
);
161 if (spclose(child_process
))
162 result
= possibly_set(result
, STATE_UNKNOWN
);
164 #ifdef HAVE_LIBSYSTEMD
168 /* check the user count against warning and critical thresholds */
169 result
= get_status((double)users
, thlds
);
171 if (result
== STATE_UNKNOWN
)
172 printf("%s\n", _("Unable to read output"));
174 printf(_("USERS %s - %d users currently logged in |%s\n"), state_text(result
), users
,
175 sperfdata_int("users", users
, "", warning_range
, critical_range
, true, 0, false, 0));
181 /* process command-line arguments */
182 int process_arguments(int argc
, char **argv
) {
183 static struct option longopts
[] = {{"critical", required_argument
, 0, 'c'},
184 {"warning", required_argument
, 0, 'w'},
185 {"version", no_argument
, 0, 'V'},
186 {"help", no_argument
, 0, 'h'},
195 option_char
= getopt_long(argc
, argv
, "+hVvc:w:", longopts
, &option
);
197 if (option_char
== -1 || option_char
== EOF
|| option_char
== 1)
200 switch (option_char
) {
201 case '?': /* print short usage statement if args not parsable */
206 case 'V': /* version */
207 print_revision(progname
, NP_VERSION
);
209 case 'c': /* critical */
210 critical_range
= optarg
;
212 case 'w': /* warning */
213 warning_range
= optarg
;
218 option_char
= optind
;
220 if (warning_range
== NULL
&& argc
> option_char
)
221 warning_range
= argv
[option_char
++];
223 if (critical_range
== NULL
&& argc
> option_char
)
224 critical_range
= argv
[option_char
++];
226 /* this will abort in case of invalid ranges */
227 set_thresholds(&thlds
, warning_range
, critical_range
);
229 if (!thlds
->warning
) {
230 usage4(_("Warning threshold must be a valid range expression"));
233 if (!thlds
->critical
) {
234 usage4(_("Critical threshold must be a valid range expression"));
240 void print_help(void) {
241 print_revision(progname
, NP_VERSION
);
243 printf("Copyright (c) 1999 Ethan Galstad\n");
244 printf(COPYRIGHT
, copyright
, email
);
246 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."));
253 printf(UT_HELP_VRSN
);
254 printf(UT_EXTRA_OPTS
);
256 printf(" %s\n", "-w, --warning=RANGE_EXPRESSION");
257 printf(" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION"));
258 printf(" %s\n", "-c, --critical=RANGE_EXPRESSION");
259 printf(" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION"));
264 void print_usage(void) {
265 printf("%s\n", _("Usage:"));
266 printf("%s -w <users> -c <users>\n", progname
);