Back to index

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