/* 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; }