Back to index

nagios-plugins  1.4.16
check_fs.c
Go to the documentation of this file.
00001 /*                                                                          
00002         Source: check_fs.c
00003         Author: Adam G. Bowen (agbowen@bealenet.com)
00004         $Revision: 1.13 $
00005         $Date: 1999/05/17 19:29:17 $
00006  
00007  * Program: Filesystem space usage plugin for NetSaint
00008  * License: GPL
00009  * Copyright (c) 1999 Adam G. Bowen (agbowen@bealenet.com)
00010  *
00011  * Description:
00012  *
00013  * This plugin will check the percent of used space in the filesystem on the
00014  * remote host at ipaddress and generate an alert if percentage is above one of
00015  * the threshold values.
00016  *
00017  * Other errors result in a STATE_UNKNOWN return.
00018  *
00019  * Command line:
00020  *
00021  * check_fs ipaddress sys_type filesystem mount_point
00022  * check_fs ipaddress sys_type filesystem mount_point <warn_%> <crit_%>
00023  *
00024  * Required input:
00025  *
00026  * ipaddress = The ipaddress of the remote system to run the check on.
00027  * sys_type = The remote system type.
00028  * filesystem = The filesystem to be checked.
00029  * mount_point = The mount point for the filesystem to be checked.
00030  *
00031  * Optional input:
00032  *
00033  * <warn_%> = Percent of used space necessary to result in a WARNING state.
00034  * <crit_%> = Percent of used space necessary to result in a CRITICAL state.
00035  *
00036  * Notes:
00037  *
00038  * If <warn_%> and <crit_%> are not passed on the command line, they will be set
00039  * to the default values in the check_fs config file.
00040  *
00041  * If the speicified filesystem does not exist, a STATE_CRITICAL is returned.
00042  *
00043  * If the speicified filesystem is not mounted, a STATE_CRITICAL is returned.
00044  * 
00045  * If the speicified filesystem is mounted to the wrong mount point, a
00046  * STATE_CRITICAL is returned.
00047  * 
00048  * sys_type is used to determine which config file to use to generate the
00049  * remote command.
00050  *
00051  * sys_type is used to determine which config file to use to generate the
00052  * remote command.
00053  *
00054  * The configuration file /usr/local/netsaint/config/check_fs/local
00055  * contains the following values:
00056  *
00057  * RSH_COMMAND|<location of rsh command on netsaint system>|
00058  * AWK_COMMAND|<location of awk command on netsaint system>|
00059  * TAIL_COMMAND|<location of tail command on netsaint system>|
00060  * TAIL_OPTIONS|<tail options need on netsaint system to retrieve info>|
00061  * WARN_PERCENT|<default warn %>|
00062  * CRITICAL_PERCENT|<default crit %>|
00063  * 
00064  * The configuration file /usr/local/netsaint/config/check_fs/<sys_type>
00065  * contains the following values:
00066  *
00067  * DF_COMMAND|<location of df command on system sys_type>|
00068  * DF_OPTIONS|<options for df command to retreive required info>|
00069  * AWK_OPTIONS|<options for awk command to retrieve required info>|
00070  *
00071  * The check_fs program expects all output to be in the following format:
00072  * filesystem;free space;% used;mount point;
00073  *
00074  * $Log: check_fs.c,v $
00075  * Revision 1.13  1999/05/17 19:29:17  netsaint
00076  * Changed the plugin to generate a different error message for each of the
00077  * following conditions:
00078  *     filesystem non-existant
00079  *     filesystem not mounted
00080  *     filesystem not mounted on correct mount point
00081  * Added a new command line paramater called mount_point.  This is the mount
00082  * point name to be checked.  If the mount point returned is not the same as
00083  * the one passed on the command line, a STATE_CRITICAL is returned.
00084  *
00085  * Revision 1.12  1999/05/17 14:35:26  netsaint
00086  * Changed the plugin to use a seperate config directory.  This directory is the
00087  * CONFIG_DIR/command_name directory.
00088  *
00089  * Revision 1.11  1999/05/14 03:01:17  netsaint
00090  * Added the following integer variable:
00091  *     socket_name
00092  * Changed the call check_net to open_socket.  Added a call to recv_socket and
00093  * close_socket.  The check_net subroutine was changed to provide more
00094  * flexibility.
00095  * Added a call to the subroutine get_command_name.
00096  * Changed the error checking routines to ensure that any error cause the
00097  * program to terminate.
00098  *
00099  * Revision 1.10  1999/05/07 15:30:26  netsaint
00100  * Removed the char variable error_buffer and the FILE *error_fp variable.
00101  * These variables are no longer needed since the printing of the error file is
00102  * handled in a subroutine.
00103  * Added a call to the check_output_file subroutine.  This routine checks the
00104  * status of the output file.  Also removed the struct stat file_stat variable.
00105  * Added a call to the check_consistency subroutine.  This subroutine checks
00106  * that the warn value is less than the critical value.
00107  *
00108  * Revision 1.9  1999/05/03 14:48:17  netsaint
00109  * Changed the config_file_prefix to config_file_fs_prefix.  Added the following
00110  * character variables:
00111  *      config_file_net_prefix
00112  *      config_file_net
00113  *      expected
00114  *      protocol
00115  * Added the following integer variables:
00116  *      result
00117  *      telnet_port
00118  * Added signal handler for the SIGALRM signal.  All these changes were to
00119  * prevent the plugin from hanging when attempting to perform check on a remote
00120  * system that is down or not working properly.  Prior to issuing the rsh
00121  * command, the plugin will attempt to establish a telnet session to the
00122  * plugin will not issue the rsh command.  Prior to establishing the telnet
00123  * connection, an alarm is set.  If the telnet connections does not return
00124  * control to the plugin before the timer expires, a SIGALRM signal will be
00125  * sent to the process which will caues the plugin to exit with a
00126  * STATE_CRITICAL error.
00127  * Added struct stat file_stat.
00128  * This is used to get the size of the out_put_file.  If the size is zero,
00129  * the plugin exits with a STATE_UNKNOWN.  Also change the error_file printing
00130  * to a subroutine in the plugins.h file.
00131  *
00132  * Revision 1.8  1999/04/28 15:01:53  netsaint
00133  * Added a </dev/null redirect of the input to the rsh command.  This was to
00134  * prevent the netsaint program from stopping when running this plugin.  Also
00135  * changed the strcat of CONFIG_DIR to the local and remote config_files to
00136  * strcpy.  This was to ensure that no leading characters were left in the
00137  * variable before adding the CONFIG_DIR location.  Changed the error checking
00138  * to ensure that a filesystem is mounted.  The df command will return the
00139  * correct information if the device in question is a file system.  However, it
00140  * will list a mount point of "" if it is not mounted.  If the filesystem is
00141  * not mounted, the plugin will return a STATE_CRITICAL.
00142  *
00143  * Revision 1.7  1999/04/23 18:59:30  netsaint
00144  * Fixed comments in source code.
00145  *
00146  * Revision 1.6  1999/04/23 18:37:01  netsaint
00147  * Changed the command line which gets passed to the system to ensure that all
00148  * error messages get redirected to the error file.
00149  *
00150  * Revision 1.5  1999/04/23 18:17:03  netsaint
00151  * Changed error messages for config file not existing.
00152  *
00153  * Revision 1.4  1999/04/23 18:14:26  netsaint
00154  * Added comments to source code.
00155  *
00156  * Revision 1.3  1999/04/23 18:07:24  netsaint
00157  * Removed the character variables total_space and used_space from plugin.
00158  * These variables are not used.  Also changed config files to remove these
00159  * varibales from the output file.
00160  *
00161  * Revision 1.2  1999/04/23 16:26:31  netsaint
00162  * Changed the pluging to use 2 config files 1 that contains local options and
00163  * 1 that contains options for the remote system.  Added the following character
00164  * variables to accomplish this:
00165  *
00166  *      config_file_prefix
00167  *      config_file_local
00168  *      config_file_remote
00169  *
00170  * config_file_local contains the following entries:
00171  *
00172  *      RSH_COMMAND
00173  *      AWK_COMMAND
00174  *      TAIL_COMMAND
00175  *      TAIL_OPTIONS
00176  *      WARN_PERCENT
00177  *      CRITICAL_PERCENT
00178  *
00179  * config_file_remote contains the following entries:
00180  *
00181  *      DF_COMMAND
00182  *      DF_OPTIONS
00183  *      AWK_OPTIONS
00184  *
00185  * Changed the character variable free_space to space_free and added 2 new
00186  * integer variable free_space and kb_per_mb.  The 2 new integers are used to
00187  * convert the avaible free space from kb to mb.
00188  *
00189  * Revision 1.1  1999/04/23 03:13:49  netsaint
00190  * Initial revision
00191  *
00192 */
00193 
00194 #include "/usr/local/src/netsaint/include/plugins.h"
00195 
00196 int main(int argc, char *argv[])
00197 {
00198   char expected[MAX_CHARS]="";
00199   char token_sep[] = ";";
00200 
00201   char awk_command[MAX_CHARS];
00202   char awk_options[MAX_CHARS];
00203   char check_fs_name[MAX_CHARS];
00204   char check_mount_point[MAX_CHARS];
00205   char command_line[MAX_CHARS];
00206   char command_name[MAX_CHARS];
00207   char config_file_local[MAX_CHARS];
00208   char config_file_remote[MAX_CHARS];
00209   char config_file_net[MAX_CHARS];
00210   char df_command[MAX_CHARS];
00211   char df_options[MAX_CHARS];
00212   char error_file[MAX_CHARS];
00213   char file_system[MAX_CHARS];
00214   char input_buffer[MAX_CHARS];
00215   char ip_address[MAX_CHARS];
00216   char mount_point[MAX_CHARS];
00217   char out_put_file[MAX_CHARS];
00218   char percent_crit[MAX_CHARS];
00219   char percent_used[MAX_CHARS];
00220   char percent_warn[MAX_CHARS];
00221   char protocol[MAX_CHARS];
00222   char port_telnet[MAX_CHARS];
00223   char rsh_command[MAX_CHARS];
00224   char space_free[MAX_CHARS];
00225   char system_name[MAX_CHARS];
00226   char tail_command[MAX_CHARS];
00227   char tail_options[MAX_CHARS];
00228 
00229   FILE *out_put_fp;
00230 
00231   int free_percent=0;
00232   int kb_per_mb=1024;
00233   int used_percent=0;
00234 
00235   int correct_fs;
00236   int correct_mp;
00237   int crit_percent;
00238   int free_space;
00239   int get_defaults;
00240   int mounted;
00241   int result;
00242   int return_value;
00243   int socket_name;
00244   int telnet_port;
00245   int warn_percent;
00246 
00247   /* Initialize alarm signal handling */
00248 
00249   signal(SIGALRM,alarm_signal);
00250 
00251   strcpy(command_name,get_command_name(argv[0]));
00252   if(!((argc==5) || (argc==7)))
00253   {
00254     printf("\n");
00255     printf(" Incorrect number of arguments supplied\n");
00256     printf("\n");
00257     printf(" Filesystem space usage plugin for NetSaint\n");
00258     printf(" Copyright (c) 1999 Adam G. Bowen (agbowen@bealenet.com)\n");
00259     printf(" $Revision: 1.13 $\n");
00260     printf(" Last Modified $Date: 1999/05/17 19:29:17 $\n");
00261     printf(" License: GPL\n");
00262     printf("\n");
00263     printf(" Description:\n");
00264     printf("\n");
00265     printf(" This plugin will check the percent of used space in the filesystem on the\n");
00266     printf(" remote host at ipaddress and generate an alert if percentage is above one of\n");
00267     printf(" the threshold values.\n");
00268     printf("\n");
00269     printf(" Usage: %s ipaddress sys_type filesystem mount_point\n",command_name);
00270     printf(" Usage: %s ipaddress sys_type filesystem  mount_point <warn_%%> <crit_%%>\n",command_name);
00271     printf("\n");
00272     printf(" Required input:\n");
00273     printf("\n");
00274     printf(" ipaddress = The ipaddress of the remote system to run the check on.\n");
00275     printf(" sys_type = The remote system type.\n");
00276     printf(" filesystem = The filesystem to be checked.\n");
00277     printf(" mount_point = The mount point for the filesystem to be checked.\n");
00278     printf("\n");
00279     printf(" Optional input:\n");
00280     printf("\n");
00281     printf(" <warn_%%> = Percent of used space necessary to result in a WARNING state.\n");
00282     printf(" <crit_%%> = Percent of used space necessary to result in a CRITICAL state.\n");
00283     printf("\n");
00284     printf(" If <warn_%%> and <crit_%%> are not passed on the command line, they will be set\n");
00285     printf(" to the default values in the %s config file.\n", command_name);
00286     printf("\n");
00287     printf(" sys_type is used to determine which config file to use to generate the\n");
00288     printf(" remote command.\n");
00289     printf("\n");
00290     return_value = STATE_UNKNOWN;
00291   }
00292   else
00293   {
00294     /* Set up config files and get the command line information */
00295 
00296     strcpy(ip_address,argv[1]);
00297     strcpy(system_name,argv[2]);
00298     strcpy(check_fs_name,argv[3]);
00299     strcpy(check_mount_point,argv[4]);
00300 
00301     strcpy(config_file_local,CONFIG_DIR);
00302     strcpy(config_file_remote,CONFIG_DIR);
00303     strcpy(config_file_net,CONFIG_DIR);
00304     strcat(config_file_local,command_name);
00305     strcat(config_file_remote,command_name);
00306     strcat(config_file_net,CHECK_TELNET);
00307     strcat(config_file_local,"/local");
00308     strcat(config_file_remote,"/");
00309     strcat(config_file_net,"/");
00310     strcat(config_file_remote,system_name);
00311     strcat(config_file_net,system_name);
00312 
00313     if(argc == 5)
00314     {
00315       get_defaults = TRUE;
00316     }
00317     else
00318     {
00319       get_defaults = FALSE;
00320       strcpy(percent_warn,argv[4]);
00321       strcpy(percent_crit,argv[5]);
00322     }
00323 
00324     /* Check if config files exist */
00325 
00326     if (access(config_file_local, EXISTS) != 0 )
00327     {
00328       printf("Config file %s does not exist!\n",config_file_local);
00329       return_value = STATE_UNKNOWN;
00330     }
00331     else if (access(config_file_remote, EXISTS) != 0 )
00332     {
00333       printf("Config file %s does not exist!\n",config_file_remote);
00334       return_value = STATE_UNKNOWN;
00335     }
00336     else if (access(config_file_net, EXISTS) != 0 )
00337     {
00338       printf("Config file %s does not exist!\n",config_file_net);
00339       return_value = STATE_UNKNOWN;
00340     }
00341     else
00342     {
00343 
00344       /* Local config file variables */
00345 
00346       if((get_defaults == TRUE) && ((return_value=get_var("WARN_PERCENT", config_file_local, percent_warn)) != STATE_OK))
00347       {
00348         printf("WARN_PERCENT entry not found in config file %s!\n",config_file_local);
00349       }
00350       else if((get_defaults == TRUE) && ((return_value=get_var("CRITICAL_PERCENT", config_file_local, percent_crit)) != STATE_OK))
00351       {
00352         printf("CRITICAL_PERCENT entry not found in config file %s!\n",config_file_local);
00353       }
00354       else if((return_value=get_var("RSH_COMMAND", config_file_local, rsh_command)) != STATE_OK)
00355       {
00356         printf("RSH_COMMAND entry not found in config file %s!\n", config_file_local);
00357       }
00358       else if((return_value=get_var("AWK_COMMAND", config_file_local, awk_command)) != STATE_OK)
00359       {
00360         printf("AWK_COMMAND entry not found in config file %s!\n", config_file_local);
00361       }
00362       else if((return_value=get_var("TAIL_COMMAND", config_file_local, tail_command)) != STATE_OK)
00363       {
00364         printf("TAIL_COMMAND entry not found in config file %s!\n", config_file_local);
00365       }
00366       else if((return_value=get_var("TAIL_OPTIONS", config_file_local, tail_options)) != STATE_OK)
00367       {
00368         printf("TAIL_OPTIONS entry not found in config file %s!\n", config_file_local);
00369       }
00370 
00371       /* Remote config file variables */
00372 
00373       else if((return_value=get_var("DF_COMMAND", config_file_remote, df_command)) != STATE_OK)
00374       {
00375         printf("DF_COMMAND entry not found in config file %s!\n", config_file_remote);
00376       }
00377       else if((return_value=get_var("DF_OPTIONS", config_file_remote, df_options)) != STATE_OK)
00378       {
00379         printf("DF_OPTIONS entry not found in config file %s!\n",config_file_remote);
00380       }
00381       else if((return_value=get_var("AWK_OPTIONS", config_file_remote, awk_options)) != STATE_OK)
00382       {
00383         printf("AWK_OPTIONS entry not found in config file %s!\n",config_file_remote);
00384       }
00385 
00386       /* Network config file variables */
00387 
00388       else if((return_value=get_var("TELNET_PORT", config_file_net, port_telnet)) != STATE_OK)
00389       {
00390         printf("TELNET_PORT entry not found in config file %s!\n",config_file_net);
00391       }
00392       else if((return_value=get_var("TELNET_PROTO", config_file_net, protocol)) != STATE_OK)
00393       {
00394         printf("TELNET_PROTO entry not found in config file %s!\n",config_file_net);
00395       }
00396       else
00397       {
00398 
00399         /* Check alert level consistency */
00400 
00401         warn_percent=atoi(percent_warn);
00402         crit_percent=atoi(percent_crit);
00403         return_value = check_consistency(warn_percent, crit_percent);
00404         if(return_value == STATE_OK)
00405         {
00406 
00407           /* Check the network */
00408 
00409           telnet_port=atoi(port_telnet);
00410           alarm(TIME_OUT);
00411           if((result=open_socket(&socket_name, ip_address, telnet_port, protocol)) != STATE_OK)
00412           {
00413             return_value=exit_error(result,ip_address,protocol,telnet_port);
00414           }
00415           else if((result=recv_socket(&socket_name, expected)) != STATE_OK)
00416           {
00417             return_value=exit_error(result,ip_address,protocol,telnet_port);
00418           }
00419           else if((result=close_socket(&socket_name)) != STATE_OK)
00420           {
00421             return_value=exit_error(result,ip_address,protocol,telnet_port);
00422           }
00423           else
00424           {
00425             alarm(0);
00426 
00427             /* Generate a out_put and error file names */
00428 
00429             strcpy(out_put_file, tmpnam(NULL));
00430             strcpy(error_file, tmpnam(NULL));
00431 
00432             /* set the command line and arguments to use for the check */
00433 
00434             sprintf(command_line,"%s %s %s %s %s </dev/null 2>%s|%s %s 2>>%s|%s %s > %s 2>>%s",rsh_command, ip_address, df_command, df_options, check_fs_name, error_file, tail_command, tail_options, error_file, awk_command, awk_options, out_put_file, error_file);
00435 
00436             /* Run the command */
00437 
00438             system(command_line);
00439 
00440             return_value=check_output_file(out_put_file);
00441             if (return_value != STATE_OK)
00442             {
00443               print_error(error_file);
00444             }
00445             else
00446             {
00447               out_put_fp=fopen(out_put_file,"r");
00448 
00449               /* Retrive single line from output file */
00450 
00451               fgets(input_buffer,MAX_CHARS-1,out_put_fp);
00452 
00453               /* close output file */
00454 
00455               fclose(out_put_fp);
00456 
00457               /* Populate variables */
00458 
00459               strcpy(file_system,strtok(input_buffer,token_sep));
00460               strcpy(space_free,strtok(NULL,token_sep));
00461               strcpy(percent_used,strtok(NULL,token_sep));
00462               strcpy(mount_point,strtok(NULL,token_sep));
00463 
00464               /* Test if file_system has correct name and mount point*/
00465 
00466               if(strcmp(file_system,check_fs_name) == 0)
00467               {
00468                 correct_fs = TRUE;
00469                 if(strcmp(mount_point,"\n") != 0)
00470                 {
00471                   mounted = TRUE;
00472                   if(strcmp(mount_point,check_mount_point) == 0)
00473                   {
00474                     correct_mp = TRUE;
00475                   }
00476                   else
00477                   {
00478                     correct_mp = FALSE;
00479                   }
00480                 }
00481                 else
00482                 {
00483                   mounted = FALSE;
00484                   correct_mp = FALSE;
00485                 }
00486               }
00487               else
00488               {
00489                 correct_fs = FALSE;
00490                 mounted = FALSE;
00491                 correct_mp = FALSE;
00492               }
00493 
00494               /* If the file system name is not correct, return a CRITICAL */
00495 
00496               if(!correct_fs)
00497               {
00498                 printf("Filesystem %s not nonexistant!  ",check_fs_name);
00499 
00500                 /* Check for the existance of an error file */
00501 
00502                 print_error(error_file);
00503 
00504                 return_value = STATE_CRITICAL;
00505               }
00506               else if(!mounted)
00507               {
00508                 printf("Filesystem %s not mounted!  ",check_fs_name);
00509 
00510                 /* Check for the existance of an error file */
00511 
00512                 print_error(error_file);
00513 
00514                 return_value = STATE_CRITICAL;
00515               }
00516               else if(!correct_mp)
00517               {
00518                 printf("Filesystem %s mounted on %s not %s!  ",check_fs_name, mount_point, check_mount_point);
00519 
00520                 /* Check for the existance of an error file */
00521 
00522                 print_error(error_file);
00523 
00524                 return_value = STATE_CRITICAL;
00525               }
00526               else
00527               {
00528                 /* Convert free space from kb to mb */
00529 
00530                 free_space=atoi(space_free);
00531                 free_space=free_space/kb_per_mb;
00532 
00533                 /* Determine free percent */
00534 
00535                 used_percent=atoi(percent_used);
00536                 free_percent=100 - used_percent;
00537 
00538                 /* Check the percent used space against warn and crit levels */
00539 
00540                 if(used_percent>=crit_percent)
00541                 {
00542                   return_value=STATE_CRITICAL;
00543                 }
00544                 else if(used_percent>=warn_percent)
00545                 {
00546                   return_value=STATE_WARNING;
00547                 }
00548 
00549                 if(return_value==STATE_OK)
00550                 {
00551                   printf("Filesystem %s mounted on %s ok - %d mb (%d%%) space free.\n",file_system,mount_point,free_space,free_percent);
00552                 }
00553                 else
00554                 {
00555                   printf("Filesystem %s mounted on %s is down to %d mb (%d%%) space free.\n",file_system,mount_point,free_space,free_percent);
00556                 }
00557               }
00558             }
00559 
00560             /* Remove output and error files before leaving */
00561 
00562             remove(out_put_file);
00563             remove(error_file);
00564           }
00565         }
00566       }
00567     }
00568   }
00569   return return_value;
00570 }