Code

- typo fixes
[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];
82         double ups_utility_deviation = 0.0;
84         setlocale (LC_ALL, "");
85         bindtextdomain (PACKAGE, LOCALEDIR);
86         textdomain (PACKAGE);
88         ups_status = strdup ("N/A");
90         if (process_arguments (argc, argv) != OK)
91                 usage ("Invalid command arguments supplied\n");
93         /* initialize alarm signal handling */
94         signal (SIGALRM, socket_timeout_alarm_handler);
96         /* set socket timeout */
97         alarm (socket_timeout);
99         /* determine what variables the UPS supports */
100         if (determine_supported_vars () != OK)
101                 return STATE_CRITICAL;
103         /* get the ups status if possible */
104         if (supported_options & UPS_STATUS) {
106                 if (determine_status () != OK)
107                         return STATE_CRITICAL;
108                 ups_status = strdup ("");
109                 result = STATE_OK;
111                 if (status & UPSSTATUS_OFF) {
112                         asprintf (&ups_status, "Off");
113                         result = STATE_CRITICAL;
114                 }
115                 else if ((status & (UPSSTATUS_OB | UPSSTATUS_LB)) ==
116                                                  (UPSSTATUS_OB | UPSSTATUS_LB)) {
117                         asprintf (&ups_status, "On Battery, Low Battery");
118                         result = STATE_CRITICAL;
119                 }
120                 else {
121                         if (status & UPSSTATUS_OL) {
122                                 asprintf (&ups_status, "%s%s", ups_status, "Online");
123                         }
124                         if (status & UPSSTATUS_OB) {
125                                 asprintf (&ups_status, "%s%s", ups_status, "On Battery");
126                                 result = STATE_WARNING;
127                         }
128                         if (status & UPSSTATUS_LB) {
129                                 asprintf (&ups_status, "%s%s", ups_status, ", Low Battery");
130                                 result = STATE_WARNING;
131                         }
132                         if (status & UPSSTATUS_CAL) {
133                                 asprintf (&ups_status, "%s%s", ups_status, ", Calibrating");
134                         }
135                         if (status & UPSSTATUS_RB) {
136                                 asprintf (&ups_status, "%s%s", ups_status, ", Replace Battery");
137                                 result = STATE_WARNING;
138                         }
139                         if (status & UPSSTATUS_UNKOWN) {
140                                 asprintf (&ups_status, "%s%s", ups_status, ", Unknown");
141                         }
142                 }
143         }
145         /* get the ups utility voltage if possible */
146         if (supported_options & UPS_UTILITY) {
148                 if (get_ups_variable ("UTILITY", temp_buffer, sizeof (temp_buffer)) != OK)
149                         return STATE_CRITICAL;
151                 ups_utility_voltage = atof (temp_buffer);
153                 if (ups_utility_voltage > 120.0)
154                         ups_utility_deviation = 120.0 - ups_utility_voltage;
155                 else
156                         ups_utility_deviation = ups_utility_voltage - 120.0;
158                 if (check_variable == UPS_UTILITY) {
159                         if (check_critical_value == TRUE
160                                         && ups_utility_deviation >= critical_value) result = STATE_CRITICAL;
161                         else if (check_warning_value == TRUE
162                                                          && ups_utility_deviation >= warning_value
163                                                          && result < STATE_WARNING) result = STATE_WARNING;
164                 }
165         }
167         /* get the ups battery percent if possible */
168         if (supported_options & UPS_BATTPCT) {
170                 if (get_ups_variable ("BATTPCT", temp_buffer, sizeof (temp_buffer)) != OK)
171                         return STATE_CRITICAL;
173                 ups_battery_percent = atof (temp_buffer);
175                 if (check_variable == UPS_BATTPCT) {
176                         if (check_critical_value == TRUE
177                                         && ups_battery_percent <= critical_value) result = STATE_CRITICAL;
178                         else if (check_warning_value == TRUE
179                                                          && ups_battery_percent <= warning_value
180                                                          && result < STATE_WARNING) result = STATE_WARNING;
181                 }
182         }
184         /* get the ups load percent if possible */
185         if (supported_options & UPS_LOADPCT) {
187                 if (get_ups_variable ("LOADPCT", temp_buffer, sizeof (temp_buffer)) != OK)
188                         return STATE_CRITICAL;
190                 ups_load_percent = atof (temp_buffer);
192                 if (check_variable == UPS_LOADPCT) {
193                         if (check_critical_value == TRUE && ups_load_percent >= critical_value)
194                                 result = STATE_CRITICAL;
195                         else if (check_warning_value == TRUE
196                                                          && ups_load_percent >= warning_value && result < STATE_WARNING)
197                                 result = STATE_WARNING;
198                 }
199         }
201         /* get the ups temperature if possible */
202         if (supported_options & UPS_TEMP) {
204                 if (get_ups_variable ("UPSTEMP", temp_buffer, sizeof (temp_buffer)) != OK)
205                         return STATE_CRITICAL;
207                 ups_temperature = (atof (temp_buffer) * 1.8) + 32;
209                 if (check_variable == UPS_TEMP) {
210                         if (check_critical_value == TRUE && ups_temperature >= critical_value)
211                                 result = STATE_CRITICAL;
212                         else if (check_warning_value == TRUE && ups_temperature >= warning_value
213                                                          && result < STATE_WARNING)
214                                 result = STATE_WARNING;
215                 }
216         }
218         /* if the UPS does not support any options we are looking for, report an error */
219         if (supported_options == UPS_NONE)
220                 result = STATE_CRITICAL;
222         /* reset timeout */
223         alarm (0);
226         asprintf (&message, "UPS %s - ", (result == STATE_OK) ? "ok" : "problem");
228         if (supported_options & UPS_STATUS)
229                 asprintf (&message, "%sStatus=%s ", message, ups_status);
231         if (supported_options & UPS_UTILITY)
232                 asprintf (&message, "%sUtility=%3.1fV ", message, ups_utility_voltage);
234         if (supported_options & UPS_BATTPCT)
235                 asprintf (&message, "%sBatt=%3.1f%% ", message, ups_battery_percent);
237         if (supported_options & UPS_LOADPCT)
238                 asprintf (&message, "%sLoad=%3.1f%% ", message, ups_load_percent);
240         if (supported_options & UPS_TEMP)
241                 asprintf (&message, "%sTemp=%3.1fF", message, ups_temperature);
243         if (supported_options == UPS_NONE)
244                 asprintf (&message, "UPS does not support any available options\n");
246         printf ("%s\n", message);
248         return result;
253 /* determines what options are supported by the UPS */
254 int
255 determine_status (void)
257         char recv_buffer[MAX_INPUT_BUFFER];
258         char temp_buffer[MAX_INPUT_BUFFER];
259         char *ptr;
261         if (get_ups_variable ("STATUS", recv_buffer, sizeof (recv_buffer)) !=
262                         STATE_OK) {
263                 printf ("Invalid response received from hostn");
264                 return ERROR;
265         }
267         recv_buffer[strlen (recv_buffer) - 1] = 0;
269         strcpy (temp_buffer, recv_buffer);
270         for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
271                          ptr = (char *) strtok (NULL, " ")) {
272                 if (!strcmp (ptr, "OFF"))
273                         status |= UPSSTATUS_OFF;
274                 else if (!strcmp (ptr, "OL"))
275                         status |= UPSSTATUS_OL;
276                 else if (!strcmp (ptr, "OB"))
277                         status |= UPSSTATUS_OB;
278                 else if (!strcmp (ptr, "LB"))
279                         status |= UPSSTATUS_LB;
280                 else if (!strcmp (ptr, "CAL"))
281                         status |= UPSSTATUS_CAL;
282                 else if (!strcmp (ptr, "RB"))
283                         status |= UPSSTATUS_RB;
284                 else
285                         status |= UPSSTATUS_UNKOWN;
286         }
288         return OK;
292 /* determines what options are supported by the UPS */
293 int
294 determine_supported_vars (void)
296         char send_buffer[MAX_INPUT_BUFFER];
297         char recv_buffer[MAX_INPUT_BUFFER];
298         char temp_buffer[MAX_INPUT_BUFFER];
299         char *ptr;
302         /* get the list of variables that this UPS supports */
303         if (ups_name)
304                 sprintf (send_buffer, "LISTVARS %s\r\n", ups_name);
305         else
306                 sprintf (send_buffer, "LISTVARS\r\n");
307         if (process_tcp_request
308                         (server_address, server_port, send_buffer, recv_buffer,
309                          sizeof (recv_buffer)) != STATE_OK) {
310                 printf ("Invalid response received from host\n");
311                 return ERROR;
312         }
314         recv_buffer[strlen (recv_buffer) - 1] = 0;
316         if (ups_name)
317                 ptr = recv_buffer + 5 + strlen (ups_name) + 2;
318         else
319                 ptr = recv_buffer + 5;
321         strcpy (temp_buffer, recv_buffer);
323         for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
324                          ptr = (char *) strtok (NULL, " ")) {
325                 if (!strcmp (ptr, "UTILITY"))
326                         supported_options |= UPS_UTILITY;
327                 else if (!strcmp (ptr, "BATTPCT"))
328                         supported_options |= UPS_BATTPCT;
329                 else if (!strcmp (ptr, "LOADPCT"))
330                         supported_options |= UPS_LOADPCT;
331                 else if (!strcmp (ptr, "STATUS"))
332                         supported_options |= UPS_STATUS;
333                 else if (!strcmp (ptr, "UPSTEMP"))
334                         supported_options |= UPS_TEMP;
335         }
337         return OK;
341 /* gets a variable value for a specific UPS  */
342 int
343 get_ups_variable (const char *varname, char *buf, size_t buflen)
345         /*  char command[MAX_INPUT_BUFFER]; */
346         char temp_buffer[MAX_INPUT_BUFFER];
347         char send_buffer[MAX_INPUT_BUFFER];
348         char *ptr;
350         /* create the command string to send to the UPS daemon */
351         if (ups_name)
352                 sprintf (send_buffer, "REQ %s@%s\n", varname, ups_name);
353         else
354                 sprintf (send_buffer, "REQ %s\n", varname);
356         /* send the command to the daemon and get a response back */
357         if (process_tcp_request
358                         (server_address, server_port, send_buffer, temp_buffer,
359                          sizeof (temp_buffer)) != STATE_OK) {
360                 printf ("Invalid response received from host\n");
361                 return ERROR;
362         }
364         if (ups_name)
365                 ptr = temp_buffer + strlen (varname) + 5 + strlen (ups_name) + 1;
366         else
367                 ptr = temp_buffer + strlen (varname) + 5;
369         if (!strcmp (ptr, "NOT-SUPPORTED")) {
370                 printf ("Error: Variable '%s' is not supported\n", varname);
371                 return ERROR;
372         }
374         if (!strcmp (ptr, "DATA-STALE")) {
375                 printf ("Error: UPS data is stale\n");
376                 return ERROR;
377         }
379         if (!strcmp (ptr, "UNKNOWN-UPS")) {
380                 if (ups_name)
381                         printf ("Error: UPS '%s' is unknown\n", ups_name);
382                 else
383                         printf ("Error: UPS is unknown\n");
384                 return ERROR;
385         }
387         strncpy (buf, ptr, buflen - 1);
388         buf[buflen - 1] = 0;
390         return OK;
397 /* Command line: CHECK_UPS <host_address> [-u ups] [-p port] [-v variable] 
398                            [-wv warn_value] [-cv crit_value] [-to to_sec] */
401 /* process command-line arguments */
402 int
403 process_arguments (int argc, char **argv)
405         int c;
407         int option = 0;
408         static struct option longopts[] = {
409                 {"hostname", required_argument, 0, 'H'},
410                 {"ups", required_argument, 0, 'u'},
411                 {"port", required_argument, 0, 'p'},
412                 {"critical", required_argument, 0, 'c'},
413                 {"warning", required_argument, 0, 'w'},
414                 {"timeout", required_argument, 0, 't'},
415                 {"variable", required_argument, 0, 'v'},
416                 {"version", no_argument, 0, 'V'},
417                 {"help", no_argument, 0, 'h'},
418                 {0, 0, 0, 0}
419         };
421         if (argc < 2)
422                 return ERROR;
424         for (c = 1; c < argc; c++) {
425                 if (strcmp ("-to", argv[c]) == 0)
426                         strcpy (argv[c], "-t");
427                 else if (strcmp ("-wt", argv[c]) == 0)
428                         strcpy (argv[c], "-w");
429                 else if (strcmp ("-ct", argv[c]) == 0)
430                         strcpy (argv[c], "-c");
431         }
433         while (1) {
434                 c = getopt_long (argc, argv, "hVH:u:p:v:c:w:t:", longopts,
435                                                                          &option);
437                 if (c == -1 || c == EOF)
438                         break;
440                 switch (c) {
441                 case '?':                                                                       /* help */
442                         usage3 ("Unknown option", optopt);
443                 case 'H':                                                                       /* hostname */
444                         if (is_host (optarg)) {
445                                 server_address = optarg;
446                         }
447                         else {
448                                 usage2 ("Invalid host name", optarg);
449                         }
450                         break;
451                 case 'u':                                                                       /* ups name */
452                         ups_name = optarg;
453                         break;
454                 case 'p':                                                                       /* port */
455                         if (is_intpos (optarg)) {
456                                 server_port = atoi (optarg);
457                         }
458                         else {
459                                 usage2 ("Server port must be a positive integer", optarg);
460                         }
461                         break;
462                 case 'c':                                                                       /* critical time threshold */
463                         if (is_intnonneg (optarg)) {
464                                 critical_value = atoi (optarg);
465                                 check_critical_value = TRUE;
466                         }
467                         else {
468                                 usage2 ("Critical time must be a nonnegative integer", optarg);
469                         }
470                         break;
471                 case 'w':                                                                       /* warning time threshold */
472                         if (is_intnonneg (optarg)) {
473                                 warning_value = atoi (optarg);
474                                 check_warning_value = TRUE;
475                         }
476                         else {
477                                 usage2 ("Warning time must be a nonnegative integer", optarg);
478                         }
479                         break;
480                 case 'v':                                                                       /* variable */
481                         if (!strcmp (optarg, "LINE"))
482                                 check_variable = UPS_UTILITY;
483                         else if (!strcmp (optarg, "TEMP"))
484                                 check_variable = UPS_TEMP;
485                         else if (!strcmp (optarg, "BATTPCT"))
486                                 check_variable = UPS_BATTPCT;
487                         else if (!strcmp (optarg, "LOADPCT"))
488                                 check_variable = UPS_LOADPCT;
489                         else
490                                 usage2 ("Unrecognized UPS variable", optarg);
491                         break;
492                 case 't':                                                                       /* timeout */
493                         if (is_intnonneg (optarg)) {
494                                 socket_timeout = atoi (optarg);
495                         }
496                         else {
497                                 usage ("Time interval must be a nonnegative integer\n");
498                         }
499                         break;
500                 case 'V':                                                                       /* version */
501                         print_revision (progname, "$Revision$");
502                         exit (STATE_OK);
503                 case 'h':                                                                       /* help */
504                         print_help ();
505                         exit (STATE_OK);
506                 }
507         }
510         if (server_address == NULL && argc > optind) {
511                 if (is_host (argv[optind]))
512                         server_address = argv[optind++];
513                 else
514                         usage ("Invalid host name");
515         }
517         if (server_address == NULL)
518                 server_address = strdup("127.0.0.1");
520         return validate_arguments();
527 int
528 validate_arguments (void)
530         return OK;
537 \f
538 void
539 print_help (void)
541         char *myport;
542         asprintf (&myport, "%d", PORT);
544         print_revision (progname, revision);
546         printf (_("Copyright (c) 2000 Tom Shields"));
547         printf (_(COPYRIGHT), copyright, email);
549         printf (_("This plugin tests the UPS service on the specified host.\n\
550 Network UPS Tools from www.exploits.org must be running for this plugin to\n\
551 work.\n\n"));
553         print_usage ();
555         printf (_(UT_HELP_VRSN));
557         printf (_(UT_HOST_PORT), 'p', myport);
559         printf (_("\
560  -u, --ups=STRING\n\
561     Name of UPS\n"));
563         printf (_(UT_WARN_CRIT));
565         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
567         printf (_(UT_VERBOSE));
569         printf (_("\
570 This plugin attempts to determine the status of a UPS (Uninterruptible Power\n\
571 Supply) on a local or remote host. If the UPS is online or calibrating, the\n\
572 plugin will return an OK state. If the battery is on it will return a WARNING\n\
573 state.  If the UPS is off or has a low battery the plugin will return a CRITICAL\n\
574 state.\n\n"));
576         printf (_("\
577 You may also specify a variable to check [such as temperature, utility voltage,\n\
578 battery load, etc.]  as well as warning and critical thresholds for the value of\n\
579 that variable.  If the remote host has multiple UPS that are being monitored you\n\
580 will have to use the [ups] option to specify which UPS to check.\n\n"));
582         printf (_("Notes:\n\n\
583 This plugin requires that the UPSD daemon distributed with Russel Kroll's\n\
584 Smart UPS Tools be installed on the remote host.  If you do not have the\n\
585 package installed on your system, you can download it from\n\
586 http://www.exploits.org/nut\n\n"));
588         printf (_(UT_SUPPORT));
594 void
595 print_usage (void)
597         printf (_("\
598 Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit]\n\
599     [-t timeout] [-v]\n"), progname);
600         printf (_(UT_HLP_VRS), progname, progname);