Example #1
0
/*
 * _init_ipmi_config initializes parameters for freeipmi library
 */
static int _init_ipmi_config (void)
{
	int errnum;
	/* Initialization flags
	 * Most commonly bitwise OR IPMI_MONITORING_FLAGS_DEBUG and/or
	 * IPMI_MONITORING_FLAGS_DEBUG_IPMI_PACKETS for extra debugging
	 * information.
	 */
	unsigned int ipmimonitoring_init_flags = 0;
	memset(&ipmi_config, 0, sizeof(struct ipmi_monitoring_ipmi_config));
	ipmi_config.driver_type = (int) slurm_ipmi_conf.driver_type;
	ipmi_config.disable_auto_probe =
		(int) slurm_ipmi_conf.disable_auto_probe;
	ipmi_config.driver_address =
		(unsigned int) slurm_ipmi_conf.driver_address;
	ipmi_config.register_spacing =
		(unsigned int) slurm_ipmi_conf.register_spacing;
	ipmi_config.driver_device = slurm_ipmi_conf.driver_device;
	ipmi_config.protocol_version = (int) slurm_ipmi_conf.protocol_version;
	ipmi_config.username = slurm_ipmi_conf.username;
	ipmi_config.password = slurm_ipmi_conf.password;
	ipmi_config.k_g = slurm_ipmi_conf.k_g;
	ipmi_config.k_g_len = (unsigned int) slurm_ipmi_conf.k_g_len;
	ipmi_config.privilege_level = (int) slurm_ipmi_conf.privilege_level;
	ipmi_config.authentication_type =
		(int) slurm_ipmi_conf.authentication_type;
	ipmi_config.cipher_suite_id = (int) slurm_ipmi_conf.cipher_suite_id;
	ipmi_config.session_timeout_len = (int) slurm_ipmi_conf.session_timeout;
	ipmi_config.retransmission_timeout_len =
		(int) slurm_ipmi_conf.retransmission_timeout;
	ipmi_config.workaround_flags =
		(unsigned int) slurm_ipmi_conf.workaround_flags;

	if (ipmi_monitoring_init(ipmimonitoring_init_flags, &errnum) < 0) {
		error("ipmi_monitoring_init: %s",
		      ipmi_monitoring_ctx_strerror(errnum));
		return SLURM_FAILURE;
	}
	if (!(ipmi_ctx = ipmi_monitoring_ctx_create())) {
		error("ipmi_monitoring_ctx_create");
		return SLURM_FAILURE;
	}
	if (sdr_cache_directory) {
		if (ipmi_monitoring_ctx_sdr_cache_directory(
			    ipmi_ctx, sdr_cache_directory) < 0) {
			error("ipmi_monitoring_ctx_sdr_cache_directory: %s",
			      ipmi_monitoring_ctx_errormsg(ipmi_ctx));
			return SLURM_FAILURE;
		}
	}
	/* Must call otherwise only default interpretations ever used */
	if (ipmi_monitoring_ctx_sensor_config_file(
		    ipmi_ctx, sensor_config_file) < 0) {
		error("ipmi_monitoring_ctx_sensor_config_file: %s",
		      ipmi_monitoring_ctx_errormsg(ipmi_ctx));
		return SLURM_FAILURE;
	}

	if (slurm_ipmi_conf.reread_sdr_cache)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_REREAD_SDR_CACHE;
	if (slurm_ipmi_conf.ignore_non_interpretable_sensors)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_NON_INTERPRETABLE_SENSORS;
	if (slurm_ipmi_conf.bridge_sensors)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_BRIDGE_SENSORS;
	if (slurm_ipmi_conf.interpret_oem_data)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_INTERPRET_OEM_DATA;
	if (slurm_ipmi_conf.shared_sensors)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_SHARED_SENSORS;
	if (slurm_ipmi_conf.discrete_reading)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_DISCRETE_READING;
	if (slurm_ipmi_conf.ignore_scanning_disabled)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_SCANNING_DISABLED;
	if (slurm_ipmi_conf.assume_bmc_owner)
		sensor_reading_flags |=
			IPMI_MONITORING_SENSOR_READING_FLAGS_ASSUME_BMC_OWNER;
	/* FIXME: This is not included until later versions of IPMI, so don't
	   always have it.
	*/
	/* if (slurm_ipmi_conf.entity_sensor_names) */
	/* 	sensor_reading_flags |= */
	/* 		IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES; */

	return SLURM_SUCCESS;
}
static int
_ipmimonitoring (struct ipmi_monitoring_ipmi_config *ipmi_config)
{
  ipmi_monitoring_ctx_t ctx = NULL;
  unsigned int sel_flags = 0;
  unsigned int i;
  int sel_count;
  int errnum;
  int rv = -1;

  if (ipmi_monitoring_init (ipmimonitoring_init_flags, &errnum) < 0)
    {
      fprintf (stderr,
               "ipmi_monitoring_init: %s\n",
               ipmi_monitoring_ctx_strerror (errnum));
      goto cleanup;
    }

  if (!(ctx = ipmi_monitoring_ctx_create ()))
    {
      perror ("ipmi_monitoring_ctx_create:");
      goto cleanup;
    }

  if (sdr_cache_directory)
    {
      if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
                                                   sdr_cache_directory) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_ctx_sdr_cache_directory: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }

  /* Must call otherwise only default interpretations ever used */
  if (sel_config_file)
    {
      if (ipmi_monitoring_ctx_sel_config_file (ctx,
                                               sel_config_file) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_ctx_sel_config_file: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  else
    {
      if (ipmi_monitoring_ctx_sel_config_file (ctx, NULL) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_ctx_sel_config_file: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  
  if (reread_sdr_cache)
    sel_flags |= IPMI_MONITORING_SEL_FLAGS_REREAD_SDR_CACHE;

  if (interpret_oem_data)
    sel_flags |= IPMI_MONITORING_SEL_FLAGS_INTERPRET_OEM_DATA;

  if (assume_system_event_record)
    sel_flags |= IPMI_MONITORING_SEL_FLAGS_ASSUME_SYSTEM_EVENT_RECORD;

  if (entity_sensor_names)
    sel_flags |= IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES;

  if (record_ids_length)
    {
      if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
                                                         hostname,
                                                         ipmi_config,
                                                         sel_flags,
                                                         record_ids,
                                                         record_ids_length,
                                                         NULL,
                                                         NULL)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_by_record_id: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  else if (sensor_types_length)
    {
      if ((sel_count = ipmi_monitoring_sel_by_sensor_type (ctx,
                                                           hostname,
                                                           ipmi_config,
                                                           sel_flags,
                                                           sensor_types,
                                                           sensor_types_length,
                                                           NULL,
                                                           NULL)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_by_sensor_type: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  else if (date_begin
           || date_end)
    {
      if ((sel_count = ipmi_monitoring_sel_by_date_range (ctx,
                                                          hostname,
                                                          ipmi_config,
                                                          sel_flags,
                                                          date_begin,
                                                          date_end,
                                                          NULL,
                                                          NULL)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_by_sensor_type: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  else
    {
      if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
                                                         hostname,
                                                         ipmi_config,
                                                         sel_flags,
                                                         NULL,
                                                         0,
                                                         NULL,
                                                         NULL)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_by_record_id: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }

  printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
          "Record ID",
          "Record Type",
          "SEL State",
          "Timestamp",
          "Sensor Name",
          "Sensor Type",
          "Event Direction",
          "Event Type Code",
          "Event Data",
          "Event Offset",
          "Event Offset String");

  for (i = 0; i < sel_count; i++, ipmi_monitoring_sel_iterator_next (ctx))
    {
      int record_id, record_type, sel_state, sensor_type, sensor_number, event_direction,
        event_offset_type, event_offset, event_type_code, manufacturer_id;
      unsigned int timestamp, event_data1, event_data2, event_data3;
      int record_type_class;
      char *event_offset_string = NULL;
      const char *sensor_type_str;
      const char *event_direction_str;
      const char *sel_state_str;
      char *sensor_name = NULL;
      unsigned char oem_data[64];
      int oem_data_len;
      unsigned int j;

      if ((record_id = ipmi_monitoring_sel_read_record_id (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_read_record_id: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((record_type = ipmi_monitoring_sel_read_record_type (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_read_record_type: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((record_type_class = ipmi_monitoring_sel_read_record_type_class (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_read_record_type_class: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sel_state = ipmi_monitoring_sel_read_sel_state (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sel_read_sel_state: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if (sel_state == IPMI_MONITORING_STATE_NOMINAL)
        sel_state_str = "Nominal";
      else if (sel_state == IPMI_MONITORING_STATE_WARNING)
        sel_state_str = "Warning";
      else if (sel_state == IPMI_MONITORING_STATE_CRITICAL)
        sel_state_str = "Critical";
      else
        sel_state_str = "N/A";

      printf ("%u, %u, %s",
              record_id,
              record_type,
              sel_state_str);
      
      if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD
          || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
        {
          
          if (ipmi_monitoring_sel_read_timestamp (ctx, &timestamp) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_timestamp: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }
          
          /* XXX: This should be converted to a nice date output using
           * your favorite timestamp -> string conversion functions.
           */
          printf (", %u", timestamp);
        }
      else
        printf (", N/A");

      if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD)
        {         
          /* If you are integrating ipmimonitoring SEL into a monitoring application,
           * you may wish to count the number of times a specific error occurred
           * and report that to the monitoring application.
           *
           * In this particular case, you'll probably want to check out
           * what sensor type each SEL event is reporting, the
           * event offset type, and the specific event offset that occurred.
           *
           * See ipmi_monitoring_offsets.h for a list of event offsets
           * and types.
           */

          if (!(sensor_name = ipmi_monitoring_sel_read_sensor_name (ctx)))
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_sensor_name: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }

          if ((sensor_type = ipmi_monitoring_sel_read_sensor_type (ctx)) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_sensor_type: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }

          if ((sensor_number = ipmi_monitoring_sel_read_sensor_number (ctx)) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_sensor_number: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }

          if ((event_direction = ipmi_monitoring_sel_read_event_direction (ctx)) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_event_direction: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }

          if ((event_type_code = ipmi_monitoring_sel_read_event_type_code (ctx)) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_event_type_code: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }

          if (ipmi_monitoring_sel_read_event_data (ctx,
                                                   &event_data1,
                                                   &event_data2,
                                                   &event_data3) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_event_data: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }         

          if ((event_offset_type = ipmi_monitoring_sel_read_event_offset_type (ctx)) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_event_offset_type: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }
          
          if ((event_offset = ipmi_monitoring_sel_read_event_offset (ctx)) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_event_offset: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }
          
          if (!(event_offset_string = ipmi_monitoring_sel_read_event_offset_string (ctx)))
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_event_offset_string: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }

          if (!strlen (sensor_name))
            sensor_name = "N/A";
          
          sensor_type_str = _get_sensor_type_string (sensor_type);

          if (event_direction == IPMI_MONITORING_SEL_EVENT_DIRECTION_ASSERTION)
            event_direction_str = "Assertion";
          else
            event_direction_str = "Deassertion";

          printf (", %s, %s, %u, %s, %Xh, %Xh-%Xh-%Xh",
                  sensor_name,
                  sensor_type_str,
                  sensor_number,
                  event_direction_str,
                  event_type_code,
                  event_data1,
                  event_data2,
                  event_data3);
                  
          if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
            printf (", %Xh", event_offset);
          else
            printf (", N/A");
          
          if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
            printf (", %s", event_offset_string);
          else
            printf (", N/A");
        }
      else if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD
               || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_NON_TIMESTAMPED_OEM_RECORD)
        {
          if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
            {
              if ((manufacturer_id = ipmi_monitoring_sel_read_manufacturer_id (ctx)) < 0)
                {
                  fprintf (stderr,
                           "ipmi_monitoring_sel_read_manufacturer_id: %s\n",
                           ipmi_monitoring_ctx_errormsg (ctx));
                  goto cleanup;
                }
              
              printf (", Manufacturer ID = %Xh", manufacturer_id);
            }

          if ((oem_data_len = ipmi_monitoring_sel_read_oem_data (ctx, oem_data, 1024)) < 0)
            {
              fprintf (stderr,
                       "ipmi_monitoring_sel_read_oem_data: %s\n",
                       ipmi_monitoring_ctx_errormsg (ctx));
              goto cleanup;
            }

          printf (", OEM Data = ");

          for (j = 0; j < oem_data_len; j++)
            printf ("%02Xh ", oem_data[j]);
        }
      else
        printf (", N/A, N/A, N/A, N/A, N/A, N/A, N/A");
      
      printf ("\n");
    }

  rv = 0;
 cleanup:
  if (ctx)
    ipmi_monitoring_ctx_destroy (ctx);
  return (rv);
}
static int
_ipmimonitoring (struct ipmi_monitoring_ipmi_config *ipmi_config)
{
  ipmi_monitoring_ctx_t ctx = NULL;
  unsigned int sensor_reading_flags = 0;
  unsigned int i;
  int sensor_count;
  int errnum;
  int rv = -1;

  if (ipmi_monitoring_init (ipmimonitoring_init_flags, &errnum) < 0)
    {
      fprintf (stderr,
               "ipmi_monitoring_init: %s\n",
               ipmi_monitoring_ctx_strerror (errnum));
      goto cleanup;
    }

  if (!(ctx = ipmi_monitoring_ctx_create ()))
    {
      perror ("ipmi_monitoring_ctx_create:");
      goto cleanup;
    }

  if (sdr_cache_directory)
    {
      if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
                                                   sdr_cache_directory) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_ctx_sdr_cache_directory: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }

  /* Must call otherwise only default interpretations ever used */
  if (sensor_config_file)
    {
      if (ipmi_monitoring_ctx_sensor_config_file (ctx,
                                                  sensor_config_file) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_ctx_sensor_config_file: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  else
    {
      if (ipmi_monitoring_ctx_sensor_config_file (ctx, NULL) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_ctx_sensor_config_file: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    } 

  if (reread_sdr_cache)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_REREAD_SDR_CACHE;

  if (ignore_non_interpretable_sensors)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_NON_INTERPRETABLE_SENSORS;
  
  if (bridge_sensors)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_BRIDGE_SENSORS;

  if (interpret_oem_data)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_INTERPRET_OEM_DATA;

  if (shared_sensors)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_SHARED_SENSORS;

  if (discrete_reading)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_DISCRETE_READING;

  if (ignore_scanning_disabled)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_SCANNING_DISABLED;

  if (assume_bmc_owner)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ASSUME_BMC_OWNER;

  if (entity_sensor_names)
    sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES;

  if (!record_ids_length && !sensor_types_length)
    {
      if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
                                                                        hostname,
                                                                        ipmi_config,
                                                                        sensor_reading_flags,
                                                                        NULL,
                                                                        0,
                                                                        NULL,
                                                                        NULL)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_readings_by_record_id: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  else if (record_ids_length)
    {
      if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
                                                                        hostname,
                                                                        ipmi_config,
                                                                        sensor_reading_flags,
                                                                        record_ids,
                                                                        record_ids_length,
                                                                        NULL,
                                                                        NULL)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_readings_by_record_id: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }
  else
    {
      if ((sensor_count = ipmi_monitoring_sensor_readings_by_sensor_type (ctx,
                                                                          hostname,
                                                                          ipmi_config,
                                                                          sensor_reading_flags,
                                                                          sensor_types,
                                                                          sensor_types_length,
                                                                          NULL,
                                                                          NULL)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_readings_by_sensor_type: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }
    }

  printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
          "Record ID",
          "Sensor Name",
          "Sensor Number",
          "Sensor Type",
          "Sensor State",
          "Sensor Reading",
          "Sensor Units",
          "Sensor Event/Reading Type Code",
          "Sensor Event Bitmask",
          "Sensor Event String");

  for (i = 0; i < sensor_count; i++, ipmi_monitoring_sensor_iterator_next (ctx))
    {
      int record_id, sensor_number, sensor_type, sensor_state, sensor_units,
        sensor_bitmask_type, sensor_bitmask, sensor_reading_type,
        event_reading_type_code;
      char **sensor_bitmask_strings = NULL;
      const char *sensor_type_str;
      const char *sensor_state_str;
      char *sensor_name = NULL;
      void *sensor_reading;

      if ((record_id = ipmi_monitoring_sensor_read_record_id (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_record_id: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sensor_number = ipmi_monitoring_sensor_read_sensor_number (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_number: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sensor_type = ipmi_monitoring_sensor_read_sensor_type (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_type: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if (!(sensor_name = ipmi_monitoring_sensor_read_sensor_name (ctx)))
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_name: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sensor_state = ipmi_monitoring_sensor_read_sensor_state (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_state: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sensor_units = ipmi_monitoring_sensor_read_sensor_units (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_units: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sensor_bitmask_type = ipmi_monitoring_sensor_read_sensor_bitmask_type (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_bitmask_type: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sensor_bitmask = ipmi_monitoring_sensor_read_sensor_bitmask (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_bitmask: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if (!(sensor_bitmask_strings = ipmi_monitoring_sensor_read_sensor_bitmask_strings (ctx)))
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_bitmask_strings: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if ((sensor_reading_type = ipmi_monitoring_sensor_read_sensor_reading_type (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_sensor_reading_type: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      sensor_reading = ipmi_monitoring_sensor_read_sensor_reading (ctx);

      if ((event_reading_type_code = ipmi_monitoring_sensor_read_event_reading_type_code (ctx)) < 0)
        {
          fprintf (stderr,
                   "ipmi_monitoring_sensor_read_event_reading_type_code: %s\n",
                   ipmi_monitoring_ctx_errormsg (ctx));
          goto cleanup;
        }

      if (!strlen (sensor_name))
        sensor_name = "N/A";

      sensor_type_str = _get_sensor_type_string (sensor_type);

      printf ("%u, %s, %u, %s",
              record_id,
              sensor_name,
              sensor_number,
              sensor_type_str);

      if (sensor_state == IPMI_MONITORING_STATE_NOMINAL)
        sensor_state_str = "Nominal";
      else if (sensor_state == IPMI_MONITORING_STATE_WARNING)
        sensor_state_str = "Warning";
      else if (sensor_state == IPMI_MONITORING_STATE_CRITICAL)
        sensor_state_str = "Critical";
      else
        sensor_state_str = "N/A";

      printf (", %s", sensor_state_str);

      if (sensor_reading)
        {
          const char *sensor_units_str;

          if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL)
            printf (", %s",
                    (*((uint8_t *)sensor_reading) ? "true" : "false"));
          else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32)
            printf (", %u",
                    *((uint32_t *)sensor_reading));
          else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
            printf (", %.2f",
                    *((double *)sensor_reading));
          else
            printf (", N/A");

          if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_CELSIUS)
            sensor_units_str = "C";
          else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT)
            sensor_units_str = "F";
          else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_VOLTS)
            sensor_units_str = "V";
          else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_AMPS)
            sensor_units_str = "A";
          else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_RPM)
            sensor_units_str = "RPM";
          else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_WATTS)
            sensor_units_str = "W";
          else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_PERCENT)
            sensor_units_str = "%";
          else
            sensor_units_str = "N/A";

          printf (", %s", sensor_units_str);
        }
      else
        printf (", N/A, N/A");
  
      printf (", %Xh", event_reading_type_code);
 
      /* It is possible you may want to monitor specific event
       * conditions that may occur.  If that is the case, you may want
       * to check out what specific bitmask type and bitmask events
       * occurred.  See ipmi_monitoring_bitmasks.h for a list of
       * bitmasks and types.
       */

      if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
        printf (", %Xh", sensor_bitmask);
      else
        printf (", N/A");
  
      if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
        {     
          unsigned int i = 0;
          
          printf (",");
          
          while (sensor_bitmask_strings[i])
            {
              printf (" ");
              
              printf ("'%s'",
                      sensor_bitmask_strings[i]);
              
              i++;
            }
        }
      else
        printf (", N/A");

      printf ("\n");
    }

  rv = 0;
 cleanup:
  if (ctx)
    ipmi_monitoring_ctx_destroy (ctx);
  return (rv);
}