*
*
* Copyright © 2008-2009 Michael Stapelberg and contributors
+ * Copyright © 2009 Thorsten Toepper <atsutane at freethoughts dot de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
#include <glob.h>
#include <dirent.h>
#include <getopt.h>
+#include <signal.h>
#include "queue.h"
#define BAR "^fg(#333333)^p(5;-2)^ro(2)^p()^fg()^p(5)"
struct battery {
- const char *path;
+ char *path;
+ /* Use last full capacity instead of design capacity */
+ bool use_last_full;
SIMPLEQ_ENTRY(battery) batteries;
};
static const char *eth_interface;
static char *wmii_path;
static const char *time_format;
-static const char *battery_path;
static bool use_colors;
static bool get_ethspeed;
+static bool get_cpu_temperature;
+static char *thermal_zone;
static const char *wmii_normcolors = "#222222 #333333";
static char order[MAX_ORDER][2];
static const char **run_watches;
static unsigned int num_run_watches;
static unsigned int interval = 1;
+static int max(int a, int b) {
+ return (a > b ? a : b);
+}
+
/*
* This function just concats two strings in place, it should only be used
* for concatting order to the name of a file or concatting color codes.
create_file(concat(order[ORDER_WLAN],"wlan"));
if (eth_interface)
create_file(concat(order[ORDER_ETH],"eth"));
- if (battery_path)
- create_file(concat(order[ORDER_BATTERY],"battery"));
+ if (get_cpu_temperature)
+ create_file(concat(order[ORDER_CPU_TEMPERATURE], "cpu_temperature"));
create_file(concat(order[ORDER_LOAD],"load"));
if (time_format)
create_file(concat(order[ORDER_TIME],"time"));
static void write_to_statusbar(const char *name, const char *message, bool final_entry) {
#ifdef DZEN
if (final_entry) {
- (void)printf("%s^p(6)\n", message);
+ if (printf("%s^p(6)\n", message) < 0) {
+ perror("printf");
+ exit(1);
+ }
+
fflush(stdout);
return;
}
- (void)printf("%s" BAR, message);
+ if (printf("%s" BAR, message) < 0) {
+ perror("printf");
+ exit(1);
+ }
return;
#endif
*
*/
void die(const char *fmt, ...) {
- if (wmii_path != NULL) {
- char buffer[512];
- va_list ap;
- va_start(ap, fmt);
- (void)vsnprintf(buffer, sizeof(buffer), fmt, ap);
- va_end(ap);
+ char buffer[512];
+ va_list ap;
+ va_start(ap, fmt);
+ (void)vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ va_end(ap);
+ if (wmii_path != NULL)
write_error_to_statusbar(buffer);
- }
+ else
+ fprintf(stderr, "%s", buffer);
exit(EXIT_FAILURE);
}
* worn off your battery is.
*
*/
-static char *get_battery_info(const char *path) {
+static char *get_battery_info(struct battery *bat) {
char buf[1024];
static char part[512];
char *walk, *last;
present_rate = -1;
charging_status_t status = CS_DISCHARGING;
- if ((fd = open(path, O_RDONLY)) == -1)
+ if ((fd = open(bat->path, O_RDONLY)) == -1)
return "No battery found";
memset(part, 0, sizeof(part));
(void)read(fd, buf, sizeof(buf));
- for (walk = buf, last = buf; (walk-buf) < 1024; walk++)
- if (*walk == '=') {
- if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN") ||
- BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN"))
- full_design = atoi(walk+1);
- else if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW") ||
- BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW"))
- remaining = atoi(walk+1);
- else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW"))
- present_rate = atoi(walk+1);
- else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging"))
- status = CS_CHARGING;
- else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full"))
- status = CS_FULL;
- } else if (*walk == '\n')
+ for (walk = buf, last = buf; (walk-buf) < 1024; walk++) {
+ if (*walk == '\n') {
last = walk+1;
+ continue;
+ }
+
+ if (*walk != '=')
+ continue;
+
+ if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW") ||
+ BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW"))
+ remaining = atoi(walk+1);
+ else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW"))
+ present_rate = atoi(walk+1);
+ else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging"))
+ status = CS_CHARGING;
+ else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full"))
+ status = CS_FULL;
+ else {
+ /* The only thing left is the full capacity */
+ if (bat->use_last_full) {
+ if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") &&
+ !BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL"))
+ continue;
+ } else {
+ if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") &&
+ !BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN"))
+ continue;
+ }
+
+ full_design = atoi(walk+1);
+ }
+ }
(void)close(fd);
if ((full_design == 1) || (remaining == -1))
(status == CS_CHARGING ? "CHR" :
(status == CS_DISCHARGING ? "BAT" : "FULL")),
(((float)remaining / (float)full_design) * 100),
- hours, minutes, seconds);
+ max(hours, 0), max(minutes, 0), max(seconds, 0));
} else {
(void)snprintf(part, sizeof(part), "%s %.02f%%",
(status == CS_CHARGING ? "CHR" :
return part;
}
+/*
+ * Reads the CPU temperature from /sys/class/thermal/thermal_zone0/temp and
+ * returns the temperature in degree celcius.
+ *
+ */
+static char *get_cpu_temperature_info() {
+ static char part[16];
+ char buf[16];
+ int temp;
+ int fd;
+
+ memset(buf, 0, sizeof(buf));
+ memset(part, 0, sizeof(part));
+
+ if ((fd = open(thermal_zone, O_RDONLY)) == -1)
+ die("Could not open %s\n", thermal_zone);
+ (void)read(fd, buf, sizeof(buf));
+ (void)close(fd);
+
+ if (sscanf(buf, "%d", &temp) != 1)
+ (void)snprintf(part, sizeof(part), "T: ? C");
+ else
+ (void)snprintf(part, sizeof(part), "T: %d C", (temp/1000));
+
+ return part;
+}
+
/*
* Checks if the PID in path is still valid by checking:
* (Linux) if /proc/<pid> exists
eth_interface = strdup(dest_value);
OPT("time_format")
time_format = strdup(dest_value);
- OPT("battery_path") {
+ OPT("battery") {
struct battery *new = calloc(1, sizeof(struct battery));
if (new == NULL)
die("Could not allocate memory\n");
- new->path = strdup(dest_value);
+ if (asprintf(&(new->path), "/sys/class/power_supply/BAT%d/uevent", atoi(dest_value)) == -1)
+ die("Could not build battery path\n");
+
+ /* check if flags were specified for this battery */
+ if (strstr(dest_value, ",") != NULL) {
+ char *flags = strstr(dest_value, ",");
+ flags++;
+ if (*flags == 'f')
+ new->use_last_full = true;
+ }
SIMPLEQ_INSERT_TAIL(&batteries, new, batteries);
} OPT("color")
use_colors = true;
OPT("get_ethspeed")
get_ethspeed = true;
- OPT("normcolors")
+ OPT("get_cpu_temperature") {
+ get_cpu_temperature = true;
+ if (strlen(dest_value) > 0) {
+ if (asprintf(&thermal_zone, "/sys/class/thermal/thermal_zone%d/temp", atoi(dest_value)) == -1)
+ die("Could not build thermal_zone path\n");
+ } else {
+ if (asprintf(&thermal_zone, "/sys/class/thermal/thermal_zone0/temp") == -1)
+ die("Could not build thermal_zone path\n");
+ }
+ } OPT("normcolors")
wmii_normcolors = strdup(dest_value);
OPT("interval")
interval = atoi(dest_value);
SET_ORDER("wlan", ORDER_WLAN);
SET_ORDER("eth", ORDER_ETH);
SET_ORDER("battery", ORDER_BATTERY);
+ SET_ORDER("cpu_temperature", ORDER_CPU_TEMPERATURE);
SET_ORDER("load", ORDER_LOAD);
SET_ORDER("time", ORDER_TIME);
token = walk;
return result;
}
+/*
+ * Exit upon SIGPIPE because when we have nowhere to write to, gathering
+ * system information is pointless.
+ *
+ */
+void sigpipe(int signum) {
+ fprintf(stderr, "Received SIGPIPE, exiting\n");
+ exit(1);
+}
+
int main(int argc, char *argv[]) {
char part[512],
pathbuf[512];
{0, 0, 0, 0}
};
+ struct sigaction action;
+ memset(&action, 0, sizeof(struct sigaction));
+ action.sa_handler = sigpipe;
+ sigaction(SIGPIPE, &action, NULL);
+
SIMPLEQ_INIT(&batteries);
while ((o = getopt_long(argc, argv, "c:h", long_options, &option_index)) != -1)
write_to_statusbar(concat(order[ORDER_ETH], "eth"), get_eth_info(), false);
struct battery *current_battery;
SIMPLEQ_FOREACH(current_battery, &batteries, batteries) {
- write_to_statusbar(concat(order[ORDER_BATTERY], "battery"), get_battery_info(current_battery->path), false);
+ write_to_statusbar(concat(order[ORDER_BATTERY], "battery"), get_battery_info(current_battery), false);
}
+ if (get_cpu_temperature)
+ write_to_statusbar(concat(order[ORDER_CPU_TEMPERATURE], "cpu_temperature"), get_cpu_temperature_info(), false);
/* Get load */
#ifdef LINUX