+static int battery_read (void) /* {{{ */
+{
+ gauge_t current = NAN; /* Current in A */
+ gauge_t voltage = NAN; /* Voltage in V */
+
+ /* We only get the charged capacity as a percentage from
+ * IOPowerSources. IOKit, on the other hand, only reports the full
+ * capacity. We use the two to calculate the current charged capacity. */
+ gauge_t charge_rel = NAN; /* Current charge in percent */
+ gauge_t capacity_charged = NAN; /* Charged capacity */
+ gauge_t capacity_full = NAN; /* Total capacity */
+ gauge_t capacity_design = NAN; /* Full design capacity */
+
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+ get_via_io_power_sources (&charge_rel, ¤t, &voltage);
+#endif
+#if HAVE_IOKIT_IOKITLIB_H
+ get_via_generic_iokit (&capacity_full, &capacity_design, ¤t, &voltage);
+#endif
+
+ capacity_charged = charge_rel * capacity_full / 100.0;
+ submit_capacity ("0", capacity_charged, capacity_full, capacity_design);
+
+ if (!isnan (current))
+ battery_submit ("0", "current", current);
+ if (!isnan (voltage))
+ battery_submit ("0", "voltage", voltage);
+
+ return (0);
+} /* }}} int battery_read */
+/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
+
+#elif KERNEL_LINUX
+/* Reads a file which contains only a number (and optionally a trailing
+ * newline) and parses that number. */
+static int sysfs_file_to_buffer(char const *dir, /* {{{ */
+ char const *power_supply,
+ char const *basename,
+ char *buffer, size_t buffer_size)
+{
+ int status;
+ FILE *fp;
+ char filename[PATH_MAX];
+
+ ssnprintf (filename, sizeof (filename), "%s/%s/%s",
+ dir, power_supply, basename);
+
+ /* No file isn't the end of the world -- not every system will be
+ * reporting the same set of statistics */
+ if (access (filename, R_OK) != 0)
+ return ENOENT;
+
+ fp = fopen (filename, "r");
+ if (fp == NULL)
+ {
+ status = errno;
+ if (status != ENOENT)
+ {
+ char errbuf[1024];
+ WARNING ("battery plugin: fopen (%s) failed: %s", filename,
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ }
+ return status;
+ }
+
+ if (fgets (buffer, buffer_size, fp) == NULL)
+ {
+ char errbuf[1024];
+ status = errno;
+ WARNING ("battery plugin: fgets failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ fclose (fp);
+ return status;
+ }
+
+ strstripnewline (buffer);
+
+ fclose (fp);
+ return 0;
+} /* }}} int sysfs_file_to_buffer */
+
+/* Reads a file which contains only a number (and optionally a trailing
+ * newline) and parses that number. */
+static int sysfs_file_to_gauge(char const *dir, /* {{{ */
+ char const *power_supply,
+ char const *basename, gauge_t *ret_value)
+{
+ int status;
+ char buffer[32] = "";
+
+ status = sysfs_file_to_buffer (dir, power_supply, basename, buffer, sizeof (buffer));
+ if (status != 0)
+ return (status);
+
+ return (strtogauge (buffer, ret_value));
+} /* }}} sysfs_file_to_gauge */
+
+static int read_sysfs_capacity (char const *dir, /* {{{ */
+ char const *power_supply,
+ char const *plugin_instance)
+{
+ gauge_t capacity_charged = NAN;
+ gauge_t capacity_full = NAN;
+ gauge_t capacity_design = NAN;
+ int status;
+
+ status = sysfs_file_to_gauge (dir, power_supply, "energy_now", &capacity_charged);
+ if (status != 0)
+ return (status);
+
+ status = sysfs_file_to_gauge (dir, power_supply, "energy_full", &capacity_full);
+ if (status != 0)
+ return (status);
+
+ status = sysfs_file_to_gauge (dir, power_supply, "energy_full_design", &capacity_design);
+ if (status != 0)
+ return (status);
+
+ submit_capacity (plugin_instance,
+ capacity_charged * SYSFS_FACTOR,
+ capacity_full * SYSFS_FACTOR,
+ capacity_design * SYSFS_FACTOR);
+ return (0);
+} /* }}} int read_sysfs_capacity */
+
+static int read_sysfs_callback (char const *dir, /* {{{ */
+ char const *power_supply,