Code

latest localization fixes for tonight ;-)
[nagiosplug.git] / plugins / check_nt.c
index 50bf9f03c485be64c557a59c4ec6fcc052cd1986..45a2bb0fda8ccd4708c345dc900e3b9d94441eb5 100644 (file)
@@ -1,32 +1,45 @@
 /******************************************************************************
- *
- * CHECK_NT.C
- *
- * Program: Windows NT plugin for NetSaint
- * License: GPL
- * Copyright (c) 2000-2002 Yves Rubin (rubiyz@yahoo.com)
- *
- * Description:
- * 
- * This requires NSClient software to run on NT (http://nsclient.ready2run.nl/)
- *
- * License Information:
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *****************************************************************************/
+*
+* Nagios check_nt plugin
+*
+* License: GPL
+* Copyright (c) 2000-2002 Yves Rubin (rubiyz@yahoo.com)
+* Copyright (c) 2003-2006 nagios-plugins team
+*
+* Last Modified: $Date$
+*
+* Description:
+*
+* This file contains the check_nt plugin
+*
+*  This plugin collects data from the NSClient service running on a
+*  Windows NT/2000/XP/2003 server.
+*  This requires NSClient software to run on NT (http://nsclient.ready2run.nl/)
+*
+* License Information:
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* $Id$
+*
+*****************************************************************************/
+
+const char *progname = "check_nt";
+const char *revision = "$Revision$";
+const char *copyright = "2003-2006";
+const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
 #include "netutils.h"
@@ -63,8 +76,6 @@ int check_critical_value=FALSE;
 enum checkvars vars_to_check = CHECK_NONE;
 int show_all=FALSE;
 
-const char *progname = "check_nt";
-
 char recv_buffer[MAX_INPUT_BUFFER];
 
 void fetch_data (const char* address, int port, const char* sendb);
@@ -75,32 +86,44 @@ void print_help(void);
 void print_usage(void);
 
 int main(int argc, char **argv){
+
+/* should be   int result = STATE_UNKNOWN; */
+
        int return_code = STATE_UNKNOWN;
        char *send_buffer=NULL;
        char *output_message=NULL;
+       char *perfdata=NULL;
        char *temp_string=NULL;
-       char *description=NULL;
+       char *temp_string_perf=NULL;
+       char *description=NULL,*counter_unit = NULL;
+       char *minval = NULL, *maxval = NULL, *errcvt = NULL;
 
        double total_disk_space=0;
        double free_disk_space=0;
        double percent_used_space=0;
+       double warning_used_space=0;
+       double critical_used_space=0;
        double mem_commitLimit=0;
        double mem_commitByte=0;
+       double fminval = 0, fmaxval = 0;
        unsigned long utilization;
        unsigned long uptime;
        unsigned long age_in_minutes;
-       double counter_value;
+       double counter_value = 0.0;
        int offset=0;
        int updays=0;
        int uphours=0;
        int upminutes=0;
 
+       int isPercent = FALSE;
+       int allRight = FALSE;
+
        setlocale (LC_ALL, "");
        bindtextdomain (PACKAGE, LOCALEDIR);
        textdomain (PACKAGE);
 
-       if(process_arguments(argc,argv)==ERROR)
-               usage(_("Could not parse arguments\n"));
+       if(process_arguments(argc,argv) == ERROR)
+               usage4 (_("Could not parse arguments"));
 
        /* initialize alarm signal handling */
        signal(SIGALRM,socket_timeout_alarm_handler);
@@ -133,6 +156,8 @@ int main(int argc, char **argv){
                        /* -l parameters is present with only integers */
                        return_code=STATE_OK;
                        temp_string = strdup (_("CPU Load"));
+                       temp_string_perf = strdup (" ");
+      
                        /* loop until one of the parameters is wrong or not present */
                        while (lvalue_list[0+offset]> (unsigned long)0 &&
                                                 lvalue_list[0+offset]<=(unsigned long)17280 && 
@@ -155,11 +180,16 @@ int main(int argc, char **argv){
 
                                asprintf(&output_message,_(" %lu%% (%lu min average)"), utilization, lvalue_list[0+offset]);
                                asprintf(&temp_string,"%s%s",temp_string,output_message);
+                               asprintf(&perfdata,_(" '%lu min avg Load'=%lu%%;%lu;%lu;0;100"), lvalue_list[0+offset], utilization,
+                                 lvalue_list[1+offset], lvalue_list[2+offset]);
+                               asprintf(&temp_string_perf,"%s%s",temp_string_perf,perfdata);
                                offset+=3;      /* move across the array */
                        }
-                       if (strlen(temp_string)>10)  /* we had at least one loop */
+      
+                       if (strlen(temp_string)>10) {  /* we had at least one loop */
                                output_message = strdup (temp_string);
-                       else
+                               perfdata = temp_string_perf;
+                       } else
                                output_message = strdup (_("not enough values for -l parameters"));
                }       
                break;
@@ -172,7 +202,7 @@ int main(int argc, char **argv){
                updays = uptime / 86400;                        
                uphours = (uptime % 86400) / 3600;
                upminutes = ((uptime % 86400) % 3600) / 60;
-               asprintf(&output_message,_("System Uptime : %u day(s) %u hour(s) %u minute(s)"),updays,uphours, upminutes);
+               asprintf(&output_message,_("System Uptime - %u day(s) %u hour(s) %u minute(s)"),updays,uphours, upminutes);
                return_code=STATE_OK;
                break;
 
@@ -180,7 +210,7 @@ int main(int argc, char **argv){
 
                if (value_list==NULL)
                        output_message = strdup (_("missing -l parameters"));
-               else if (strlen(value_list)==1)
+               else if (strlen(value_list)!=1)
                        output_message = strdup (_("wrong -l argument"));
                else {
                        asprintf(&send_buffer,"%s&4&%s", req_password, value_list);
@@ -188,12 +218,16 @@ int main(int argc, char **argv){
                        free_disk_space=atof(strtok(recv_buffer,"&"));
                        total_disk_space=atof(strtok(NULL,"&"));
                        percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100;
+                       warning_used_space = ((float)warning_value / 100) * total_disk_space;
+                       critical_used_space = ((float)critical_value / 100) * total_disk_space;
 
                        if (free_disk_space>=0) {
                                asprintf(&temp_string,_("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"),
-                                                                value_list, total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space,
-                                                                free_disk_space / 1073741824, (free_disk_space / total_disk_space)*100); 
-
+                                 value_list, total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824,
+                                 percent_used_space, free_disk_space / 1073741824, (free_disk_space / total_disk_space)*100);
+                               asprintf(&temp_string_perf,_("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), value_list,
+                                 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824,
+                                 critical_used_space / 1073741824, total_disk_space / 1073741824);
 
                                if(check_critical_value==TRUE && percent_used_space >= critical_value)
                                        return_code=STATE_CRITICAL;
@@ -203,8 +237,8 @@ int main(int argc, char **argv){
                                        return_code=STATE_OK;   
 
                                output_message = strdup (temp_string);
-                       }
-                       else {
+                               perfdata = temp_string_perf;
+                       else {
                                output_message = strdup (_("Free disk space : Invalid drive "));
                                return_code=STATE_UNKNOWN;
                        }
@@ -219,7 +253,7 @@ int main(int argc, char **argv){
                else {
                        preparelist(value_list);                /* replace , between services with & to send the request */
                        asprintf(&send_buffer,"%s&%u&%s&%s", req_password,(vars_to_check==CHECK_SERVICESTATE)?5:6,
-                                                        (show_all==TRUE)?_("ShowAll"):_("ShowFail"),value_list);
+                                                        (show_all==TRUE) ? "ShowAll" : "ShowFail",value_list);
                        fetch_data (server_address, server_port, send_buffer);
                        return_code=atoi(strtok(recv_buffer,"&"));
                        temp_string=strtok(NULL,"&");
@@ -234,9 +268,16 @@ int main(int argc, char **argv){
                mem_commitLimit=atof(strtok(recv_buffer,"&"));
                mem_commitByte=atof(strtok(NULL,"&"));
                percent_used_space = (mem_commitByte / mem_commitLimit) * 100;
+               warning_used_space = ((float)warning_value / 100) * mem_commitLimit;
+               critical_used_space = ((float)critical_value / 100) * mem_commitLimit;
+
+               /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here, 
+               which equals RAM + Pagefiles. */
                asprintf(&output_message,_("Memory usage: total:%.2f Mb - used: %.2f Mb (%.0f%%) - free: %.2f Mb (%.0f%%)"), 
-                       mem_commitLimit / 1048576, mem_commitByte / 1048567, percent_used_space,  
-                       (mem_commitLimit - mem_commitByte) / 1048576, (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
+                 mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space,  
+                 (mem_commitLimit - mem_commitByte) / 1048567, (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
+               asprintf(&perfdata,_("'Memory usage'=%.2fMb;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567,
+                 warning_used_space / 1048567, critical_used_space / 1048567, mem_commitLimit / 1048567);
        
                return_code=STATE_OK;
                if(check_critical_value==TRUE && percent_used_space >= critical_value)
@@ -248,39 +289,112 @@ int main(int argc, char **argv){
 
        case CHECK_COUNTER:
 
-               if (value_list==NULL)
-                       output_message = strdup (_("No counter specified"));
-               else {
-                       preparelist(value_list);                /* replace , between services with & to send the request */
-                       asprintf(&send_buffer,"%s&8&%s", req_password,value_list);
-                       fetch_data (server_address, server_port, send_buffer);
-                       strtok(value_list,"&");                 /* burn the first parameters */
-                       description = strtok(NULL,"&");
-                       counter_value = atof(recv_buffer);
 
-                       if (description == NULL) 
-                               asprintf(&output_message, "%.f", counter_value);
-                       else
-                               asprintf(&output_message,"%s = %.f",  description, counter_value);
-       
-                       if (critical_value > warning_value) {        /* Normal thresholds */
-                               if(check_critical_value==TRUE && counter_value >= critical_value)
-                                       return_code=STATE_CRITICAL;
-                               else if (check_warning_value==TRUE && counter_value >= warning_value)
-                                       return_code=STATE_WARNING;      
-                               else
-                                       return_code=STATE_OK;   
-                       } 
-                       else {                                       /* inverse thresholds */
-                               return_code=STATE_OK;
-                               if(check_critical_value==TRUE && counter_value <= critical_value)
-                                       return_code=STATE_CRITICAL;
-                               else if (check_warning_value==TRUE && counter_value <= warning_value)
-                                       return_code=STATE_WARNING;      
-                       }
+               /* 
+               CHECK_COUNTER has been modified to provide extensive perfdata information.
+                       In order to do this, some modifications have been done to the code
+                       and some constraints have been introduced.
+                       
+                       1) For the sake of simplicity of the code, perfdata information will only be 
+                        provided when the "description" field is added. 
+                       
+                       2) If the counter you're going to measure is percent-based, the code will detect
+                        the percent sign in its name and will attribute minimum (0%) and maximum (100%) 
+                        values automagically, as well the ¨%" sign to graph units.
+
+                       3) OTOH, if the counter is "absolute", you'll have to provide the following
+                        the counter unit - that is, the dimensions of the counter you're getting. Examples:
+                        pages/s, packets transferred, etc.
+
+                       4) If you want, you may provide the minimum and maximum values to expect. They aren't mandatory,
+                        but once specified they MUST have the same order of magnitude and units of -w and -c; otherwise.
+                        strange things will happen when you make graphs of your data.
+               */
+
+               if (value_list == NULL)
+                       output_message = strdup (_("No counter specified"));
+               else
+               {
+                       preparelist (value_list);       /* replace , between services with & to send the request */
+                       isPercent = (strchr (value_list, '%') != NULL);
+
+                       strtok (value_list, "&");       /* burn the first parameters */
+                       description = strtok (NULL, "&");
+                       counter_unit = strtok (NULL, "&");
+                       asprintf (&send_buffer, "%s&8&%s", req_password, value_list);
+                       fetch_data (server_address, server_port, send_buffer);
+                       counter_value = atof (recv_buffer);
+
+
+                       if (description == NULL)
+                       asprintf (&output_message, "%.f", counter_value);
+                       else if (isPercent)
+                            {  
+                               counter_unit = strdup ("%");
+                               allRight = TRUE;
+                            }
+
+                       if ((counter_unit != NULL) && (!allRight))
+                       {       
+                               minval = strtok (NULL, "&");
+                               maxval = strtok (NULL, "&");
+
+                               /* All parameters specified. Let's check the numbers */
+
+                               fminval = (minval != NULL) ? strtod (minval, &errcvt) : -1;
+                               fmaxval = (minval != NULL) ? strtod (maxval, &errcvt) : -1;
+
+                               if ((fminval == 0) && (minval == errcvt))
+                                       output_message = strdup (_("Minimum value contains non-numbers"));
+                               else
+                               {
+                                       if ((fmaxval == 0) && (maxval == errcvt))
+                                               output_message = strdup (_("Maximum value contains non-numbers"));
+                                       else
+                                               allRight = TRUE;        /* Everything is OK. */
+
+                               }
+                       }
+                       else if ((counter_unit == NULL) && (description != NULL))
+                               output_message = strdup (_("No unit counter specified"));
+
+                       if (allRight)
+                       {
+                               /* Let's format the output string, finally... */
+                                       if (strstr(description, "%") == NULL) {
+                                               asprintf (&output_message, "%s = %.2f %s",                                                                                      description, counter_value, counter_unit);
+                                       } else {
+                                               /* has formatting, will segv if wrong */
+                                       asprintf (&output_message, description, counter_value);
+                                       }
+                                       asprintf (&output_message, "%s |", output_message);
+                               asprintf (&output_message,"%s %s", output_message, 
+                                               fperfdata (description, counter_value, 
+                                                       counter_unit, 1, warning_value, 1, critical_value,
+                                                       (!(isPercent) && (minval != NULL)), fminval,
+                                                       (!(isPercent) && (minval != NULL)), fmaxval));
+                       }
                }
-               break;
 
+               if (critical_value > warning_value)
+               {                       /* Normal thresholds */
+                       if (check_critical_value == TRUE && counter_value >= critical_value)
+                            return_code = STATE_CRITICAL;
+                       else if (check_warning_value == TRUE && counter_value >= warning_value)
+                               return_code = STATE_WARNING;
+                            else
+                               return_code = STATE_OK;
+               }
+               else
+               {                       /* inverse thresholds */
+                       return_code = STATE_OK;
+                       if (check_critical_value == TRUE && counter_value <= critical_value)
+                            return_code = STATE_CRITICAL;
+                       else if (check_warning_value == TRUE && counter_value <= warning_value)
+                                   return_code = STATE_WARNING;
+               }
+        break;
+               
        case CHECK_FILEAGE:
 
                if (value_list==NULL)
@@ -314,7 +428,7 @@ int main(int argc, char **argv){
 
        case CHECK_NONE:
        default:
-               usage (_("Please specify a variable to check"));
+               usage4 (_("Please specify a variable to check"));
                break;
 
        }
@@ -322,16 +436,15 @@ int main(int argc, char **argv){
        /* reset timeout */
        alarm(0);
 
-       printf("%s\n",output_message);
-
+       if (perfdata==NULL)
+               printf("%s\n",output_message);
+       else
+               printf("%s | %s\n",output_message,perfdata);
        return return_code;
 }
 
 
 
-
-
-\f
 /* process command-line arguments */
 int process_arguments(int argc, char **argv){
        int c;
@@ -379,14 +492,12 @@ int process_arguments(int argc, char **argv){
                switch (c)
                        {
                        case '?': /* print short usage statement if args not parsable */
-                               printf("%s: Unknown argument: %s\n\n",progname,optarg);
-                               print_usage();
-                               exit(STATE_UNKNOWN);
+                       usage2 (_("Unknown argument"), optarg);
                        case 'h': /* help */
                                print_help();
                                exit(STATE_OK);
                        case 'V': /* version */
-                               print_revision(progname,"$Revision$");
+                               print_revision(progname,revision);
                                exit(STATE_OK);
                        case 'H': /* hostname */
                                if (server_address)     free(server_address);
@@ -399,7 +510,7 @@ int process_arguments(int argc, char **argv){
                                if (is_intnonneg(optarg))
                                        server_port=atoi(optarg);
                                else
-                                       die(STATE_UNKNOWN,_("Server port an integer (seconds)\nType '%s -h' for additional help\n"),progname);
+                                       die(STATE_UNKNOWN,_("Server port must be an integer\n"));
                                break;
                        case 'v':
                                if(strlen(optarg)<4)
@@ -459,16 +570,13 @@ int process_arguments(int argc, char **argv){
 
 
 
-
-
-\f
 void fetch_data (const char *address, int port, const char *sendb) {
        int result;
 
        result=process_tcp_request(address, port, sendb, recv_buffer,sizeof(recv_buffer));
 
        if(result!=STATE_OK)
-               die (result, "could not fetch information from server\n");
+               die (result, _("could not fetch information from server\n"));
                
        if (!strncmp(recv_buffer,"ERROR",5))
                die (STATE_UNKNOWN, "NSClient - %s\n",recv_buffer);
@@ -505,38 +613,43 @@ void preparelist(char *string) {
 
 
 
-
-
-\f
 void print_help(void)
 {
-       print_revision(progname,"$Revision$");
-       printf (_("\
-Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n\n\
-This plugin collects data from the NSClient service running on a\n\
-Windows NT/2000/XP server.\n\n"));
+       print_revision(progname,revision);
+       
+       printf ("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n");
+       printf (COPYRIGHT, copyright, email);
+       
+       printf ("%s\n", _("This plugin collects data from the NSClient service running on a"));
+  printf ("%s\n", _("Windows NT/2000/XP/2003 server."));
+
+  printf ("\n\n");
+  
        print_usage();
-  printf (_("\nOptions:\n\
--H, --hostname=HOST\n\
-  Name of the host to check\n\
--p, --port=INTEGER\n\
-  Optional port number (default: %d)\n\
--s <password>\n\
-  Password needed for the request\n\
--w, --warning=INTEGER\n\
-  Threshold which will result in a warning status\n\
--c, --critical=INTEGER\n\
-  Threshold which will result in a critical status\n\
--t, --timeout=INTEGER\n\
-  Seconds before connection attempt times out (default: %d)\n\
--h, --help\n\
-  Print this help screen\n\
--V, --version\n\
-  Print version information\n"),
-               PORT, DEFAULT_SOCKET_TIMEOUT);
-  printf (_("\
--v, --variable=STRING\n\
-  Variable to check.  Valid variables are:\n"));
+       
+  printf (_(UT_HELP_VRSN));
+
+  printf ("%s\n", _("Options:"));
+  printf (" %s\n", "-H, --hostname=HOST");
+  printf ("   %s\n", _("Name of the host to check"));
+  printf (" %s\n", "-p, --port=INTEGER");
+  printf ("   %s", _("Optional port number (default: "));
+  printf ("%d)\n", PORT);
+  printf (" %s\n", "-s <password>");
+  printf ("   %s\n", _("Password needed for the request"));
+  printf (" %s\n", "-w, --warning=INTEGER");
+  printf ("   %s\n", _("Threshold which will result in a warning status"));
+  printf (" %s\n", "-c, --critical=INTEGER");
+  printf ("   %s\n", _("Threshold which will result in a critical status"));
+  printf (" %s\n", "-t, --timeout=INTEGER");
+  printf ("   %s", _("Seconds before connection attempt times out (default: "));
+  printf ("%d)\n", DEFAULT_SOCKET_TIMEOUT);
+  printf (" %s\n", "-h, --help");
+  printf ("   %s\n", _("Print this help screen"));
+  printf (" %s\n", "-V, --version");
+  printf ("   %s\n", _("Print version information"));
+  printf (" %s\n", "-v, --variable=STRING");
+  printf ("   %s\n", _("Variable to check.  Valid variables are:"));
   printf (_("\
    CLIENTVERSION = Get the NSClient version\n\
      If -l <version> is specified, will return warning if versions differ.\n"));
@@ -571,23 +684,26 @@ Windows NT/2000/XP server.\n\n"));
      Request a -l parameters with the following syntax:\n\
                 -l \"\\\\<performance object>\\\\counter\",\"<description>\n\
      The <description> parameter is optional and \n\
-     is given to a printf output command which require a float parameters.\n\
+     is given to a printf output command which requires a float parameter.\n\
+     If <description> does not include \"%%\", it is used as a label.\n\
      Some examples:\n\
        \"Paging file usage is %%.2f %%%%\"\n\
        \"%%.f %%%% paging file used.\"\n"));
-       printf (_("Notes:\n\
+  printf (_("Notes:\n\
  - The NSClient service should be running on the server to get any information\n\
    (http://nsclient.ready2run.nl).\n\
- - Critical thresholds should be lower than warning thresholds\n"));
+ - Critical thresholds should be lower than warning thresholds\n\
+ - Default port 1248 is sometimes in use by other services. The error \n\
+   output when this happens contains \"Cannot map xxxxx to protocol number\". \n\
+   One fix for this is to change the port to something else on check_nt \n\
+   and on the client service it\'s connecting to. \n"));
 }
 
 
 
-
 void print_usage(void)
 {
-       printf(_("\
-Usage: %s -H host -v variable [-p port] [-w warning] [-c critical]\n\
-  [-l params] [-d SHOWALL] [-t timeout]\n"), progname);
-       printf (_(UT_HLP_VRS), progname, progname);
+  printf (_("Usage:"));
+       printf ("%s -H host -v variable [-p port] [-w warning] [-c critical]",progname);
+  printf ("[-l params] [-d SHOWALL] [-t timeout]\n");
 }