Code

more pedantic compiler warnings
[nagiosplug.git] / plugins / check_ups.c
1 /******************************************************************************
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; either version 2 of the License, or (at
6  your option) any later version.
8  This program is distributed in the hope that it will be useful, but
9  WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  General Public License for more details.
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 ******************************************************************************/
19 const char *progname = "check_ups";
20 const char *revision = "$Revision$";
21 const char *copyright = "2000-2002";
22 const char *email = "nagiosplug-devel@lists.sourceforge.net";
24 #include "common.h"
25 #include "netutils.h"
26 #include "utils.h"
28 enum {
29         PORT = 3493
30 };
32 #define CHECK_NONE       0
34 #define UPS_NONE     0   /* no supported options */
35 #define UPS_UTILITY  1   /* supports utility line voltage */
36 #define UPS_BATTPCT  2   /* supports percent battery remaining */
37 #define UPS_STATUS   4   /* supports UPS status */
38 #define UPS_TEMP     8   /* supports UPS temperature */
39 #define UPS_LOADPCT     16   /* supports load percent */
41 #define UPSSTATUS_NONE     0
42 #define UPSSTATUS_OFF      1
43 #define UPSSTATUS_OL       2
44 #define UPSSTATUS_OB       4
45 #define UPSSTATUS_LB       8
46 #define UPSSTATUS_CAL     16
47 #define UPSSTATUS_RB      32  /*Replace Battery */
48 #define UPSSTATUS_UNKOWN  64
50 int server_port = PORT;
51 char *server_address;
52 char *ups_name = NULL;
53 double warning_value = 0.0;
54 double critical_value = 0.0;
55 int check_warning_value = FALSE;
56 int check_critical_value = FALSE;
57 int check_variable = UPS_NONE;
58 int supported_options = UPS_NONE;
59 int status = UPSSTATUS_NONE;
61 double ups_utility_voltage = 0.0;
62 double ups_battery_percent = 0.0;
63 double ups_load_percent = 0.0;
64 double ups_temperature = 0.0;
65 char *ups_status;
67 int determine_status (void);
68 int determine_supported_vars (void);
69 int get_ups_variable (const char *, char *, size_t);
71 int process_arguments (int, char **);
72 int validate_arguments (void);
73 void print_help (void);
74 void print_usage (void);
76 int
77 main (int argc, char **argv)
78 {
79         int result = STATE_OK;
80         char *message;
81         char temp_buffer[MAX_INPUT_BUFFER];
83         double ups_utility_deviation = 0.0;
84         ups_status = strdup ("N/A");
86         if (process_arguments (argc, argv) != OK)
87                 usage ("Invalid command arguments supplied\n");
89         /* initialize alarm signal handling */
90         signal (SIGALRM, socket_timeout_alarm_handler);
92         /* set socket timeout */
93         alarm (socket_timeout);
95         /* determine what variables the UPS supports */
96         if (determine_supported_vars () != OK)
97                 return STATE_CRITICAL;
99         /* get the ups status if possible */
100         if (supported_options & UPS_STATUS) {
102                 if (determine_status () != OK)
103                         return STATE_CRITICAL;
104                 ups_status = strdup ("");
105                 result = STATE_OK;
107                 if (status & UPSSTATUS_OFF) {
108                         asprintf (&ups_status, "Off");
109                         result = STATE_CRITICAL;
110                 }
111                 else if ((status & (UPSSTATUS_OB | UPSSTATUS_LB)) ==
112                                                  (UPSSTATUS_OB | UPSSTATUS_LB)) {
113                         asprintf (&ups_status, "On Battery, Low Battery");
114                         result = STATE_CRITICAL;
115                 }
116                 else {
117                         if (status & UPSSTATUS_OL) {
118                                 asprintf (&ups_status, "%s%s", ups_status, "Online");
119                         }
120                         if (status & UPSSTATUS_OB) {
121                                 asprintf (&ups_status, "%s%s", ups_status, "On Battery");
122                                 result = STATE_WARNING;
123                         }
124                         if (status & UPSSTATUS_LB) {
125                                 asprintf (&ups_status, "%s%s", ups_status, ", Low Battery");
126                                 result = STATE_WARNING;
127                         }
128                         if (status & UPSSTATUS_CAL) {
129                                 asprintf (&ups_status, "%s%s", ups_status, ", Calibrating");
130                         }
131                         if (status & UPSSTATUS_RB) {
132                                 asprintf (&ups_status, "%s%s", ups_status, ", Replace Battery");
133                                 result = STATE_WARNING;
134                         }
135                         if (status & UPSSTATUS_UNKOWN) {
136                                 asprintf (&ups_status, "%s%s", ups_status, ", Unknown");
137                         }
138                 }
139         }
141         /* get the ups utility voltage if possible */
142         if (supported_options & UPS_UTILITY) {
144                 if (get_ups_variable ("UTILITY", temp_buffer, sizeof (temp_buffer)) != OK)
145                         return STATE_CRITICAL;
147                 ups_utility_voltage = atof (temp_buffer);
149                 if (ups_utility_voltage > 120.0)
150                         ups_utility_deviation = 120.0 - ups_utility_voltage;
151                 else
152                         ups_utility_deviation = ups_utility_voltage - 120.0;
154                 if (check_variable == UPS_UTILITY) {
155                         if (check_critical_value == TRUE
156                                         && ups_utility_deviation >= critical_value) result = STATE_CRITICAL;
157                         else if (check_warning_value == TRUE
158                                                          && ups_utility_deviation >= warning_value
159                                                          && result < STATE_WARNING) result = STATE_WARNING;
160                 }
161         }
163         /* get the ups battery percent if possible */
164         if (supported_options & UPS_BATTPCT) {
166                 if (get_ups_variable ("BATTPCT", temp_buffer, sizeof (temp_buffer)) != OK)
167                         return STATE_CRITICAL;
169                 ups_battery_percent = atof (temp_buffer);
171                 if (check_variable == UPS_BATTPCT) {
172                         if (check_critical_value == TRUE
173                                         && ups_battery_percent <= critical_value) result = STATE_CRITICAL;
174                         else if (check_warning_value == TRUE
175                                                          && ups_battery_percent <= warning_value
176                                                          && result < STATE_WARNING) result = STATE_WARNING;
177                 }
178         }
180         /* get the ups load percent if possible */
181         if (supported_options & UPS_LOADPCT) {
183                 if (get_ups_variable ("LOADPCT", temp_buffer, sizeof (temp_buffer)) != OK)
184                         return STATE_CRITICAL;
186                 ups_load_percent = atof (temp_buffer);
188                 if (check_variable == UPS_LOADPCT) {
189                         if (check_critical_value == TRUE && ups_load_percent >= critical_value)
190                                 result = STATE_CRITICAL;
191                         else if (check_warning_value == TRUE
192                                                          && ups_load_percent >= warning_value && result < STATE_WARNING)
193                                 result = STATE_WARNING;
194                 }
195         }
197         /* get the ups temperature if possible */
198         if (supported_options & UPS_TEMP) {
200                 if (get_ups_variable ("UPSTEMP", temp_buffer, sizeof (temp_buffer)) != OK)
201                         return STATE_CRITICAL;
203                 ups_temperature = (atof (temp_buffer) * 1.8) + 32;
205                 if (check_variable == UPS_TEMP) {
206                         if (check_critical_value == TRUE && ups_temperature >= critical_value)
207                                 result = STATE_CRITICAL;
208                         else if (check_warning_value == TRUE && ups_temperature >= warning_value
209                                                          && result < STATE_WARNING)
210                                 result = STATE_WARNING;
211                 }
212         }
214         /* if the UPS does not support any options we are looking for, report an error */
215         if (supported_options == UPS_NONE)
216                 result = STATE_CRITICAL;
218         /* reset timeout */
219         alarm (0);
222         asprintf (&message, "UPS %s - ", (result == STATE_OK) ? "ok" : "problem");
224         if (supported_options & UPS_STATUS)
225                 asprintf (&message, "%sStatus=%s ", message, ups_status);
227         if (supported_options & UPS_UTILITY)
228                 asprintf (&message, "%sUtility=%3.1fV ", message, ups_utility_voltage);
230         if (supported_options & UPS_BATTPCT)
231                 asprintf (&message, "%sBatt=%3.1f%% ", message, ups_battery_percent);
233         if (supported_options & UPS_LOADPCT)
234                 asprintf (&message, "%sLoad=%3.1f%% ", message, ups_load_percent);
236         if (supported_options & UPS_TEMP)
237                 asprintf (&message, "%sTemp=%3.1fF", message, ups_temperature);
239         if (supported_options == UPS_NONE)
240                 asprintf (&message, "UPS does not support any available options\n");
242         printf ("%s\n", message);
244         return result;
249 /* determines what options are supported by the UPS */
250 int
251 determine_status (void)
253         char recv_buffer[MAX_INPUT_BUFFER];
254         char temp_buffer[MAX_INPUT_BUFFER];
255         char *ptr;
257         if (get_ups_variable ("STATUS", recv_buffer, sizeof (recv_buffer)) !=
258                         STATE_OK) {
259                 printf ("Invalid response received from hostn");
260                 return ERROR;
261         }
263         recv_buffer[strlen (recv_buffer) - 1] = 0;
265         strcpy (temp_buffer, recv_buffer);
266         for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
267                          ptr = (char *) strtok (NULL, " ")) {
268                 if (!strcmp (ptr, "OFF"))
269                         status |= UPSSTATUS_OFF;
270                 else if (!strcmp (ptr, "OL"))
271                         status |= UPSSTATUS_OL;
272                 else if (!strcmp (ptr, "OB"))
273                         status |= UPSSTATUS_OB;
274                 else if (!strcmp (ptr, "LB"))
275                         status |= UPSSTATUS_LB;
276                 else if (!strcmp (ptr, "CAL"))
277                         status |= UPSSTATUS_CAL;
278                 else if (!strcmp (ptr, "RB"))
279                         status |= UPSSTATUS_RB;
280                 else
281                         status |= UPSSTATUS_UNKOWN;
282         }
284         return OK;
288 /* determines what options are supported by the UPS */
289 int
290 determine_supported_vars (void)
292         char send_buffer[MAX_INPUT_BUFFER];
293         char recv_buffer[MAX_INPUT_BUFFER];
294         char temp_buffer[MAX_INPUT_BUFFER];
295         char *ptr;
298         /* get the list of variables that this UPS supports */
299         if (ups_name)
300                 sprintf (send_buffer, "LISTVARS %s\r\n", ups_name);
301         else
302                 sprintf (send_buffer, "LISTVARS\r\n");
303         if (process_tcp_request
304                         (server_address, server_port, send_buffer, recv_buffer,
305                          sizeof (recv_buffer)) != STATE_OK) {
306                 printf ("Invalid response received from host\n");
307                 return ERROR;
308         }
310         recv_buffer[strlen (recv_buffer) - 1] = 0;
312         if (ups_name)
313                 ptr = recv_buffer + 5 + strlen (ups_name) + 2;
314         else
315                 ptr = recv_buffer + 5;
317         strcpy (temp_buffer, recv_buffer);
319         for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
320                          ptr = (char *) strtok (NULL, " ")) {
321                 if (!strcmp (ptr, "UTILITY"))
322                         supported_options |= UPS_UTILITY;
323                 else if (!strcmp (ptr, "BATTPCT"))
324                         supported_options |= UPS_BATTPCT;
325                 else if (!strcmp (ptr, "LOADPCT"))
326                         supported_options |= UPS_LOADPCT;
327                 else if (!strcmp (ptr, "STATUS"))
328                         supported_options |= UPS_STATUS;
329                 else if (!strcmp (ptr, "UPSTEMP"))
330                         supported_options |= UPS_TEMP;
331         }
333         return OK;
337 /* gets a variable value for a specific UPS  */
338 int
339 get_ups_variable (const char *varname, char *buf, size_t buflen)
341         /*  char command[MAX_INPUT_BUFFER]; */
342         char temp_buffer[MAX_INPUT_BUFFER];
343         char send_buffer[MAX_INPUT_BUFFER];
344         char *ptr;
346         /* create the command string to send to the UPS daemon */
347         if (ups_name)
348                 sprintf (send_buffer, "REQ %s@%s\n", varname, ups_name);
349         else
350                 sprintf (send_buffer, "REQ %s\n", varname);
352         /* send the command to the daemon and get a response back */
353         if (process_tcp_request
354                         (server_address, server_port, send_buffer, temp_buffer,
355                          sizeof (temp_buffer)) != STATE_OK) {
356                 printf ("Invalid response received from host\n");
357                 return ERROR;
358         }
360         if (ups_name)
361                 ptr = temp_buffer + strlen (varname) + 5 + strlen (ups_name) + 1;
362         else
363                 ptr = temp_buffer + strlen (varname) + 5;
365         if (!strcmp (ptr, "NOT-SUPPORTED")) {
366                 printf ("Error: Variable '%s' is not supported\n", varname);
367                 return ERROR;
368         }
370         if (!strcmp (ptr, "DATA-STALE")) {
371                 printf ("Error: UPS data is stale\n");
372                 return ERROR;
373         }
375         if (!strcmp (ptr, "UNKNOWN-UPS")) {
376                 if (ups_name)
377                         printf ("Error: UPS '%s' is unknown\n", ups_name);
378                 else
379                         printf ("Error: UPS is unknown\n");
380                 return ERROR;
381         }
383         strncpy (buf, ptr, buflen - 1);
384         buf[buflen - 1] = 0;
386         return OK;
393 /* Command line: CHECK_UPS <host_address> [-u ups] [-p port] [-v variable] 
394                            [-wv warn_value] [-cv crit_value] [-to to_sec] */
397 /* process command-line arguments */
398 int
399 process_arguments (int argc, char **argv)
401         int c;
403         int option_index = 0;
404         static struct option long_options[] = {
405                 {"hostname", required_argument, 0, 'H'},
406                 {"ups", required_argument, 0, 'u'},
407                 {"port", required_argument, 0, 'p'},
408                 {"critical", required_argument, 0, 'c'},
409                 {"warning", required_argument, 0, 'w'},
410                 {"timeout", required_argument, 0, 't'},
411                 {"variable", required_argument, 0, 'v'},
412                 {"version", no_argument, 0, 'V'},
413                 {"help", no_argument, 0, 'h'},
414                 {0, 0, 0, 0}
415         };
417         if (argc < 2)
418                 return ERROR;
420         for (c = 1; c < argc; c++) {
421                 if (strcmp ("-to", argv[c]) == 0)
422                         strcpy (argv[c], "-t");
423                 else if (strcmp ("-wt", argv[c]) == 0)
424                         strcpy (argv[c], "-w");
425                 else if (strcmp ("-ct", argv[c]) == 0)
426                         strcpy (argv[c], "-c");
427         }
429         while (1) {
430                 c = getopt_long (argc, argv, "hVH:u:p:v:c:w:t:", long_options,
431                                                                          &option_index);
433                 if (c == -1 || c == EOF)
434                         break;
436                 switch (c) {
437                 case '?':                                                                       /* help */
438                         usage3 ("Unknown option", optopt);
439                 case 'H':                                                                       /* hostname */
440                         if (is_host (optarg)) {
441                                 server_address = optarg;
442                         }
443                         else {
444                                 usage2 ("Invalid host name", optarg);
445                         }
446                         break;
447                 case 'u':                                                                       /* ups name */
448                         ups_name = optarg;
449                         break;
450                 case 'p':                                                                       /* port */
451                         if (is_intpos (optarg)) {
452                                 server_port = atoi (optarg);
453                         }
454                         else {
455                                 usage2 ("Server port must be a positive integer", optarg);
456                         }
457                         break;
458                 case 'c':                                                                       /* critical time threshold */
459                         if (is_intnonneg (optarg)) {
460                                 critical_value = atoi (optarg);
461                                 check_critical_value = TRUE;
462                         }
463                         else {
464                                 usage2 ("Critical time must be a nonnegative integer", optarg);
465                         }
466                         break;
467                 case 'w':                                                                       /* warning time threshold */
468                         if (is_intnonneg (optarg)) {
469                                 warning_value = atoi (optarg);
470                                 check_warning_value = TRUE;
471                         }
472                         else {
473                                 usage2 ("Warning time must be a nonnegative integer", optarg);
474                         }
475                         break;
476                 case 'v':                                                                       /* variable */
477                         if (!strcmp (optarg, "LINE"))
478                                 check_variable = UPS_UTILITY;
479                         else if (!strcmp (optarg, "TEMP"))
480                                 check_variable = UPS_TEMP;
481                         else if (!strcmp (optarg, "BATTPCT"))
482                                 check_variable = UPS_BATTPCT;
483                         else if (!strcmp (optarg, "LOADPCT"))
484                                 check_variable = UPS_LOADPCT;
485                         else
486                                 usage2 ("Unrecognized UPS variable", optarg);
487                         break;
488                 case 't':                                                                       /* timeout */
489                         if (is_intnonneg (optarg)) {
490                                 socket_timeout = atoi (optarg);
491                         }
492                         else {
493                                 usage ("Time interval must be a nonnegative integer\n");
494                         }
495                         break;
496                 case 'V':                                                                       /* version */
497                         print_revision (progname, "$Revision$");
498                         exit (STATE_OK);
499                 case 'h':                                                                       /* help */
500                         print_help ();
501                         exit (STATE_OK);
502                 }
503         }
506         if (server_address == NULL && argc > optind) {
507                 if (is_host (argv[optind]))
508                         server_address = argv[optind++];
509                 else
510                         usage ("Invalid host name");
511         }
513         if (server_address == NULL)
514                 server_address = strdup("127.0.0.1");
516         return validate_arguments();
523 int
524 validate_arguments (void)
526         return OK;
533 \f
534 void
535 print_help (void)
537         char *myport;
538         asprintf (&myport, "%d", PORT);
540         print_revision (progname, revision);
542         printf (_("Copyright (c) 2000 Tom Shields"));
543         printf (_(COPYRIGHT), copyright, email);
545         printf (_("This plugin tests the UPS service on the specified host.\n\
546 Network UPS Tools from www.exploits.org must be running for this plugin to\n\
547 work.\n\n"));
549         print_usage ();
551         printf (_(UT_HELP_VRSN));
553         printf (_(UT_HOST_PORT), 'p', myport);
555         printf (_("\
556  -u, --ups=STRING\n\
557     Name of UPS\n"));
559         printf (_(UT_WARN_CRIT));
561         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
563         printf (_(UT_VERBOSE));
565         printf (_("\
566 This plugin attempts to determine the status of a UPS (Uninterruptible Power\n\
567 Supply) on a local or remote host. If the UPS is online or calibrating, the\n\
568 plugin will return an OK state. If the battery is on it will return a WARNING\n\
569 state.  If the UPS is off or has a low battery the plugin will return a CRITICAL\n\
570 state.\n\n"));
572         printf (_("\
573 You may also specify a variable to check [such as temperature, utility voltage,\n\
574 battery load, etc.]  as well as warning and critical thresholds for the value of\n\
575 that variable.  If the remote host has multiple UPS that are being monitored you\n\
576 will have to use the [ups] option to specify which UPS to check.\n\n"));
578         printf (_("Notes:\n\n\
579 This plugin requires that the UPSD daemon distributed with Russel Kroll's\n\
580 Smart UPS Tools be installed on the remote host.  If you do not have the\n\
581 package installed on your system, you can download it from\n\
582 http://www.exploits.org/nut\n\n"));
584         printf (_(UT_SUPPORT));
590 void
591 print_usage (void)
593         printf (_("\
594 Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit]\n\
595     [-t timeout] [-v]\n"), progname);
596         printf (_(UT_HLP_VRS), progname, progname);