Logo Search packages:      
Sourcecode: nagios-plugins version File versions

check_fs.c

/*                                                                          
        Source: check_fs.c
        Author: Adam G. Bowen (agbowen@bealenet.com)
        $Revision: 1.13 $
        $Date: 1999/05/17 19:29:17 $
 
 * Program: Filesystem space usage plugin for NetSaint
 * License: GPL
 * Copyright (c) 1999 Adam G. Bowen (agbowen@bealenet.com)
 *
 * Description:
 *
 * This plugin will check the percent of used space in the filesystem on the
 * remote host at ipaddress and generate an alert if percentage is above one of
 * the threshold values.
 *
 * Other errors result in a STATE_UNKNOWN return.
 *
 * Command line:
 *
 * check_fs ipaddress sys_type filesystem mount_point
 * check_fs ipaddress sys_type filesystem mount_point <warn_%> <crit_%>
 *
 * Required input:
 *
 * ipaddress = The ipaddress of the remote system to run the check on.
 * sys_type = The remote system type.
 * filesystem = The filesystem to be checked.
 * mount_point = The mount point for the filesystem to be checked.
 *
 * Optional input:
 *
 * <warn_%> = Percent of used space necessary to result in a WARNING state.
 * <crit_%> = Percent of used space necessary to result in a CRITICAL state.
 *
 * Notes:
 *
 * If <warn_%> and <crit_%> are not passed on the command line, they will be set
 * to the default values in the check_fs config file.
 *
 * If the speicified filesystem does not exist, a STATE_CRITICAL is returned.
 *
 * If the speicified filesystem is not mounted, a STATE_CRITICAL is returned.
 * 
 * If the speicified filesystem is mounted to the wrong mount point, a
 * STATE_CRITICAL is returned.
 * 
 * sys_type is used to determine which config file to use to generate the
 * remote command.
 *
 * sys_type is used to determine which config file to use to generate the
 * remote command.
 *
 * The configuration file /usr/local/netsaint/config/check_fs/local
 * contains the following values:
 *
 * RSH_COMMAND|<location of rsh command on netsaint system>|
 * AWK_COMMAND|<location of awk command on netsaint system>|
 * TAIL_COMMAND|<location of tail command on netsaint system>|
 * TAIL_OPTIONS|<tail options need on netsaint system to retrieve info>|
 * WARN_PERCENT|<default warn %>|
 * CRITICAL_PERCENT|<default crit %>|
 * 
 * The configuration file /usr/local/netsaint/config/check_fs/<sys_type>
 * contains the following values:
 *
 * DF_COMMAND|<location of df command on system sys_type>|
 * DF_OPTIONS|<options for df command to retreive required info>|
 * AWK_OPTIONS|<options for awk command to retrieve required info>|
 *
 * The check_fs program expects all output to be in the following format:
 * filesystem;free space;% used;mount point;
 *
 * $Log: check_fs.c,v $
 * Revision 1.13  1999/05/17 19:29:17  netsaint
 * Changed the plugin to generate a different error message for each of the
 * following conditions:
 *    filesystem non-existant
 *    filesystem not mounted
 *    filesystem not mounted on correct mount point
 * Added a new command line paramater called mount_point.  This is the mount
 * point name to be checked.  If the mount point returned is not the same as
 * the one passed on the command line, a STATE_CRITICAL is returned.
 *
 * Revision 1.12  1999/05/17 14:35:26  netsaint
 * Changed the plugin to use a seperate config directory.  This directory is the
 * CONFIG_DIR/command_name directory.
 *
 * Revision 1.11  1999/05/14 03:01:17  netsaint
 * Added the following integer variable:
 *    socket_name
 * Changed the call check_net to open_socket.  Added a call to recv_socket and
 * close_socket.  The check_net subroutine was changed to provide more
 * flexibility.
 * Added a call to the subroutine get_command_name.
 * Changed the error checking routines to ensure that any error cause the
 * program to terminate.
 *
 * Revision 1.10  1999/05/07 15:30:26  netsaint
 * Removed the char variable error_buffer and the FILE *error_fp variable.
 * These variables are no longer needed since the printing of the error file is
 * handled in a subroutine.
 * Added a call to the check_output_file subroutine.  This routine checks the
 * status of the output file.  Also removed the struct stat file_stat variable.
 * Added a call to the check_consistency subroutine.  This subroutine checks
 * that the warn value is less than the critical value.
 *
 * Revision 1.9  1999/05/03 14:48:17  netsaint
 * Changed the config_file_prefix to config_file_fs_prefix.  Added the following
 * character variables:
 *      config_file_net_prefix
 *      config_file_net
 *      expected
 *      protocol
 * Added the following integer variables:
 *      result
 *      telnet_port
 * Added signal handler for the SIGALRM signal.  All these changes were to
 * prevent the plugin from hanging when attempting to perform check on a remote
 * system that is down or not working properly.  Prior to issuing the rsh
 * command, the plugin will attempt to establish a telnet session to the
 * plugin will not issue the rsh command.  Prior to establishing the telnet
 * connection, an alarm is set.  If the telnet connections does not return
 * control to the plugin before the timer expires, a SIGALRM signal will be
 * sent to the process which will caues the plugin to exit with a
 * STATE_CRITICAL error.
 * Added struct stat file_stat.
 * This is used to get the size of the out_put_file.  If the size is zero,
 * the plugin exits with a STATE_UNKNOWN.  Also change the error_file printing
 * to a subroutine in the plugins.h file.
 *
 * Revision 1.8  1999/04/28 15:01:53  netsaint
 * Added a </dev/null redirect of the input to the rsh command.  This was to
 * prevent the netsaint program from stopping when running this plugin.  Also
 * changed the strcat of CONFIG_DIR to the local and remote config_files to
 * strcpy.  This was to ensure that no leading characters were left in the
 * variable before adding the CONFIG_DIR location.  Changed the error checking
 * to ensure that a filesystem is mounted.  The df command will return the
 * correct information if the device in question is a file system.  However, it
 * will list a mount point of "" if it is not mounted.  If the filesystem is
 * not mounted, the plugin will return a STATE_CRITICAL.
 *
 * Revision 1.7  1999/04/23 18:59:30  netsaint
 * Fixed comments in source code.
 *
 * Revision 1.6  1999/04/23 18:37:01  netsaint
 * Changed the command line which gets passed to the system to ensure that all
 * error messages get redirected to the error file.
 *
 * Revision 1.5  1999/04/23 18:17:03  netsaint
 * Changed error messages for config file not existing.
 *
 * Revision 1.4  1999/04/23 18:14:26  netsaint
 * Added comments to source code.
 *
 * Revision 1.3  1999/04/23 18:07:24  netsaint
 * Removed the character variables total_space and used_space from plugin.
 * These variables are not used.  Also changed config files to remove these
 * varibales from the output file.
 *
 * Revision 1.2  1999/04/23 16:26:31  netsaint
 * Changed the pluging to use 2 config files 1 that contains local options and
 * 1 that contains options for the remote system.  Added the following character
 * variables to accomplish this:
 *
 *      config_file_prefix
 *      config_file_local
 *      config_file_remote
 *
 * config_file_local contains the following entries:
 *
 *      RSH_COMMAND
 *      AWK_COMMAND
 *      TAIL_COMMAND
 *      TAIL_OPTIONS
 *      WARN_PERCENT
 *      CRITICAL_PERCENT
 *
 * config_file_remote contains the following entries:
 *
 *      DF_COMMAND
 *      DF_OPTIONS
 *      AWK_OPTIONS
 *
 * Changed the character variable free_space to space_free and added 2 new
 * integer variable free_space and kb_per_mb.  The 2 new integers are used to
 * convert the avaible free space from kb to mb.
 *
 * Revision 1.1  1999/04/23 03:13:49  netsaint
 * Initial revision
 *
*/

#include "/usr/local/src/netsaint/include/plugins.h"

int main(int argc, char *argv[])
{
  char expected[MAX_CHARS]="";
  char token_sep[] = ";";

  char awk_command[MAX_CHARS];
  char awk_options[MAX_CHARS];
  char check_fs_name[MAX_CHARS];
  char check_mount_point[MAX_CHARS];
  char command_line[MAX_CHARS];
  char command_name[MAX_CHARS];
  char config_file_local[MAX_CHARS];
  char config_file_remote[MAX_CHARS];
  char config_file_net[MAX_CHARS];
  char df_command[MAX_CHARS];
  char df_options[MAX_CHARS];
  char error_file[MAX_CHARS];
  char file_system[MAX_CHARS];
  char input_buffer[MAX_CHARS];
  char ip_address[MAX_CHARS];
  char mount_point[MAX_CHARS];
  char out_put_file[MAX_CHARS];
  char percent_crit[MAX_CHARS];
  char percent_used[MAX_CHARS];
  char percent_warn[MAX_CHARS];
  char protocol[MAX_CHARS];
  char port_telnet[MAX_CHARS];
  char rsh_command[MAX_CHARS];
  char space_free[MAX_CHARS];
  char system_name[MAX_CHARS];
  char tail_command[MAX_CHARS];
  char tail_options[MAX_CHARS];

  FILE *out_put_fp;

  int free_percent=0;
  int kb_per_mb=1024;
  int used_percent=0;

  int correct_fs;
  int correct_mp;
  int crit_percent;
  int free_space;
  int get_defaults;
  int mounted;
  int result;
  int return_value;
  int socket_name;
  int telnet_port;
  int warn_percent;

  /* Initialize alarm signal handling */

  signal(SIGALRM,alarm_signal);

  strcpy(command_name,get_command_name(argv[0]));
  if(!((argc==5) || (argc==7)))
  {
    printf("\n");
    printf(" Incorrect number of arguments supplied\n");
    printf("\n");
    printf(" Filesystem space usage plugin for NetSaint\n");
    printf(" Copyright (c) 1999 Adam G. Bowen (agbowen@bealenet.com)\n");
    printf(" $Revision: 1.13 $\n");
    printf(" Last Modified $Date: 1999/05/17 19:29:17 $\n");
    printf(" License: GPL\n");
    printf("\n");
    printf(" Description:\n");
    printf("\n");
    printf(" This plugin will check the percent of used space in the filesystem on the\n");
    printf(" remote host at ipaddress and generate an alert if percentage is above one of\n");
    printf(" the threshold values.\n");
    printf("\n");
    printf(" Usage: %s ipaddress sys_type filesystem mount_point\n",command_name);
    printf(" Usage: %s ipaddress sys_type filesystem  mount_point <warn_%%> <crit_%%>\n",command_name);
    printf("\n");
    printf(" Required input:\n");
    printf("\n");
    printf(" ipaddress = The ipaddress of the remote system to run the check on.\n");
    printf(" sys_type = The remote system type.\n");
    printf(" filesystem = The filesystem to be checked.\n");
    printf(" mount_point = The mount point for the filesystem to be checked.\n");
    printf("\n");
    printf(" Optional input:\n");
    printf("\n");
    printf(" <warn_%%> = Percent of used space necessary to result in a WARNING state.\n");
    printf(" <crit_%%> = Percent of used space necessary to result in a CRITICAL state.\n");
    printf("\n");
    printf(" If <warn_%%> and <crit_%%> are not passed on the command line, they will be set\n");
    printf(" to the default values in the %s config file.\n", command_name);
    printf("\n");
    printf(" sys_type is used to determine which config file to use to generate the\n");
    printf(" remote command.\n");
    printf("\n");
    return_value = STATE_UNKNOWN;
  }
  else
  {
    /* Set up config files and get the command line information */

    strcpy(ip_address,argv[1]);
    strcpy(system_name,argv[2]);
    strcpy(check_fs_name,argv[3]);
    strcpy(check_mount_point,argv[4]);

    strcpy(config_file_local,CONFIG_DIR);
    strcpy(config_file_remote,CONFIG_DIR);
    strcpy(config_file_net,CONFIG_DIR);
    strcat(config_file_local,command_name);
    strcat(config_file_remote,command_name);
    strcat(config_file_net,CHECK_TELNET);
    strcat(config_file_local,"/local");
    strcat(config_file_remote,"/");
    strcat(config_file_net,"/");
    strcat(config_file_remote,system_name);
    strcat(config_file_net,system_name);

    if(argc == 5)
    {
      get_defaults = TRUE;
    }
    else
    {
      get_defaults = FALSE;
      strcpy(percent_warn,argv[4]);
      strcpy(percent_crit,argv[5]);
    }

    /* Check if config files exist */

    if (access(config_file_local, EXISTS) != 0 )
    {
      printf("Config file %s does not exist!\n",config_file_local);
      return_value = STATE_UNKNOWN;
    }
    else if (access(config_file_remote, EXISTS) != 0 )
    {
      printf("Config file %s does not exist!\n",config_file_remote);
      return_value = STATE_UNKNOWN;
    }
    else if (access(config_file_net, EXISTS) != 0 )
    {
      printf("Config file %s does not exist!\n",config_file_net);
      return_value = STATE_UNKNOWN;
    }
    else
    {

      /* Local config file variables */

      if((get_defaults == TRUE) && ((return_value=get_var("WARN_PERCENT", config_file_local, percent_warn)) != STATE_OK))
      {
        printf("WARN_PERCENT entry not found in config file %s!\n",config_file_local);
      }
      else if((get_defaults == TRUE) && ((return_value=get_var("CRITICAL_PERCENT", config_file_local, percent_crit)) != STATE_OK))
      {
        printf("CRITICAL_PERCENT entry not found in config file %s!\n",config_file_local);
      }
      else if((return_value=get_var("RSH_COMMAND", config_file_local, rsh_command)) != STATE_OK)
      {
        printf("RSH_COMMAND entry not found in config file %s!\n", config_file_local);
      }
      else if((return_value=get_var("AWK_COMMAND", config_file_local, awk_command)) != STATE_OK)
      {
        printf("AWK_COMMAND entry not found in config file %s!\n", config_file_local);
      }
      else if((return_value=get_var("TAIL_COMMAND", config_file_local, tail_command)) != STATE_OK)
      {
        printf("TAIL_COMMAND entry not found in config file %s!\n", config_file_local);
      }
      else if((return_value=get_var("TAIL_OPTIONS", config_file_local, tail_options)) != STATE_OK)
      {
        printf("TAIL_OPTIONS entry not found in config file %s!\n", config_file_local);
      }

      /* Remote config file variables */

      else if((return_value=get_var("DF_COMMAND", config_file_remote, df_command)) != STATE_OK)
      {
        printf("DF_COMMAND entry not found in config file %s!\n", config_file_remote);
      }
      else if((return_value=get_var("DF_OPTIONS", config_file_remote, df_options)) != STATE_OK)
      {
        printf("DF_OPTIONS entry not found in config file %s!\n",config_file_remote);
      }
      else if((return_value=get_var("AWK_OPTIONS", config_file_remote, awk_options)) != STATE_OK)
      {
        printf("AWK_OPTIONS entry not found in config file %s!\n",config_file_remote);
      }

      /* Network config file variables */

      else if((return_value=get_var("TELNET_PORT", config_file_net, port_telnet)) != STATE_OK)
      {
        printf("TELNET_PORT entry not found in config file %s!\n",config_file_net);
      }
      else if((return_value=get_var("TELNET_PROTO", config_file_net, protocol)) != STATE_OK)
      {
        printf("TELNET_PROTO entry not found in config file %s!\n",config_file_net);
      }
      else
      {

        /* Check alert level consistency */

        warn_percent=atoi(percent_warn);
        crit_percent=atoi(percent_crit);
        return_value = check_consistency(warn_percent, crit_percent);
        if(return_value == STATE_OK)
        {

          /* Check the network */

          telnet_port=atoi(port_telnet);
          alarm(TIME_OUT);
          if((result=open_socket(&socket_name, ip_address, telnet_port, protocol)) != STATE_OK)
          {
            return_value=exit_error(result,ip_address,protocol,telnet_port);
          }
          else if((result=recv_socket(&socket_name, expected)) != STATE_OK)
          {
            return_value=exit_error(result,ip_address,protocol,telnet_port);
          }
          else if((result=close_socket(&socket_name)) != STATE_OK)
          {
            return_value=exit_error(result,ip_address,protocol,telnet_port);
          }
          else
          {
            alarm(0);

            /* Generate a out_put and error file names */

            strcpy(out_put_file, tmpnam(NULL));
            strcpy(error_file, tmpnam(NULL));

            /* set the command line and arguments to use for the check */

            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);

            /* Run the command */

            system(command_line);

            return_value=check_output_file(out_put_file);
            if (return_value != STATE_OK)
            {
              print_error(error_file);
            }
            else
            {
              out_put_fp=fopen(out_put_file,"r");

              /* Retrive single line from output file */

              fgets(input_buffer,MAX_CHARS-1,out_put_fp);

              /* close output file */

              fclose(out_put_fp);

              /* Populate variables */

              strcpy(file_system,strtok(input_buffer,token_sep));
              strcpy(space_free,strtok(NULL,token_sep));
              strcpy(percent_used,strtok(NULL,token_sep));
              strcpy(mount_point,strtok(NULL,token_sep));

              /* Test if file_system has correct name and mount point*/

              if(strcmp(file_system,check_fs_name) == 0)
              {
                correct_fs = TRUE;
                if(strcmp(mount_point,"\n") != 0)
                {
                  mounted = TRUE;
                  if(strcmp(mount_point,check_mount_point) == 0)
                  {
                    correct_mp = TRUE;
                  }
                  else
                  {
                    correct_mp = FALSE;
                  }
                }
                else
                {
                  mounted = FALSE;
                  correct_mp = FALSE;
                }
              }
              else
              {
                correct_fs = FALSE;
                mounted = FALSE;
                correct_mp = FALSE;
              }

              /* If the file system name is not correct, return a CRITICAL */

              if(!correct_fs)
              {
                printf("Filesystem %s not nonexistant!  ",check_fs_name);

                /* Check for the existance of an error file */

                print_error(error_file);

                return_value = STATE_CRITICAL;
              }
              else if(!mounted)
              {
                printf("Filesystem %s not mounted!  ",check_fs_name);

                /* Check for the existance of an error file */

                print_error(error_file);

                return_value = STATE_CRITICAL;
              }
              else if(!correct_mp)
              {
                printf("Filesystem %s mounted on %s not %s!  ",check_fs_name, mount_point, check_mount_point);

                /* Check for the existance of an error file */

                print_error(error_file);

                return_value = STATE_CRITICAL;
              }
              else
              {
                /* Convert free space from kb to mb */

                free_space=atoi(space_free);
                free_space=free_space/kb_per_mb;

                /* Determine free percent */

                used_percent=atoi(percent_used);
                free_percent=100 - used_percent;

                /* Check the percent used space against warn and crit levels */

                if(used_percent>=crit_percent)
                {
                  return_value=STATE_CRITICAL;
                }
                else if(used_percent>=warn_percent)
                {
                  return_value=STATE_WARNING;
                }

                if(return_value==STATE_OK)
                {
                  printf("Filesystem %s mounted on %s ok - %d mb (%d%%) space free.\n",file_system,mount_point,free_space,free_percent);
                }
                else
                {
                  printf("Filesystem %s mounted on %s is down to %d mb (%d%%) space free.\n",file_system,mount_point,free_space,free_percent);
                }
              }
            }

            /* Remove output and error files before leaving */

            remove(out_put_file);
            remove(error_file);
          }
        }
      }
    }
  }
  return return_value;
}

Generated by  Doxygen 1.6.0   Back to index