X-Git-Url: https://git.xinqibao.xyz/slstatus.git/blobdiff_plain/8a29374783251da5ff23831e03c761b4a58eff03..832b21ca4b4ba866e010a6f52c0f84919c7123f2:/slstatus.c?ds=sidebyside

diff --git a/slstatus.c b/slstatus.c
index 4432e18..993eba4 100644
--- a/slstatus.c
+++ b/slstatus.c
@@ -25,11 +25,7 @@
 #include <unistd.h>
 #include <X11/Xlib.h>
 
-#undef strlcat
-
-#include "extern/arg.h"
-#include "extern/strlcat.h"
-#include "extern/concat.h"
+#include "arg.h"
 
 struct arg {
 	char *(*func)();
@@ -39,7 +35,9 @@ struct arg {
 
 static char *smprintf(const char *fmt, ...);
 static char *battery_perc(const char *bat);
+static char *battery_power(const char *bat);
 static char *battery_state(const char *bat);
+static char *cpu_freq(void);
 static char *cpu_perc(void);
 static char *datetime(const char *fmt);
 static char *disk_free(const char *mnt);
@@ -51,6 +49,7 @@ static char *gid(void);
 static char *hostname(void);
 static char *ip(const char *iface);
 static char *kernel_release(void);
+static char *keyboard_indicators(void);
 static char *load_avg(void);
 static char *ram_free(void);
 static char *ram_perc(void);
@@ -72,10 +71,9 @@ static void sighandler(const int signo);
 static void usage(const int eval);
 
 char *argv0;
-char concat[];
 static unsigned short int delay = 0;
 static unsigned short int done;
-static unsigned short int dflag, oflag;
+static unsigned short int dflag, oflag, nflag;
 static Display *dpy;
 
 #include "config.h"
@@ -107,12 +105,13 @@ static char *
 battery_perc(const char *bat)
 {
 	int perc;
+	char path[PATH_MAX];
 	FILE *fp;
 
-	ccat(3, "/sys/class/power_supply/", bat, "/capacity");
-	fp = fopen(concat, "r");
+	snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/capacity");
+	fp = fopen(path, "r");
 	if (fp == NULL) {
-		warn("Failed to open file %s", concat);
+		warn("Failed to open file %s", path);
 		return smprintf("%s", UNKNOWN_STR);
 	}
 	fscanf(fp, "%i", &perc);
@@ -121,16 +120,36 @@ battery_perc(const char *bat)
 	return smprintf("%d%%", perc);
 }
 
+static char *
+battery_power(const char *bat)
+{
+	char path[PATH_MAX];
+	FILE *fp;
+	int watts;
+
+	snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/power_now");
+	fp = fopen(path, "r");
+	if (fp == NULL) {
+		warn("Failed to open file %s", path);
+		return smprintf("%s", UNKNOWN_STR);
+	}
+	fscanf(fp, "%i", &watts);
+	fclose(fp);
+
+	return smprintf("%d", (watts + 500000) / 1000000);
+}
+
 static char *
 battery_state(const char *bat)
 {
+	char path[PATH_MAX];
 	char state[12];
 	FILE *fp;
 
-	ccat(3, "/sys/class/power_supply/", bat, "/status");
-	fp = fopen(concat, "r");
+	snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/status");
+	fp = fopen(path, "r");
 	if (fp == NULL) {
-		warn("Failed to open file %s", concat);
+		warn("Failed to open file %s", path);
 		return smprintf("%s", UNKNOWN_STR);
 	}
 	fscanf(fp, "%12s", state);
@@ -142,11 +161,30 @@ battery_state(const char *bat)
 		return smprintf("-");
 	} else if (strcmp(state, "Full") == 0) {
 		return smprintf("=");
+	} else if (strcmp(state, "Unknown") == 0) {
+		return smprintf("/");
 	} else {
 		return smprintf("?");
 	}
 }
 
+static char *
+cpu_freq(void)
+{
+	int freq;
+	FILE *fp;
+
+	fp = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r");
+	if (fp == NULL) {
+		warn("Failed to open file /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
+		return smprintf("%s", UNKNOWN_STR);
+	}
+	fscanf(fp, "%i", &freq);
+	fclose(fp);
+
+	return smprintf("%d", (freq + 500) / 1000);
+}
+
 static char *
 cpu_perc(void)
 {
@@ -325,6 +363,29 @@ kernel_release(void)
 	return smprintf("%s", udata.release);
 }
 
+static char *
+keyboard_indicators(void)
+{
+	Display *dpy = XOpenDisplay(NULL);
+	XKeyboardState state;
+	XGetKeyboardControl(dpy, &state);
+	XCloseDisplay(dpy);
+
+	switch (state.led_mask) {
+		case 1:
+			return smprintf("c");
+			break;
+		case 2:
+			return smprintf("n");
+			break;
+		case 3:
+			return smprintf("cn");
+			break;
+		default:
+			return smprintf("");
+	}
+}
+
 static char *
 load_avg(void)
 {
@@ -426,9 +487,9 @@ run_command(const char *cmd)
 	}
 	fgets(buf, sizeof(buf), fp);
 	pclose(fp);
-	buf[sizeof(buf)] = '\0';
+	buf[sizeof(buf) - 1] = '\0';
 
-	if ((nlptr = strstr(buf, "\n")) != NULL) {
+	if ((nlptr = strrchr(buf, '\n')) != NULL) {
 		nlptr[0] = '\0';
 	}
 
@@ -450,7 +511,7 @@ swap_free(void)
 		return smprintf("%s", UNKNOWN_STR);
 	}
 
-	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
+	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
 		warn("swap_free: read error");
 		fclose(fp);
 		return smprintf("%s", UNKNOWN_STR);
@@ -487,7 +548,7 @@ swap_perc(void)
 		return smprintf("%s", UNKNOWN_STR);
 	}
 
-	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
+	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
 		warn("swap_perc: read error");
 		fclose(fp);
 		return smprintf("%s", UNKNOWN_STR);
@@ -528,7 +589,7 @@ swap_total(void)
 		warn("Failed to open file /proc/meminfo");
 		return smprintf("%s", UNKNOWN_STR);
 	}
-	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
+	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
 		warn("swap_total: read error");
 		fclose(fp);
 		return smprintf("%s", UNKNOWN_STR);
@@ -559,7 +620,7 @@ swap_used(void)
 		warn("Failed to open file /proc/meminfo");
 		return smprintf("%s", UNKNOWN_STR);
 	}
-	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf), fp)) == 0) {
+	if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
 		warn("swap_used: read error");
 		fclose(fp);
 		return smprintf("%s", UNKNOWN_STR);
@@ -620,8 +681,7 @@ uptime(void)
 static char *
 username(void)
 {
-	uid_t uid = geteuid();
-	struct passwd *pw = getpwuid(uid);
+	struct passwd *pw = getpwuid(geteuid());
 
 	if (pw == NULL) {
 		warn("Failed to get username");
@@ -645,25 +705,29 @@ vol_perc(const char *card)
 	int v, afd, devmask;
 	char *vnames[] = SOUND_DEVICE_NAMES;
 
-	afd = open(card, O_RDONLY);
-	if (afd < 0) {
+	afd = open(card, O_RDONLY | O_NONBLOCK);
+	if (afd == -1) {
 		warn("Cannot open %s", card);
 		return smprintf(UNKNOWN_STR);
 	}
 
-	ioctl(afd, MIXER_READ(SOUND_MIXER_DEVMASK), &devmask);
+	if (ioctl(afd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
+		warn("Cannot get volume for %s", card);
+		close(afd);
+		return smprintf("%s", UNKNOWN_STR);
+	}
 	for (i = 0; i < (sizeof(vnames) / sizeof((vnames[0]))); i++) {
-		if (devmask & (1 << i)) {
-			if (!strcmp("vol", vnames[i])) {
-				ioctl(afd, MIXER_READ(i), &v);
+		if (devmask & (1 << i) && !strcmp("vol", vnames[i])) {
+			if (ioctl(afd, MIXER_READ(i), &v) == -1) {
+				warn("vol_perc: ioctl");
+				close(afd);
+				return smprintf("%s", UNKNOWN_STR);
 			}
 		}
 	}
 
 	close(afd);
-	if (v == 0) {
-		return smprintf("mute");
-	}
+
 	return smprintf("%d%%", v & 0xff);
 }
 
@@ -673,13 +737,14 @@ wifi_perc(const char *iface)
 	int perc;
 	char buf[255];
 	char *datastart;
+	char path[PATH_MAX];
 	char status[5];
 	FILE *fp;
 
-	ccat(3, "/sys/class/net/", iface, "/operstate");
-	fp = fopen(concat, "r");
+	snprintf(path, sizeof(path), "%s%s%s", "/sys/class/net/", iface, "/operstate");
+	fp = fopen(path, "r");
 	if (fp == NULL) {
-		warn("Failed to open file %s", concat);
+		warn("Failed to open file %s", path);
 		return smprintf("%s", UNKNOWN_STR);
 	}
 	fgets(status, 5, fp);
@@ -693,13 +758,13 @@ wifi_perc(const char *iface)
 		warn("Failed to open file /proc/net/wireless");
 		return smprintf("%s", UNKNOWN_STR);
 	}
-	ccat(2, iface, ":");
+
 	fgets(buf, sizeof(buf), fp);
 	fgets(buf, sizeof(buf), fp);
 	fgets(buf, sizeof(buf), fp);
 	fclose(fp);
 
-	if ((datastart = strstr(buf, concat)) == NULL) {
+	if ((datastart = strstr(buf, iface)) == NULL) {
 		return smprintf("%s", UNKNOWN_STR);
 	}
 	datastart = (datastart+(strlen(iface)+1));
@@ -748,7 +813,7 @@ sighandler(const int signo)
 static void
 usage(const int eval)
 {
-	fprintf(stderr, "usage: %s [-d] [-o] [-v] [-h]\n", argv0);
+	fprintf(stderr, "usage: %s [-d] [-o] [-n] [-v] [-h]\n", argv0);
 	exit(eval);
 }
 
@@ -768,8 +833,11 @@ main(int argc, char *argv[])
 		case 'o':
 			oflag = 1;
 			break;
+		case 'n':
+			nflag = 1;
+			break;
 		case 'v':
-			printf("slstatus (C) 2016 slstatus engineers\n");
+			printf("slstatus (C) 2016-2017 slstatus engineers\n");
 			return 0;
 		case 'h':
 			usage(0);
@@ -777,7 +845,7 @@ main(int argc, char *argv[])
 			usage(1);
 	} ARGEND
 
-	if (dflag && oflag) {
+	if ((dflag && oflag) || (dflag && nflag) || (oflag && nflag)) {
 		usage(1);
 	}
 	if (dflag && daemon(1, 1) < 0) {
@@ -810,18 +878,19 @@ main(int argc, char *argv[])
 				element = smprintf("%s", UNKNOWN_STR);
 				warnx("Failed to format output");
 			}
-			if (strlcat(status_string, element, sizeof(status_string)) >= sizeof(status_string)) {
-				warnx("Output too long");
-			}
+			strncat(status_string, element, sizeof(status_string) - strlen(status_string) - 1);
 			free(res);
 			free(element);
 		}
 
-		if (!oflag) {
+		if (oflag) {
+			printf("%s\n", status_string);
+		} else if (nflag) {
+			printf("%s\n", status_string);
+			done = 1;
+		} else {
 			XStoreName(dpy, DefaultRootWindow(dpy), status_string);
 			XSync(dpy, False);
-		} else {
-			printf("%s\n", status_string);
 		}
 
 		if ((UPDATE_INTERVAL - delay) <= 0) {