--- /dev/null
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include <sys/types.h>
+
+typedef struct GlobalData GlobalData;
+
+typedef struct {
+ char *color;
+ char *text;
+} StatusItem;
+
+
+typedef struct GlobalData {
+ char *line;
+ size_t linelen;
+ size_t linemax; /* Buffer size, including NUL */
+} GlobalData;
+
+
+
+void line_clear(GlobalData *g);
+void line_append_strn(GlobalData *g, char *string, size_t len);
+void line_append_str(GlobalData *g, char *string);
+
+void line_append_item(GlobalData *g, StatusItem *s);
+
+void line_print(GlobalData *g);
+
+void statusitem_init(StatusItem *s);
+
+#endif
+++ /dev/null
-
-#ifndef __BATTERY_H__
-#define __BATTERY_H__
-
-void status_battery(char *batname);
-
-#endif
+++ /dev/null
-
-#ifndef __CPUUSAGE_H__
-#define __CPUUSAGE_H__
-
-void status_cpuusage();
-
-#endif
+++ /dev/null
-
-#ifndef __DATETIME_H__
-#define __DATETIME_H__
-
-void status_datetime();
-
-#endif
+++ /dev/null
-
-#ifndef __FAN_H__
-#define __FAN_H__
-
-void status_fan(char *title, char *sysfile);
-
-#endif
+++ /dev/null
-
-#ifndef __MEMUSAGE_H__
-#define __MEMUSAGE_H__
-
-void status_memusage();
-
-#endif
+++ /dev/null
-
-#ifndef __NETIF_H__
-#define __NETIF_H__
-
-void status_netif(char *ifname);
-
-#endif
+++ /dev/null
-
-#ifndef __TEMP_H__
-#define __TEMP_H__
-
-void status_temp(char *title, char *sysfile);
-
-#endif
+++ /dev/null
-
-#ifndef __UPTIME_H__
-#define __UPTIME_H__
-
-void status_uptime();
-
-#endif
+++ /dev/null
-
-#ifndef __VOLUME_ALSA_H__
-#define __VOLUME_ALSA_H__
-
-#include <alsa/asoundlib.h>
-
-int status_volume_alsa(char *cardname, char *mixername, snd_mixer_selem_channel_id_t channel);
-
-#endif
--- /dev/null
+#ifndef __STATUSES_H__
+#define __STATUSES_H__
+
+#include <alsa/asoundlib.h>
+
+#include "common.h"
+
+void status_battery(GlobalData *g, char *batname);
+void status_cpuusage(GlobalData *g);
+void status_datetime(GlobalData *g);
+void status_fan(GlobalData *g, char *title, char *sysfile);
+void status_memusage(GlobalData *g);
+void status_netif(GlobalData *g, char *ifname);
+void status_temp(GlobalData *g, char *title, char *sysfile);
+void status_uptime(GlobalData *g);
+int status_volume_alsa(GlobalData *g, char *cardname, char *mixername, snd_mixer_selem_channel_id_t channel);
+
+#endif
--- /dev/null
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "common.h"
+
+
+static int linebuf_sane(GlobalData *g)
+{
+ return (g->linelen < g->linemax);
+}
+
+
+void line_clear(GlobalData *g)
+{
+ assert(g->linemax > 0);
+
+ g->line[0] = '\0';
+ g->linelen = 0;
+}
+
+
+void line_append_strn(GlobalData *g, char *string, size_t len)
+{
+ assert(linebuf_sane(g));
+
+ if (g->linemax <= g->linelen + len) {
+ /* Buffer full. Tough luck. */
+ return;
+ }
+
+ memcpy(&g->line[g->linelen], string, len);
+ g->linelen += len;
+ g->line[g->linelen] = '\0';
+}
+
+
+void line_append_str(GlobalData *g, char *string)
+{
+ line_append_strn(g, string, strlen(string));
+}
+
+
+
+void line_append_item(GlobalData *g, StatusItem *s)
+{
+ line_append_str(g, " ");
+
+ if (s->color) {
+ line_append_str(g, "^fg(");
+ line_append_str(g, s->color);
+ line_append_str(g, ")");
+ }
+
+ if (s->text) {
+ line_append_str(g, s->text);
+ }
+
+ line_append_str(g, " ");
+}
+
+
+void line_print(GlobalData *g)
+{
+ puts(g->line);
+}
+
+
+void statusitem_init(StatusItem *s)
+{
+ s->color = NULL;
+ s->text = NULL;
+}
#include <unistd.h>
#include <string.h>
-#include "status/battery.h"
+#include "common.h"
#include "tools.h"
#ifndef POWER_BASEDIR
#endif
-void status_battery(char *batname)
+void status_battery(GlobalData *g, char *batname)
{
+ StatusItem s;
+ char text[32] = { 0 };
+
char batpath[256];
int batpathlen;
float battTime = -1;
+ statusitem_init(&s);
+ s.text = text;
+
/* Prepare path */
batpathlen = sizeof(POWER_BASEDIR) - 1 + strlen(batname);
if (batpathlen + 1 + sizeof("/energy_full") >= sizeof(batpath)) {
if (chargePercent <= 40) {
if (chargePercent <= 25) {
if (chargePercent <= 10) {
- fputs("^fg(red)", stdout);
+ s.color = "red";
} else {
// 11-25%
- fputs("^fg(orange)", stdout);
+ s.color = "orange";
}
} else {
// 26-40%
- fputs("^fg(yellow)", stdout);
+ s.color = "yellow";
}
} else {
if (chargePercent > 70) {
- fputs("^fg(white)", stdout);
+ s.color = "white";
} else {
// 41-70%
- fputs("^fg(green)", stdout);
+ s.color = "green";
}
}
if (battW == 0) {
// fully charged and not in use
- printf(" %s: %d%% _ _ ",
- batname, chargePercent);
+ snprintf(text, sizeof(text), "%s: %d%% _ _",
+ batname, chargePercent);
} else {
- printf(" %s: %d%% %.1fh %.1fW ",
- batname, chargePercent, battTime, (float)battW / 1000000.0);
+ snprintf(text, sizeof(text), "%s: %d%% %.1fh %.1fW",
+ batname, chargePercent, battTime, (float)battW / 1000000.0);
}
+
+ line_append_item(g, &s);
}
#include <unistd.h>
#include <stdlib.h>
-#include "status/cpuusage.h"
+#include "common.h"
#include "config.h"
#ifndef NUM_CPUS
unsigned long last_cpu_total = 0;
float cpu_history[CPU_HISTORY_SIZE]; // don't care about init values
-void status_cpuusage()
+void status_cpuusage(GlobalData *g)
{
+ StatusItem s;
+ char text[32] = { 0 };
+
double loadavg[3] = { -13.37, -13.37, -13.37 } ;
char *stline = NULL;
int i;
+ statusitem_init(&s);
+ s.text = text;
+
// Error signaling color
- fputs("^fg(yellow)", stdout);
+ s.color = "yellow";
stfile = fopen("/proc/stat", "r");
if (stfile != NULL) {
if (cpu_history[0] < 0.4) {
// CPU idling OK
- fputs("^fg(#0077FF)", stdout);
+ s.color = "#0077FF";
} else {
// CPU busy
- fputs("^fg(#FF00FF)", stdout);
+ s.color = "#FF00FF";
}
-
- //printf(" CPU: %.0f%% ", cpu_history[0] * 100);
}
free(stline);
if (getloadavg(loadavg, 3) > 0) {
- printf(" %s%.0f,%.0f,%.0f,%.0f ",
- cpu_history[0] < 0.1000 ? " " : "",
- cpu_history[0] * 100,
- loadavg[0] * (100 / 1),
- loadavg[1] * (100 / 1), // (100 / NUM_CPUS)
- loadavg[2] * (100 / 1));
+ snprintf(text, sizeof(text),
+ "%s%.0f,%.0f,%.0f,%.0f",
+ cpu_history[0] < 0.1000 ? " " : "",
+ cpu_history[0] * 100,
+ loadavg[0] * (100 / 1),
+ loadavg[1] * (100 / 1), // (100 / NUM_CPUS)
+ loadavg[2] * (100 / 1));
}
- //fputs(" CPU usage ", stdout);
+ line_append_item(g, &s);
}
#include <stdio.h>
#include <time.h>
-#include "status/datetime.h"
+#include "common.h"
#include "config.h"
-void status_datetime()
+void status_datetime(GlobalData *g)
{
+ StatusItem s;
+ char text[32] = { 0 };
+
time_t nows = 0;
struct tm *nowtm;
+
+ statusitem_init(&s);
+ s.text = text;
+
nows = time(NULL);
if (nows == ((time_t) -1)) {
- printf(" ^fg(red)ERROR: DATETIME");
- return;
- }
+ s.color = "red";
+ s.text = "ERROR: DATETIME";
- nowtm = localtime(&nows);
-
- printf(" ^fg(#666666)%d.%d.%d ^fg(grey)%d:%.2d"
- #ifdef SHOW_SECONDS
- ":%.2d"
- #endif
- " "
- ,nowtm -> tm_mday,
- (nowtm -> tm_mon) + 1,
- (nowtm -> tm_year) + 1900,
- nowtm -> tm_hour,
- nowtm -> tm_min
-
- #ifdef SHOW_SECONDS
- ,nowtm -> tm_sec
- #endif
- );
+ line_append_item(g, &s);
+ } else {
+ nowtm = localtime(&nows);
+
+ s.color = "#666666";
+ snprintf(text, sizeof(text),
+ "%d.%d.%d",
+ nowtm->tm_mday,
+ (nowtm->tm_mon) + 1,
+ (nowtm->tm_year) + 1900
+ );
+ line_append_item(g, &s);
+
+ s.color = "grey";
+ snprintf(text, sizeof(text),
+ "%d:%.2d"
+ #ifdef SHOW_SECONDS
+ ":%.2d"
+ #endif
+ ,nowtm->tm_hour,
+ nowtm->tm_min
+
+ #ifdef SHOW_SECONDS
+ ,nowtm -> tm_sec
+ #endif
+ );
+ line_append_item(g, &s);
+ }
}
#include <fcntl.h>
#include <unistd.h>
-#include "status/fan.h"
+#include "common.h"
#include "tools.h"
-void status_fan(char *title, char *sysfile)
+void status_fan(GlobalData *g, char *title, char *sysfile)
{
+ StatusItem s;
+ char text[16] = { 0 };
+
char stline[16];
ssize_t stlen;
+
+ statusitem_init(&s);
+ s.text = text;
+
stlen = fileRead(stline, sizeof(stline), sysfile);
if (stlen <= 0) {
return;
// Read a valid value? Sometimes we get garbage from sysfs...
if (stlen > 5) {
- printf(" ^fg(red)%sERROR ", title);
- return;
+ s.color = "red";
+ snprintf(text, sizeof(text), "%sERROR", title);
+ } else {
+ stline[stlen - 1] = '\0';
+
+ s.color = "#CCCCCC";
+ snprintf(text, sizeof(text), "%s%s rpm", title, stline);
}
- fputs(" ^fg(#CCCCCC)", stdout);
- fputs(title, stdout);
- fwrite(stline, 1, stlen - 1, stdout);
- fputs(" rpm ", stdout);
+ line_append_item(g, &s);
}
#include <stdio.h>
#include <stdlib.h>
-#include "status/memusage.h"
+#include "common.h"
#include "tools.h"
-void status_memusage()
+void status_memusage(GlobalData *g)
{
+ StatusItem s;
+ char text[16] = { 0 };
+
char *stline = NULL;
size_t stlen;
FILE *stfile;
int memcached = 0;
+ statusitem_init(&s);
+ s.text = text;
+
stfile = fopen("/proc/meminfo", "r");
if (stfile != NULL) {
stlen = getline(&stline, &stlen, stfile);
/* Change color based on % of RAM used */
if ((float)memused / (float)memtotal < 0.85) {
- fputs("^fg(green)", stdout);
+ s.color = "green";
} else {
- fputs("^fg(red)", stdout);
+ s.color = "red";
}
- printf(" Mem: %d M ", memused);
+ snprintf(text, sizeof(text), "Mem: %d M", memused);
+
+ line_append_item(g, &s);
}
}
#include <unistd.h>
#include <string.h>
-#include "status/netif.h"
+#include "common.h"
#include "tools.h"
#include "config.h"
#endif
-void status_netif(char *ifname)
+void status_netif(GlobalData *g, char *ifname)
{
+ StatusItem s;
+ char text[16] = { 0 };
+
char ifpath[256];
int ifpathlen;
int ifsumpower;
+ statusitem_init(&s);
+ s.text = text;
+
/* Prepare path */
ifpathlen = sizeof(NETIF_BASEDIR) - 1 + strlen(ifname);
if (ifpathlen + 1 + sizeof("/statistics/rx_bytes") >= sizeof(ifpath)) {
/* Is the interface up? */
if (access(ifpath, F_OK)) {
- //printf(" ^fg(grey)[%s] ", ifname);
+ //s.color = "grey";
return;
}
stlen = fileRead(stline, sizeof(stline), ifpath);
if (stlen > 0) {
if (stline[0] == '1') {
- fputs("^fg(yellow)", stdout);
+ s.color = "yellow";
} else {
- //fputs("^fg(red)", stdout);
+ //s.color = "red";
return;
}
} else {
ifsum = ifsum / 1024;
}
- printf(" %s: %.*f %c ", ifname,
- ifsumpower ? ifsumpower - 1 : ifsumpower,
- ifsum,
- powerToChar(ifsumpower));
+ snprintf(text, sizeof(text), "%s: %.*f %c",
+ ifname,
+ ifsumpower ? ifsumpower - 1 : ifsumpower,
+ ifsum,
+ powerToChar(ifsumpower));
+
+ line_append_item(g, &s);
}
#include <fcntl.h>
#include <unistd.h>
-#include "status/temp.h"
+#include "common.h"
#include "tools.h"
-void status_temp(char *title, char *sysfile)
+void status_temp(GlobalData *g, char *title, char *sysfile)
{
+ StatusItem s;
+ char text[16] = { 0 };
+
char stline[16];
ssize_t stlen;
+
+ statusitem_init(&s);
+ s.text = text;
+
stlen = fileRead(stline, sizeof(stline), sysfile);
if (stlen <= 0) {
return;
* Sometimes we get garbage from sysfs...
*/
if (stlen < 6 || stlen > 7) {
- printf(" ^fg(red)%sERROR ", title);
- return;
+ s.color = "red";
+ snprintf(text, sizeof(text), "%sERROR", title);
+ } else {
+ stline[stlen - 4] = '\0';
+
+ s.color = "#FF33FF";
+ snprintf(text, sizeof(text), "%s%s°C", title, stline);
}
- fputs(" ^fg(#FF33FF)", stdout);
- fputs(title, stdout);
- fwrite(stline, 1, stlen - 4, stdout);
- /*
- fputs(".", stdout);
- fwrite(&stline[stlen - 3], 1, 1, stdout);
- */
- fputs("°C ", stdout);
+ line_append_item(g, &s);
}
#include <unistd.h>
#include <stdlib.h>
-#include "status/uptime.h"
+#include "common.h"
#include "tools.h"
#include "config.h"
-void status_uptime()
+void status_uptime(GlobalData *g)
{
+ StatusItem s;
+ char text[16] = { 0 };
+
char stline[16];
ssize_t stlen;
int i;
int upts, uptm, upth, uptd;
- fputs(" ^fg(#AAAAAA)up: ", stdout);
+
+ statusitem_init(&s);
+ s.text = text;
stlen = fileRead(stline, sizeof(stline), "/proc/uptime");
if (stlen < 0) {
- fputs(" ^fg(red)ERROR ", stdout);
- return;
- }
+ s.color = "red";
+ s.text = "up: ERROR";
+ } else {
+ unsigned textlen = 0;
- /* Cut first element */
- for(i = 0; i < stlen; i++) {
- if (stline[i] == ' ') {
- stline[i] = '\0';
- break;
+ /* Cut first element */
+ for(i = 0; i < stlen; i++) {
+ if (stline[i] == ' ') {
+ stline[i] = '\0';
+ break;
+ }
}
- }
- // Split time into days, hours, mins, secs
- upts = atoi(stline);
- uptd = upts / (24 * 60 * 60);
- upts -= uptd * (24 * 60 * 60);
- upth = upts / (60 * 60);
- upts -= upth * (60 * 60);
- uptm = upts / (60);
- upts -= uptm * (60);
-
- if (uptd > 0) {
- printf("%dd ", uptd);
- }
+ // Split time into days, hours, mins, secs
+ upts = atoi(stline);
+ uptd = upts / (24 * 60 * 60);
+ upts -= uptd * (24 * 60 * 60);
+ upth = upts / (60 * 60);
+ upts -= upth * (60 * 60);
+ uptm = upts / (60);
+ upts -= uptm * (60);
- printf("%d:%.2d"
- #ifdef SHOW_SECONDS
- ":%.2d"
- #endif
+ s.color = "#AAAAAA";
+ textlen = snprintf(text, sizeof(text), "up: ");
+ if (uptd > 0) {
+ textlen += snprintf(&text[textlen], sizeof(text) - textlen, "%dd ", uptd);
+ }
+
+
+ snprintf(&text[textlen], sizeof(text) - textlen,
+ "%d:%.2d"
+ #ifdef SHOW_SECONDS
+ ":%.2d"
+ #endif
- " "
- ,upth
- ,uptm
+ ""
+ ,upth
+ ,uptm
- #ifdef SHOW_SECONDS
- ,upts
- #endif
- );
+ #ifdef SHOW_SECONDS
+ ,upts
+ #endif
+ );
+
+ line_append_item(g, &s);
+ }
}
#include <alsa/asoundlib.h>
-#include "status/volume_alsa.h"
+#include "common.h"
-int status_volume_alsa(char *cardname, char *mixername, snd_mixer_selem_channel_id_t channel)
+int status_volume_alsa(GlobalData *g,
+ char *cardname,
+ char *mixername,
+ snd_mixer_selem_channel_id_t channel)
{
+ StatusItem s;
+ char text[16] = { 0 };
+
snd_mixer_t *handle = NULL;
snd_mixer_elem_t *elem;
snd_mixer_selem_id_t *sid;
int on_off;
+ statusitem_init(&s);
+ s.text = text;
+
snd_mixer_selem_id_alloca(&sid);
if (snd_mixer_open(&handle, 0) < 0) {
if (snd_mixer_selem_has_playback_volume(elem)
&& snd_mixer_selem_has_playback_channel(elem, channel)) {
snd_mixer_selem_get_playback_switch(elem, channel, &on_off);
- if (on_off) {
- fputs("^fg(#22FF22)", stdout);
- } else {
- fputs("^fg(red)", stdout);
- }
-
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
-
snd_mixer_selem_get_playback_volume(elem, channel, &volume);
- fputs("^ca(1, amixer sset Master toggle)", stdout);
- fputs("^ca(4, amixer sset Master 2+ unmute)", stdout);
- fputs("^ca(5, amixer sset Master 2- unmute)", stdout);
- printf(" Vol: %d ", (int)volume);
- fputs("^ca()", stdout);
- fputs("^ca()", stdout);
- fputs("^ca()", stdout);
+
+ s.color = on_off ? "#22FF22" : "red";
+ snprintf(text, sizeof(text), "Vol: %d", (int)volume);
}
snd_mixer_close(handle);
+ line_append_item(g, &s);
+
return 0;
ERROR:
#include <stdio.h>
#include <stdlib.h>
+#include "common.h"
#include "config.h"
-#include "status/battery.h"
-#include "status/cpuusage.h"
-#include "status/datetime.h"
-#include "status/fan.h"
-#include "status/memusage.h"
-#include "status/netif.h"
-#include "status/volume_alsa.h"
-#include "status/temp.h"
-#include "status/uptime.h"
+#include "statuses.h"
+
+
+static char outline[1024];
+
+static GlobalData gd = {
+ .line = outline,
+ .linemax = sizeof(outline),
+};
void updatestatus()
{
- //status_uptime();
+ GlobalData *g = &gd;
+
- status_cpuusage();
+ line_clear(g);
- status_battery("BAT0");
- status_battery("BAT1");
+ //status_uptime(g);
- status_memusage();
+ status_cpuusage(g);
- status_netif("eth0");
- //status_netif("eth1");
- //status_netif("eth2");
- status_netif("wlan0");
- //status_netif("wlan1");
- status_netif("wlan2");
- //status_netif("usb0");
- status_netif("ppp0");
+ status_battery(g, "BAT0");
+ status_battery(g, "BAT1");
+
+ status_memusage(g);
+
+ status_netif(g, "eth0");
+ //status_netif(g, "eth1");
+ //status_netif(g, "eth2");
+ status_netif(g, "wlan0");
+ //status_netif(g, "wlan1");
+ status_netif(g, "wlan2");
+ //status_netif(g, "usb0");
+ status_netif(g, "ppp0");
//status_temp("GPU: ", "/sys/class/hwmon/hwmon0/device/temp4_input");
//status_temp("CPU: ", "/sys/class/hwmon/hwmon0/device/temp2_input");
- status_temp("CPU: ", "/sys/devices/platform/coretemp.0/temp1_input");
+ status_temp(g, "CPU: ", "/sys/devices/platform/coretemp.0/temp1_input");
+
+ status_fan(g, "Fan: ", "/sys/devices/platform/thinkpad_hwmon/fan1_input");
- status_fan("Fan: ", "/sys/devices/platform/thinkpad_hwmon/fan1_input");
+ status_volume_alsa(g, "default", "Master", 0);
- status_volume_alsa("default", "Master", 0);
+ status_datetime(g);
- status_datetime();
+ line_print(g);
- fputs("\n", stdout);
fflush(stdout);
}