1 /******************************************************************************
2 *
3 * CHECK_USERS.C
4 *
5 * Program: Current users plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * Last Modified: $Date$
10 * Modifications:
11 *
12 * 1999-11-17 Karl DeBisschop
13 * - check stderr and status from spoen/spclose
14 * - reformat commenst to fit 80-cahr screen
15 * - set default result to STATE_UNKNOWN
16 * - initialize users at -1, eliminate 'found' variable
17 *
18 * Command line: CHECK_USERS <wusers> <cusers>
19 *
20 * Description:
21 *
22 * This plugin will use the /usr/bin/who command to check the number
23 * of users currently logged into the system. If number of logged in
24 * user exceeds the number specified by the <cusers> option, a
25 * STATE_CRITICAL is return. It it exceeds <wusers>, a STATE_WARNING
26 * is returned. Errors reading the output from the who command result
27 * in a STATE_UNKNOWN error.
28 *
29 * License Information:
30 *
31 * This program is free software; you can redistribute it and/or modify
32 * it under the terms of the GNU General Public License as published by
33 * the Free Software Foundation; either version 2 of the License, or
34 * (at your option) any later version.
35 *
36 * This program is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with this program; if not, write to the Free Software
43 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44 *
45 *****************************************************************************/
47 #include "common.h"
48 #include "popen.h"
49 #include "utils.h"
51 const char *progname = "check_users";
52 #define REVISION "$Revision$"
53 #define COPYRIGHT "1999-2002"
54 #define AUTHOR "Ethan Galstad"
55 #define EMAIL "nagios@nagios.org"
57 #define possibly_set(a,b) ((a) == 0 ? (b) : 0)
59 int process_arguments (int, char **);
60 void print_usage (void);
61 void print_help (void);
63 int wusers = -1;
64 int cusers = -1;
66 int
67 main (int argc, char **argv)
68 {
69 int users = -1;
70 int result = STATE_OK;
71 char input_buffer[MAX_INPUT_BUFFER];
73 if (process_arguments (argc, argv) == ERROR)
74 usage ("Could not parse arguments\n");
76 /* run the command */
77 child_process = spopen (WHO_COMMAND);
78 if (child_process == NULL) {
79 printf ("Could not open pipe: %s\n", WHO_COMMAND);
80 return STATE_UNKNOWN;
81 }
83 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
84 if (child_stderr == NULL)
85 printf ("Could not open stderr for %s\n", WHO_COMMAND);
87 users = 0;
89 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
91 /* increment 'users' on all lines except total user count */
92 if (input_buffer[0] != '#') {
93 users++;
94 continue;
95 }
97 /* get total logged in users */
98 if (sscanf (input_buffer, "# users=%d", &users) == 1)
99 break;
101 }
103 /* check STDERR */
104 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
105 result = possibly_set (result, STATE_UNKNOWN);
106 (void) fclose (child_stderr);
108 /* close the pipe */
109 if (spclose (child_process))
110 result = possibly_set (result, STATE_UNKNOWN);
112 /* else check the user count against warning and critical thresholds */
113 if (users >= cusers)
114 result = STATE_CRITICAL;
115 else if (users >= wusers)
116 result = STATE_WARNING;
117 else if (users >= 0)
118 result = STATE_OK;
120 if (result == STATE_UNKNOWN)
121 printf ("Unable to read output\n");
122 else
123 printf ("USERS %s - %d users currently logged in\n", state_text (result),
124 users);
126 return result;
127 }
133 /* process command-line arguments */
134 int
135 process_arguments (int argc, char **argv)
136 {
137 int c;
139 int option_index = 0;
140 static struct option long_options[] = {
141 {"critical", required_argument, 0, 'c'},
142 {"warning", required_argument, 0, 'w'},
143 {"version", no_argument, 0, 'V'},
144 {"help", no_argument, 0, 'h'},
145 {0, 0, 0, 0}
146 };
148 if (argc < 2)
149 usage ("\n");
151 while (1) {
152 c = getopt_long (argc, argv, "+hVvc:w:", long_options, &option_index);
154 if (c == -1 || c == EOF || c == 1)
155 break;
157 switch (c) {
158 case '?': /* print short usage statement if args not parsable */
159 printf ("%s: Unknown argument: %s\n\n", progname, optarg);
160 print_usage ();
161 exit (STATE_UNKNOWN);
162 case 'h': /* help */
163 print_help ();
164 exit (STATE_OK);
165 case 'V': /* version */
166 print_revision (progname, REVISION);
167 exit (STATE_OK);
168 case 'c': /* critical */
169 if (!is_intnonneg (optarg))
170 usage ("Critical threshold must be a nonnegative integer\n");
171 cusers = atoi (optarg);
172 break;
173 case 'w': /* warning */
174 if (!is_intnonneg (optarg))
175 usage ("Warning threshold must be a nonnegative integer\n");
176 wusers = atoi (optarg);
177 break;
178 }
179 }
181 c = optind;
182 if (wusers == -1 && argc > c) {
183 if (is_intnonneg (argv[c]) == FALSE)
184 usage ("Warning threshold must be a nonnegative integer\n");
185 wusers = atoi (argv[c++]);
186 }
188 if (cusers == -1 && argc > c) {
189 if (is_intnonneg (argv[c]) == FALSE)
190 usage ("Warning threshold must be a nonnegative integer\n");
191 cusers = atoi (argv[c]);
192 }
194 return OK;
195 }
201 void
202 print_usage (void)
203 {
204 printf ("Usage: %s -w <users> -c <users>\n", progname);
205 }
211 void
212 print_help (void)
213 {
214 print_revision (progname, REVISION);
215 printf
216 ("Copyright (c) " COPYRIGHT " " AUTHOR "(" EMAIL ")\n\n"
217 "This plugin checks the number of users currently logged in on the local\n"
218 "system and generates an error if the number exceeds the thresholds specified.\n");
219 print_usage ();
220 printf
221 ("Options:\n"
222 " -w, --warning=INTEGER\n"
223 " Set WARNING status if more than INTEGER users are logged in\n"
224 " -c, --critical=INTEGER\n"
225 " Set CRITICAL status if more than INTEGER users are logged in\n"
226 " -h, --help\n"
227 " Print detailed help screen\n"
228 " -V, --version\n" " Print version information\n");
229 }