init
This commit is contained in:
		
							
								
								
									
										43
									
								
								slstatus/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								slstatus/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| ISC License | ||||
|  | ||||
| Copyright 2016-2022 Aaron Marcher <me@drkhsh.at> | ||||
|  | ||||
| Copyright 2016 Roy Freytag <rfreytag@hs-mittweida.de> | ||||
| Copyright 2016 Vincent Loupmon <vincentloupmon@gmail.com> | ||||
| Copyright 2016 Daniel Walter <d.walter@0x90.at> | ||||
| Copyright 2016-2018 Ali H. Fardan <raiz@firemail.cc> | ||||
| Copyright 2016 Jody Leonard <me@jodyleonard.com> | ||||
| Copyright 2016-2018 Quentin Rameau <quinq@fifth.space> | ||||
| Copyright 2016 Mike Coddington <mike@coddington.us> | ||||
| Copyright 2016-2018 Ivan J. <parazyd@dyne.org> | ||||
| Copyright 2017 Tobias Stoeckmann <tobias@stoeckmann.org> | ||||
| Copyright 2017-2018 Laslo Hunhold <dev@frign.de> | ||||
| Copyright 2018 Darron Anderson <darronanderson@protonmail.com> | ||||
| Copyright 2018 Josuah Demangeon <mail@josuah.net> | ||||
| Copyright 2018 Tobias Tschinkowitz <tobias@he4d.net> | ||||
| Copyright 2018 David Demelier <markand@malikania.fr> | ||||
| Copyright 2018-2012 Michael Buch <michaelbuch12@gmail.com> | ||||
| Copyright 2018 Ian Remmler <ian@remmler.org> | ||||
| Copyright 2016-2019 Joerg Jung <jung@openbsd.org> | ||||
| Copyright 2019 Ryan Kes <alrayyes@gmail.com> | ||||
| Copyright 2019 Cem Keylan <cem@ckyln.com> | ||||
| Copyright 2019 Dimitris Papastamos <dsp@2f30.org> | ||||
| Copyright 2019-2022 Ingo Feinerer <feinerer@logic.at> | ||||
| Copyright 2020 Alexandre Ratchov <alex@caoua.org> | ||||
| Copyright 2020 Mart Lubbers <mart@martlubbers.net> | ||||
| Copyright 2020 Daniel Moch <daniel@danielmoch.com> | ||||
| Copyright 2022 Nickolas Raymond Kaczynski <nrk@disroot.org> | ||||
| Copyright 2022 Patrick Iacob <iacobp@oregonstate.edu> | ||||
| Copyright 2021-2022 Steven Ward <planet36@gmail.com> | ||||
|  | ||||
| Permission to use, copy, modify, and/or distribute this software for any | ||||
| purpose with or without fee is hereby granted, provided that the above | ||||
| copyright notice and this permission notice appear in all copies. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
| WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
| MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
| ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
| OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
							
								
								
									
										69
									
								
								slstatus/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								slstatus/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| # See LICENSE file for copyright and license details | ||||
| # slstatus - suckless status monitor | ||||
| .POSIX: | ||||
|  | ||||
| include config.mk | ||||
|  | ||||
| REQ = util | ||||
| COM =\ | ||||
| 	components/battery\ | ||||
| 	components/cat\ | ||||
| 	components/cpu\ | ||||
| 	components/datetime\ | ||||
| 	components/disk\ | ||||
| 	components/entropy\ | ||||
| 	components/hostname\ | ||||
| 	components/ip\ | ||||
| 	components/kernel_release\ | ||||
| 	components/keyboard_indicators\ | ||||
| 	components/keymap\ | ||||
| 	components/load_avg\ | ||||
| 	components/netspeeds\ | ||||
| 	components/num_files\ | ||||
| 	components/ram\ | ||||
| 	components/run_command\ | ||||
| 	components/swap\ | ||||
| 	components/temperature\ | ||||
| 	components/uptime\ | ||||
| 	components/user\ | ||||
| 	components/volume\ | ||||
| 	components/wifi | ||||
|  | ||||
| all: slstatus | ||||
|  | ||||
| $(COM:=.o): config.mk $(REQ:=.h) slstatus.h | ||||
| slstatus.o: slstatus.c slstatus.h arg.h config.h config.mk $(REQ:=.h) | ||||
|  | ||||
| .c.o: | ||||
| 	$(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $< | ||||
|  | ||||
| config.h: | ||||
| 	cp config.def.h $@ | ||||
|  | ||||
| slstatus: slstatus.o $(COM:=.o) $(REQ:=.o) | ||||
| 	$(CC) -o $@ $(LDFLAGS) $(COM:=.o) $(REQ:=.o) slstatus.o $(LDLIBS) | ||||
|  | ||||
| clean: | ||||
| 	rm -f slstatus slstatus.o $(COM:=.o) $(REQ:=.o) slstatus-${VERSION}.tar.gz | ||||
|  | ||||
| dist: | ||||
| 	rm -rf "slstatus-$(VERSION)" | ||||
| 	mkdir -p "slstatus-$(VERSION)/components" | ||||
| 	cp -R LICENSE Makefile README config.mk config.def.h \ | ||||
| 	      arg.h slstatus.h slstatus.c $(REQ:=.c) $(REQ:=.h) \ | ||||
| 	      slstatus.1 "slstatus-$(VERSION)" | ||||
| 	cp -R $(COM:=.c) "slstatus-$(VERSION)/components" | ||||
| 	tar -cf - "slstatus-$(VERSION)" | gzip -c > "slstatus-$(VERSION).tar.gz" | ||||
| 	rm -rf "slstatus-$(VERSION)" | ||||
|  | ||||
| install: all | ||||
| 	mkdir -p "$(DESTDIR)$(PREFIX)/bin" | ||||
| 	cp -f slstatus "$(DESTDIR)$(PREFIX)/bin" | ||||
| 	chmod 755 "$(DESTDIR)$(PREFIX)/bin/slstatus" | ||||
| 	mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" | ||||
| 	cp -f slstatus.1 "$(DESTDIR)$(MANPREFIX)/man1" | ||||
| 	chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" | ||||
|  | ||||
| uninstall: | ||||
| 	rm -f "$(DESTDIR)$(PREFIX)/bin/slstatus" | ||||
| 	rm -f "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" | ||||
							
								
								
									
										65
									
								
								slstatus/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								slstatus/README
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| slstatus - suckless status | ||||
| ========================== | ||||
| slstatus is a small tool for providing system status information to other | ||||
| programs over the EWMH property of the root window (used by dwm(1)) or | ||||
| standard input/output. It is designed to be as efficient as possible by | ||||
| only issuing the minimum of system calls required. | ||||
|  | ||||
|  | ||||
| Features | ||||
| -------- | ||||
| - Battery percentage/state/time left | ||||
| - Cat (read file) | ||||
| - CPU usage | ||||
| - CPU frequency | ||||
| - Custom shell commands | ||||
| - Date and time | ||||
| - Disk status (free storage, percentage, total storage and used storage) | ||||
| - Available entropy | ||||
| - Username/GID/UID | ||||
| - Hostname | ||||
| - IP address (IPv4 and IPv6) | ||||
| - Kernel version | ||||
| - Keyboard indicators | ||||
| - Keymap | ||||
| - Load average | ||||
| - Network speeds (RX and TX) | ||||
| - Number of files in a directory (hint: Maildir) | ||||
| - Memory status (free memory, percentage, total memory and used memory) | ||||
| - Swap status (free swap, percentage, total swap and used swap) | ||||
| - Temperature | ||||
| - Uptime | ||||
| - Volume percentage | ||||
| - WiFi signal percentage and ESSID | ||||
|  | ||||
|  | ||||
| Requirements | ||||
| ------------ | ||||
| Currently slstatus works on FreeBSD, Linux and OpenBSD. | ||||
| In order to build slstatus you need the Xlib header files. | ||||
|  | ||||
| - For volume percentage on Linux the kernel module `snd-mixer-oss` must be | ||||
|   loaded. | ||||
| - For volume percentage on FreeBSD, `sndio` must be installed. | ||||
|  | ||||
|  | ||||
| Installation | ||||
| ------------ | ||||
| Edit config.mk to match your local setup (slstatus is installed into the | ||||
| /usr/local namespace by default). | ||||
|  | ||||
| Afterwards enter the following command to build and install slstatus (if | ||||
| necessary as root): | ||||
|  | ||||
|     make clean install | ||||
|  | ||||
|  | ||||
| Running slstatus | ||||
| ---------------- | ||||
| See the man page for details. | ||||
|  | ||||
|  | ||||
| Configuration | ||||
| ------------- | ||||
| slstatus can be customized by creating a custom config.h and (re)compiling the | ||||
| source code. This keeps it fast, secure and simple. | ||||
							
								
								
									
										33
									
								
								slstatus/arg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								slstatus/arg.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #ifndef ARG_H | ||||
| #define ARG_H | ||||
|  | ||||
| extern char *argv0; | ||||
|  | ||||
| /* int main(int argc, char *argv[]) */ | ||||
| #define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0);      \ | ||||
|                       *argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \ | ||||
|                  	int i_, argused_;                                         \ | ||||
|                  	if ((*argv)[1] == '-' && !(*argv)[2]) {                   \ | ||||
|                  		argc--, argv++;                                   \ | ||||
|                  		break;                                            \ | ||||
|                  	}                                                         \ | ||||
|                  	for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) {           \ | ||||
| 				switch ((*argv)[i_]) | ||||
| #define ARGEND   		if (argused_) {                                   \ | ||||
|                  			if ((*argv)[i_ + 1]) {                    \ | ||||
|                  				break;                            \ | ||||
|                  			} else {                                  \ | ||||
|                  				argc--, argv++;                   \ | ||||
|                  				break;                            \ | ||||
|                  			}                                         \ | ||||
|                  		}                                                 \ | ||||
|                  	}                                                         \ | ||||
|                  } | ||||
| #define ARGC()    ((*argv)[i_]) | ||||
| #define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) :        \ | ||||
|                   (*(argv + 1))     ? (argused_ = 1, *(argv + 1))        : (x)) | ||||
| #define EARGF(x) ARGF_(((x), exit(1), (char *)0)) | ||||
| #define ARGF()   ARGF_((char *)0) | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										247
									
								
								slstatus/components/battery.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								slstatus/components/battery.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| /* | ||||
|  * https://www.kernel.org/doc/html/latest/power/power_supply_class.html | ||||
|  */ | ||||
| 	#include <limits.h> | ||||
| 	#include <stdint.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	#define POWER_SUPPLY_CAPACITY "/sys/class/power_supply/%s/capacity" | ||||
| 	#define POWER_SUPPLY_STATUS   "/sys/class/power_supply/%s/status" | ||||
| 	#define POWER_SUPPLY_CHARGE   "/sys/class/power_supply/%s/charge_now" | ||||
| 	#define POWER_SUPPLY_ENERGY   "/sys/class/power_supply/%s/energy_now" | ||||
| 	#define POWER_SUPPLY_CURRENT  "/sys/class/power_supply/%s/current_now" | ||||
| 	#define POWER_SUPPLY_POWER    "/sys/class/power_supply/%s/power_now" | ||||
|  | ||||
| 	static const char * | ||||
| 	pick(const char *bat, const char *f1, const char *f2, char *path, | ||||
| 	     size_t length) | ||||
| 	{ | ||||
| 		if (esnprintf(path, length, f1, bat) > 0 && | ||||
| 		    access(path, R_OK) == 0) | ||||
| 			return f1; | ||||
|  | ||||
| 		if (esnprintf(path, length, f2, bat) > 0 && | ||||
| 		    access(path, R_OK) == 0) | ||||
| 			return f2; | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_perc(const char *bat) | ||||
| 	{ | ||||
| 		int cap_perc; | ||||
| 		char path[PATH_MAX]; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%d", &cap_perc) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", cap_perc); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_state(const char *bat) | ||||
| 	{ | ||||
| 		static struct { | ||||
| 			char *state; | ||||
| 			char *symbol; | ||||
| 		} map[] = { | ||||
| 			{ "Charging",    "+" }, | ||||
| 			{ "Discharging", "-" }, | ||||
| 			{ "Full",        "o" }, | ||||
| 			{ "Not charging", "o" }, | ||||
| 		}; | ||||
| 		size_t i; | ||||
| 		char path[PATH_MAX], state[12]; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%12[a-zA-Z ]", state) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		for (i = 0; i < LEN(map); i++) | ||||
| 			if (!strcmp(map[i].state, state)) | ||||
| 				break; | ||||
|  | ||||
| 		return (i == LEN(map)) ? "?" : map[i].symbol; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_remaining(const char *bat) | ||||
| 	{ | ||||
| 		uintmax_t charge_now, current_now, m, h; | ||||
| 		double timeleft; | ||||
| 		char path[PATH_MAX], state[12]; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%12[a-zA-Z ]", state) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path, | ||||
| 		          sizeof(path)) || | ||||
| 		    pscanf(path, "%ju", &charge_now) < 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!strcmp(state, "Discharging")) { | ||||
| 			if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path, | ||||
| 			          sizeof(path)) || | ||||
| 			    pscanf(path, "%ju", ¤t_now) < 0) | ||||
| 				return NULL; | ||||
|  | ||||
| 			if (current_now == 0) | ||||
| 				return NULL; | ||||
|  | ||||
| 			timeleft = (double)charge_now / (double)current_now; | ||||
| 			h = timeleft; | ||||
| 			m = (timeleft - (double)h) * 60; | ||||
|  | ||||
| 			return bprintf("%juh %jum", h, m); | ||||
| 		} | ||||
|  | ||||
| 		return ""; | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <fcntl.h> | ||||
| 	#include <machine/apmvar.h> | ||||
| 	#include <sys/ioctl.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	static int | ||||
| 	load_apm_power_info(struct apm_power_info *apm_info) | ||||
| 	{ | ||||
| 		int fd; | ||||
|  | ||||
| 		fd = open("/dev/apm", O_RDONLY); | ||||
| 		if (fd < 0) { | ||||
| 			warn("open '/dev/apm':"); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		memset(apm_info, 0, sizeof(struct apm_power_info)); | ||||
| 		if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) { | ||||
| 			warn("ioctl 'APM_IOC_GETPOWER':"); | ||||
| 			close(fd); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		return close(fd), 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct apm_power_info apm_info; | ||||
|  | ||||
| 		if (load_apm_power_info(&apm_info)) | ||||
| 			return bprintf("%d", apm_info.battery_life); | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_state(const char *unused) | ||||
| 	{ | ||||
| 		struct { | ||||
| 			unsigned int state; | ||||
| 			char *symbol; | ||||
| 		} map[] = { | ||||
| 			{ APM_AC_ON,      "+" }, | ||||
| 			{ APM_AC_OFF,     "-" }, | ||||
| 		}; | ||||
| 		struct apm_power_info apm_info; | ||||
| 		size_t i; | ||||
|  | ||||
| 		if (load_apm_power_info(&apm_info)) { | ||||
| 			for (i = 0; i < LEN(map); i++) | ||||
| 				if (map[i].state == apm_info.ac_state) | ||||
| 					break; | ||||
|  | ||||
| 			return (i == LEN(map)) ? "?" : map[i].symbol; | ||||
| 		} | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_remaining(const char *unused) | ||||
| 	{ | ||||
| 		struct apm_power_info apm_info; | ||||
| 		unsigned int h, m; | ||||
|  | ||||
| 		if (load_apm_power_info(&apm_info)) { | ||||
| 			if (apm_info.ac_state != APM_AC_ON) { | ||||
| 				h = apm_info.minutes_left / 60; | ||||
| 				m = apm_info.minutes_left % 60; | ||||
| 				return bprintf("%uh %02um", h, m); | ||||
| 			} else { | ||||
| 				return ""; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	#define BATTERY_LIFE  "hw.acpi.battery.life" | ||||
| 	#define BATTERY_STATE "hw.acpi.battery.state" | ||||
| 	#define BATTERY_TIME  "hw.acpi.battery.time" | ||||
|  | ||||
| 	const char * | ||||
| 	battery_perc(const char *unused) | ||||
| 	{ | ||||
| 		int cap_perc; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(cap_perc); | ||||
| 		if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", cap_perc); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_state(const char *unused) | ||||
| 	{ | ||||
| 		int state; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(state); | ||||
| 		if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		switch (state) { | ||||
| 		case 0: /* FALLTHROUGH */ | ||||
| 		case 2: | ||||
| 			return "+"; | ||||
| 		case 1: | ||||
| 			return "-"; | ||||
| 		default: | ||||
| 			return "?"; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_remaining(const char *unused) | ||||
| 	{ | ||||
| 		int rem; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(rem); | ||||
| 		if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len | ||||
| 		    || rem < 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%uh %02um", rem / 60, rem % 60); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										32
									
								
								slstatus/components/cat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								slstatus/components/cat.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| cat(const char *path) | ||||
| { | ||||
|         char *f; | ||||
|         FILE *fp; | ||||
|  | ||||
|         if (!(fp = fopen(path, "r"))) { | ||||
|                 warn("fopen '%s':", path); | ||||
|                 return NULL; | ||||
|         } | ||||
|  | ||||
|         f = fgets(buf, sizeof(buf) - 1, fp); | ||||
|         if (fclose(fp) < 0) { | ||||
|                 warn("fclose '%s':", path); | ||||
|                 return NULL; | ||||
|         } | ||||
|         if (!f) | ||||
|                 return NULL; | ||||
|  | ||||
|         if ((f = strrchr(buf, '\n'))) | ||||
|                 f[0] = '\0'; | ||||
|  | ||||
|         return buf[0] ? buf : NULL; | ||||
| } | ||||
|  | ||||
							
								
								
									
										157
									
								
								slstatus/components/cpu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								slstatus/components/cpu.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_freq(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t freq; | ||||
|  | ||||
| 		/* in kHz */ | ||||
| 		if (pscanf(CPU_FREQ, "%ju", &freq) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(freq * 1000, 1000); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_perc(const char *unused) | ||||
| 	{ | ||||
| 		static long double a[7]; | ||||
| 		long double b[7], sum; | ||||
|  | ||||
| 		memcpy(b, a, sizeof(b)); | ||||
| 		/* cpu user nice system idle iowait irq softirq */ | ||||
| 		if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf", | ||||
| 		           &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) | ||||
| 		    != 7) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (b[0] == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) - | ||||
| 		      (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]); | ||||
|  | ||||
| 		if (sum == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", (int)(100 * | ||||
| 		               ((b[0] + b[1] + b[2] + b[5] + b[6]) - | ||||
| 		                (a[0] + a[1] + a[2] + a[5] + a[6])) / sum)); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <sys/param.h> | ||||
| 	#include <sys/sched.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_freq(const char *unused) | ||||
| 	{ | ||||
| 		int freq, mib[2]; | ||||
| 		size_t size; | ||||
|  | ||||
| 		mib[0] = CTL_HW; | ||||
| 		mib[1] = HW_CPUSPEED; | ||||
|  | ||||
| 		size = sizeof(freq); | ||||
|  | ||||
| 		/* in MHz */ | ||||
| 		if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { | ||||
| 			warn("sysctl 'HW_CPUSPEED':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		return fmt_human(freq * 1E6, 1000); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_perc(const char *unused) | ||||
| 	{ | ||||
| 		int mib[2]; | ||||
| 		static uintmax_t a[CPUSTATES]; | ||||
| 		uintmax_t b[CPUSTATES], sum; | ||||
| 		size_t size; | ||||
|  | ||||
| 		mib[0] = CTL_KERN; | ||||
| 		mib[1] = KERN_CPTIME; | ||||
|  | ||||
| 		size = sizeof(a); | ||||
|  | ||||
| 		memcpy(b, a, sizeof(b)); | ||||
| 		if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) { | ||||
| 			warn("sysctl 'KERN_CPTIME':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (b[0] == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - | ||||
| 		      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); | ||||
|  | ||||
| 		if (sum == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * | ||||
| 		               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + | ||||
| 		                 a[CP_INTR]) - | ||||
| 		                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + | ||||
| 		                 b[CP_INTR])) / sum); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <devstat.h> | ||||
| 	#include <sys/param.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_freq(const char *unused) | ||||
| 	{ | ||||
| 		int freq; | ||||
| 		size_t size; | ||||
|  | ||||
| 		size = sizeof(freq); | ||||
| 		/* in MHz */ | ||||
| 		if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) { | ||||
| 			warn("sysctlbyname 'hw.clockrate':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		return fmt_human(freq * 1E6, 1000); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_perc(const char *unused) | ||||
| 	{ | ||||
| 		size_t size; | ||||
| 		static long a[CPUSTATES]; | ||||
| 		long b[CPUSTATES], sum; | ||||
|  | ||||
| 		size = sizeof(a); | ||||
| 		memcpy(b, a, sizeof(b)); | ||||
| 		if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) { | ||||
| 			warn("sysctlbyname 'kern.cp_time':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (b[0] == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - | ||||
| 		      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); | ||||
|  | ||||
| 		if (sum == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * | ||||
| 		               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + | ||||
| 		                 a[CP_INTR]) - | ||||
| 		                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + | ||||
| 		                 b[CP_INTR])) / sum); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										20
									
								
								slstatus/components/datetime.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								slstatus/components/datetime.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| datetime(const char *fmt) | ||||
| { | ||||
| 	time_t t; | ||||
|  | ||||
| 	t = time(NULL); | ||||
| 	if (!strftime(buf, sizeof(buf), fmt, localtime(&t))) { | ||||
| 		warn("strftime: Result string exceeds buffer size"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return buf; | ||||
| } | ||||
							
								
								
									
										59
									
								
								slstatus/components/disk.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								slstatus/components/disk.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <sys/statvfs.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| disk_free(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return fmt_human(fs.f_frsize * fs.f_bavail, 1024); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| disk_perc(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%d", (int)(100 * | ||||
| 	               (1 - ((double)fs.f_bavail / (double)fs.f_blocks)))); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| disk_total(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return fmt_human(fs.f_frsize * fs.f_blocks, 1024); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| disk_used(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return fmt_human(fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024); | ||||
| } | ||||
							
								
								
									
										29
									
								
								slstatus/components/entropy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								slstatus/components/entropy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include "../slstatus.h" | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
| 	#include <stdio.h> | ||||
|  | ||||
| 	#include "../util.h" | ||||
|  | ||||
| 	#define ENTROPY_AVAIL "/proc/sys/kernel/random/entropy_avail" | ||||
|  | ||||
| 	const char * | ||||
| 	entropy(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t num; | ||||
|  | ||||
| 		if (pscanf(ENTROPY_AVAIL, "%ju", &num) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%ju", num); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | defined(__FreeBSD__) | ||||
| 	const char * | ||||
| 	entropy(const char *unused) | ||||
| 	{ | ||||
| 		// https://www.unicode.org/charts/PDF/U2200.pdf | ||||
| 		/* Unicode Character 'INFINITY' (U+221E) */ | ||||
| 		return "\u221E"; | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										17
									
								
								slstatus/components/hostname.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								slstatus/components/hostname.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| hostname(const char *unused) | ||||
| { | ||||
| 	if (gethostname(buf, sizeof(buf)) < 0) { | ||||
| 		warn("gethostbyname:"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return buf; | ||||
| } | ||||
							
								
								
									
										61
									
								
								slstatus/components/ip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								slstatus/components/ip.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ifaddrs.h> | ||||
| #include <netdb.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #if defined(__OpenBSD__) | ||||
| 	#include <sys/socket.h> | ||||
| 	#include <sys/types.h> | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <netinet/in.h> | ||||
| 	#include <sys/socket.h> | ||||
| #endif | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| static const char * | ||||
| ip(const char *interface, unsigned short sa_family) | ||||
| { | ||||
| 	struct ifaddrs *ifaddr, *ifa; | ||||
| 	int s; | ||||
| 	char host[NI_MAXHOST]; | ||||
|  | ||||
| 	if (getifaddrs(&ifaddr) < 0) { | ||||
| 		warn("getifaddrs:"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { | ||||
| 		if (!ifa->ifa_addr) | ||||
| 			continue; | ||||
|  | ||||
| 		s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), | ||||
| 		                host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); | ||||
| 		if (!strcmp(ifa->ifa_name, interface) && | ||||
| 		    (ifa->ifa_addr->sa_family == sa_family)) { | ||||
| 			freeifaddrs(ifaddr); | ||||
| 			if (s != 0) { | ||||
| 				warn("getnameinfo: %s", gai_strerror(s)); | ||||
| 				return NULL; | ||||
| 			} | ||||
| 			return bprintf("%s", host); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	freeifaddrs(ifaddr); | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| ipv4(const char *interface) | ||||
| { | ||||
| 	return ip(interface, AF_INET); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| ipv6(const char *interface) | ||||
| { | ||||
| 	return ip(interface, AF_INET6); | ||||
| } | ||||
							
								
								
									
										19
									
								
								slstatus/components/kernel_release.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								slstatus/components/kernel_release.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <sys/utsname.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| kernel_release(const char *unused) | ||||
| { | ||||
| 	struct utsname udata; | ||||
|  | ||||
| 	if (uname(&udata) < 0) { | ||||
| 		warn("uname:"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%s", udata.release); | ||||
| } | ||||
							
								
								
									
										50
									
								
								slstatus/components/keyboard_indicators.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								slstatus/components/keyboard_indicators.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ctype.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| /* | ||||
|  * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num | ||||
|  * lock, each optionally followed by '?', in the order of indicators desired. | ||||
|  * If followed by '?', the letter with case preserved is included in the output | ||||
|  * if the corresponding indicator is on.  Otherwise, the letter is always | ||||
|  * included, lowercase when off and uppercase when on. | ||||
|  */ | ||||
| const char * | ||||
| keyboard_indicators(const char *fmt) | ||||
| { | ||||
| 	Display *dpy; | ||||
| 	XKeyboardState state; | ||||
| 	size_t fmtlen, i, n; | ||||
| 	int togglecase, isset; | ||||
| 	char key; | ||||
|  | ||||
| 	if (!(dpy = XOpenDisplay(NULL))) { | ||||
| 		warn("XOpenDisplay: Failed to open display"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	XGetKeyboardControl(dpy, &state); | ||||
| 	XCloseDisplay(dpy); | ||||
|  | ||||
| 	fmtlen = strnlen(fmt, 4); | ||||
| 	for (i = n = 0; i < fmtlen; i++) { | ||||
| 		key = tolower(fmt[i]); | ||||
| 		if (key != 'c' && key != 'n') | ||||
| 			continue; | ||||
|  | ||||
| 		togglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?'); | ||||
| 		isset = (state.led_mask & (1 << (key == 'n'))); | ||||
|  | ||||
| 		if (togglecase) | ||||
| 			buf[n++] = isset ? toupper(key) : key; | ||||
| 		else if (isset) | ||||
| 			buf[n++] = fmt[i]; | ||||
| 	} | ||||
|  | ||||
| 	buf[n] = 0; | ||||
| 	return buf; | ||||
| } | ||||
							
								
								
									
										86
									
								
								slstatus/components/keymap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								slstatus/components/keymap.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ctype.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <X11/XKBlib.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| static int | ||||
| valid_layout_or_variant(char *sym) | ||||
| { | ||||
| 	size_t i; | ||||
| 	/* invalid symbols from xkb rules config */ | ||||
| 	static const char *invalid[] = { "evdev", "inet", "pc", "base" }; | ||||
|  | ||||
| 	for (i = 0; i < LEN(invalid); i++) | ||||
| 		if (!strncmp(sym, invalid[i], strlen(invalid[i]))) | ||||
| 			return 0; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| get_layout(char *syms, int grp_num) | ||||
| { | ||||
| 	char *tok, *layout; | ||||
| 	int grp; | ||||
|  | ||||
| 	layout = NULL; | ||||
| 	tok = strtok(syms, "+:"); | ||||
| 	for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) { | ||||
| 		if (!valid_layout_or_variant(tok)) { | ||||
| 			continue; | ||||
| 		} else if (strlen(tok) == 1 && isdigit(tok[0])) { | ||||
| 			/* ignore :2, :3, :4 (additional layout groups) */ | ||||
| 			continue; | ||||
| 		} | ||||
| 		layout = tok; | ||||
| 		grp++; | ||||
| 	} | ||||
|  | ||||
| 	return layout; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| keymap(const char *unused) | ||||
| { | ||||
| 	Display *dpy; | ||||
| 	XkbDescRec *desc; | ||||
| 	XkbStateRec state; | ||||
| 	char *symbols; | ||||
| 	const char *layout; | ||||
|  | ||||
| 	layout = NULL; | ||||
|  | ||||
| 	if (!(dpy = XOpenDisplay(NULL))) { | ||||
| 		warn("XOpenDisplay: Failed to open display"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	if (!(desc = XkbAllocKeyboard())) { | ||||
| 		warn("XkbAllocKeyboard: Failed to allocate keyboard"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) { | ||||
| 		warn("XkbGetNames: Failed to retrieve key symbols"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	if (XkbGetState(dpy, XkbUseCoreKbd, &state)) { | ||||
| 		warn("XkbGetState: Failed to retrieve keyboard state"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) { | ||||
| 		warn("XGetAtomName: Failed to get atom name"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	layout = bprintf("%s", get_layout(symbols, state.group)); | ||||
| 	XFree(symbols); | ||||
| end: | ||||
| 	XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); | ||||
| 	if (XCloseDisplay(dpy)) | ||||
| 		warn("XCloseDisplay: Failed to close display"); | ||||
|  | ||||
| 	return layout; | ||||
| } | ||||
							
								
								
									
										19
									
								
								slstatus/components/load_avg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								slstatus/components/load_avg.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| load_avg(const char *unused) | ||||
| { | ||||
| 	double avgs[3]; | ||||
|  | ||||
| 	if (getloadavg(avgs, 3) < 0) { | ||||
| 		warn("getloadavg: Failed to obtain load average"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]); | ||||
| } | ||||
							
								
								
									
										129
									
								
								slstatus/components/netspeeds.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								slstatus/components/netspeeds.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
|  | ||||
| 	#define NET_RX_BYTES "/sys/class/net/%s/statistics/rx_bytes" | ||||
| 	#define NET_TX_BYTES "/sys/class/net/%s/statistics/tx_bytes" | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_rx(const char *interface) | ||||
| 	{ | ||||
| 		uintmax_t oldrxbytes; | ||||
| 		static uintmax_t rxbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		char path[PATH_MAX]; | ||||
|  | ||||
| 		oldrxbytes = rxbytes; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), NET_RX_BYTES, interface) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%ju", &rxbytes) != 1) | ||||
| 			return NULL; | ||||
| 		if (oldrxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_tx(const char *interface) | ||||
| 	{ | ||||
| 		uintmax_t oldtxbytes; | ||||
| 		static uintmax_t txbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		char path[PATH_MAX]; | ||||
|  | ||||
| 		oldtxbytes = txbytes; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), NET_TX_BYTES, interface) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%ju", &txbytes) != 1) | ||||
| 			return NULL; | ||||
| 		if (oldtxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((txbytes - oldtxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | defined(__FreeBSD__) | ||||
| 	#include <ifaddrs.h> | ||||
| 	#include <net/if.h> | ||||
| 	#include <string.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <sys/socket.h> | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_rx(const char *interface) | ||||
| 	{ | ||||
| 		struct ifaddrs *ifal, *ifa; | ||||
| 		struct if_data *ifd; | ||||
| 		uintmax_t oldrxbytes; | ||||
| 		static uintmax_t rxbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		int if_ok = 0; | ||||
|  | ||||
| 		oldrxbytes = rxbytes; | ||||
|  | ||||
| 		if (getifaddrs(&ifal) < 0) { | ||||
| 			warn("getifaddrs failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		rxbytes = 0; | ||||
| 		for (ifa = ifal; ifa; ifa = ifa->ifa_next) | ||||
| 			if (!strcmp(ifa->ifa_name, interface) && | ||||
| 			   (ifd = (struct if_data *)ifa->ifa_data)) | ||||
| 				rxbytes += ifd->ifi_ibytes, if_ok = 1; | ||||
|  | ||||
| 		freeifaddrs(ifal); | ||||
| 		if (!if_ok) { | ||||
| 			warn("reading 'if_data' failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (oldrxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_tx(const char *interface) | ||||
| 	{ | ||||
| 		struct ifaddrs *ifal, *ifa; | ||||
| 		struct if_data *ifd; | ||||
| 		uintmax_t oldtxbytes; | ||||
| 		static uintmax_t txbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		int if_ok = 0; | ||||
|  | ||||
| 		oldtxbytes = txbytes; | ||||
|  | ||||
| 		if (getifaddrs(&ifal) < 0) { | ||||
| 			warn("getifaddrs failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		txbytes = 0; | ||||
| 		for (ifa = ifal; ifa; ifa = ifa->ifa_next) | ||||
| 			if (!strcmp(ifa->ifa_name, interface) && | ||||
| 			   (ifd = (struct if_data *)ifa->ifa_data)) | ||||
| 				txbytes += ifd->ifi_obytes, if_ok = 1; | ||||
|  | ||||
| 		freeifaddrs(ifal); | ||||
| 		if (!if_ok) { | ||||
| 			warn("reading 'if_data' failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (oldtxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((txbytes - oldtxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										32
									
								
								slstatus/components/num_files.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								slstatus/components/num_files.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <dirent.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| num_files(const char *path) | ||||
| { | ||||
| 	struct dirent *dp; | ||||
| 	DIR *dir; | ||||
| 	int num; | ||||
|  | ||||
| 	if (!(dir = opendir(path))) { | ||||
| 		warn("opendir '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	num = 0; | ||||
| 	while ((dp = readdir(dir))) { | ||||
| 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) | ||||
| 			continue; /* skip self and parent */ | ||||
|  | ||||
| 		num++; | ||||
| 	} | ||||
|  | ||||
| 	closedir(dir); | ||||
|  | ||||
| 	return bprintf("%d", num); | ||||
| } | ||||
							
								
								
									
										212
									
								
								slstatus/components/ram.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								slstatus/components/ram.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,212 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
|  | ||||
| 	const char * | ||||
| 	ram_free(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t free; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", | ||||
| 		           "MemTotal: %ju kB\n" | ||||
| 		           "MemFree: %ju kB\n" | ||||
| 		           "MemAvailable: %ju kB\n", | ||||
| 		           &free, &free, &free) != 3) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(free * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_perc(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t total, free, buffers, cached; | ||||
| 		int percent; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", | ||||
| 		           "MemTotal: %ju kB\n" | ||||
| 		           "MemFree: %ju kB\n" | ||||
| 		           "MemAvailable: %ju kB\n" | ||||
| 		           "Buffers: %ju kB\n" | ||||
| 		           "Cached: %ju kB\n", | ||||
| 		           &total, &free, &buffers, &buffers, &cached) != 5) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (total == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		percent = 100 * ((total - free) - (buffers + cached)) / total; | ||||
| 		return bprintf("%d", percent); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_total(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t total; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", "MemTotal: %ju kB\n", &total) | ||||
| 		    != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(total * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_used(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t total, free, buffers, cached, used; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", | ||||
| 		           "MemTotal: %ju kB\n" | ||||
| 		           "MemFree: %ju kB\n" | ||||
| 		           "MemAvailable: %ju kB\n" | ||||
| 		           "Buffers: %ju kB\n" | ||||
| 		           "Cached: %ju kB\n", | ||||
| 		           &total, &free, &buffers, &buffers, &cached) != 5) | ||||
| 			return NULL; | ||||
|  | ||||
| 		used = (total - free - buffers - cached); | ||||
| 		return fmt_human(used * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/sysctl.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	#define LOG1024 10 | ||||
| 	#define pagetok(size, pageshift) (size_t)(size << (pageshift - LOG1024)) | ||||
|  | ||||
| 	inline int | ||||
| 	load_uvmexp(struct uvmexp *uvmexp) | ||||
| 	{ | ||||
| 		int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; | ||||
| 		size_t size; | ||||
|  | ||||
| 		size = sizeof(*uvmexp); | ||||
|  | ||||
| 		if (sysctl(uvmexp_mib, 2, uvmexp, &size, NULL, 0) >= 0) | ||||
| 			return 1; | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_free(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
| 		int free_pages; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		free_pages = uvmexp.npages - uvmexp.active; | ||||
| 		return fmt_human(pagetok(free_pages, uvmexp.pageshift) * | ||||
| 				 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
| 		int percent; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		percent = uvmexp.active * 100 / uvmexp.npages; | ||||
| 		return bprintf("%d", percent); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_total(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(pagetok(uvmexp.npages, | ||||
| 					 uvmexp.pageshift) * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_used(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(pagetok(uvmexp.active, | ||||
| 					 uvmexp.pageshift) * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <sys/sysctl.h> | ||||
| 	#include <sys/vmmeter.h> | ||||
| 	#include <unistd.h> | ||||
| 	#include <vm/vm_param.h> | ||||
|  | ||||
| 	const char * | ||||
| 	ram_free(const char *unused) { | ||||
| 		struct vmtotal vm_stats; | ||||
| 		int mib[] = {CTL_VM, VM_TOTAL}; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(struct vmtotal); | ||||
| 		if (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0 | ||||
| 		    || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(vm_stats.t_free * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_total(const char *unused) { | ||||
| 		unsigned int npages; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(npages); | ||||
| 		if (sysctlbyname("vm.stats.vm.v_page_count", | ||||
| 		                 &npages, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(npages * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_perc(const char *unused) { | ||||
| 		unsigned int npages; | ||||
| 		unsigned int active; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(npages); | ||||
| 		if (sysctlbyname("vm.stats.vm.v_page_count", | ||||
| 		                 &npages, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (sysctlbyname("vm.stats.vm.v_active_count", | ||||
| 		                 &active, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", active * 100 / npages); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_used(const char *unused) { | ||||
| 		unsigned int active; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(active); | ||||
| 		if (sysctlbyname("vm.stats.vm.v_active_count", | ||||
| 		                 &active, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(active * getpagesize(), 1024); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										31
									
								
								slstatus/components/run_command.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								slstatus/components/run_command.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| run_command(const char *cmd) | ||||
| { | ||||
| 	char *p; | ||||
| 	FILE *fp; | ||||
|  | ||||
| 	if (!(fp = popen(cmd, "r"))) { | ||||
| 		warn("popen '%s':", cmd); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	p = fgets(buf, sizeof(buf) - 1, fp); | ||||
| 	if (pclose(fp) < 0) { | ||||
| 		warn("pclose '%s':", cmd); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	if (!p) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if ((p = strrchr(buf, '\n'))) | ||||
| 		p[0] = '\0'; | ||||
|  | ||||
| 	return buf[0] ? buf : NULL; | ||||
| } | ||||
							
								
								
									
										274
									
								
								slstatus/components/swap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								slstatus/components/swap.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,274 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	static int | ||||
| 	get_swap_info(long *s_total, long *s_free, long *s_cached) | ||||
| 	{ | ||||
| 		FILE *fp; | ||||
| 		struct { | ||||
| 			const char *name; | ||||
| 			const size_t len; | ||||
| 			long *var; | ||||
| 		} ent[] = { | ||||
| 			{ "SwapTotal",  sizeof("SwapTotal") - 1,  s_total  }, | ||||
| 			{ "SwapFree",   sizeof("SwapFree") - 1,   s_free   }, | ||||
| 			{ "SwapCached", sizeof("SwapCached") - 1, s_cached }, | ||||
| 		}; | ||||
| 		size_t line_len = 0, i, left; | ||||
| 		char *line = NULL; | ||||
|  | ||||
| 		/* get number of fields we want to extract */ | ||||
| 		for (i = 0, left = 0; i < LEN(ent); i++) | ||||
| 			if (ent[i].var) | ||||
| 				left++; | ||||
|  | ||||
| 		if (!(fp = fopen("/proc/meminfo", "r"))) { | ||||
| 			warn("fopen '/proc/meminfo':"); | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		/* read file line by line and extract field information */ | ||||
| 		while (left > 0 && getline(&line, &line_len, fp) >= 0) { | ||||
| 			for (i = 0; i < LEN(ent); i++) { | ||||
| 				if (ent[i].var && | ||||
| 				    !strncmp(line, ent[i].name, ent[i].len)) { | ||||
| 					sscanf(line + ent[i].len + 1, | ||||
| 					       "%ld kB\n", ent[i].var); | ||||
| 					left--; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		free(line); | ||||
| 		if (ferror(fp)) { | ||||
| 			warn("getline '/proc/meminfo':"); | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		fclose(fp); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_free(const char *unused) | ||||
| 	{ | ||||
| 		long free; | ||||
|  | ||||
| 		if (get_swap_info(NULL, &free, NULL)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(free * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_perc(const char *unused) | ||||
| 	{ | ||||
| 		long total, free, cached; | ||||
|  | ||||
| 		if (get_swap_info(&total, &free, &cached) || total == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * (total - free - cached) / total); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_total(const char *unused) | ||||
| 	{ | ||||
| 		long total; | ||||
|  | ||||
| 		if (get_swap_info(&total, NULL, NULL)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(total * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_used(const char *unused) | ||||
| 	{ | ||||
| 		long total, free, cached; | ||||
|  | ||||
| 		if (get_swap_info(&total, &free, &cached)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((total - free - cached) * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/swap.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	static int | ||||
| 	getstats(int *total, int *used) | ||||
| 	{ | ||||
| 		struct swapent *sep, *fsep; | ||||
| 		int rnswap, nswap, i; | ||||
|  | ||||
| 		if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) { | ||||
| 			warn("swaptctl 'SWAP_NSWAP':"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 		if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) { | ||||
| 			warn("calloc 'nswap':"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 		if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) { | ||||
| 			warn("swapctl 'SWAP_STATA':"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 		if (nswap != rnswap) { | ||||
| 			warn("getstats: SWAP_STATS != SWAP_NSWAP"); | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		*total = 0; | ||||
| 		*used = 0; | ||||
|  | ||||
| 		for (i = 0; i < rnswap; i++) { | ||||
| 			*total += sep->se_nblks >> 1; | ||||
| 			*used += sep->se_inuse >> 1; | ||||
| 		} | ||||
|  | ||||
| 		free(fsep); | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_free(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((total - used) * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_perc(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (total == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * used / total); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_total(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(total * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_used(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(used * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <fcntl.h> | ||||
| 	#include <kvm.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	static int getswapinfo(struct kvm_swap *swap_info, size_t size) | ||||
| 	{ | ||||
| 		kvm_t *kd; | ||||
|  | ||||
| 		kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, NULL); | ||||
| 		if (kd == NULL) { | ||||
| 			warn("kvm_openfiles '/dev/null':"); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		if (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) { | ||||
| 			warn("kvm_getswapinfo:"); | ||||
| 			kvm_close(kd); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		kvm_close(kd); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_free(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long used, total; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		total = swap_info[0].ksw_total; | ||||
| 		used = swap_info[0].ksw_used; | ||||
|  | ||||
| 		return fmt_human((total - used) * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long used, total; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		total = swap_info[0].ksw_total; | ||||
| 		used = swap_info[0].ksw_used; | ||||
|  | ||||
| 		return bprintf("%d", used * 100 / total); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_total(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long total; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		total = swap_info[0].ksw_total; | ||||
|  | ||||
| 		return fmt_human(total * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_used(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long used; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		used = swap_info[0].ksw_used; | ||||
|  | ||||
| 		return fmt_human(used * getpagesize(), 1024); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										73
									
								
								slstatus/components/temperature.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								slstatus/components/temperature.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stddef.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
|  | ||||
| 	const char * | ||||
| 	temp(const char *file) | ||||
| 	{ | ||||
| 		uintmax_t temp; | ||||
|  | ||||
| 		if (pscanf(file, "%ju", &temp) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%ju", temp / 1000); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <stdio.h> | ||||
| 	#include <sys/time.h> /* before <sys/sensors.h> for struct timeval */ | ||||
| 	#include <sys/sensors.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	const char * | ||||
| 	temp(const char *unused) | ||||
| 	{ | ||||
| 		int mib[5]; | ||||
| 		size_t size; | ||||
| 		struct sensor temp; | ||||
|  | ||||
| 		mib[0] = CTL_HW; | ||||
| 		mib[1] = HW_SENSORS; | ||||
| 		mib[2] = 0; /* cpu0 */ | ||||
| 		mib[3] = SENSOR_TEMP; | ||||
| 		mib[4] = 0; /* temp0 */ | ||||
|  | ||||
| 		size = sizeof(temp); | ||||
|  | ||||
| 		if (sysctl(mib, 5, &temp, &size, NULL, 0) < 0) { | ||||
| 			warn("sysctl 'SENSOR_TEMP':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		/* kelvin to celsius */ | ||||
| 		return bprintf("%d", (int)((float)(temp.value-273150000) / 1E6)); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <stdio.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	#define ACPI_TEMP "hw.acpi.thermal.%s.temperature" | ||||
|  | ||||
| 	const char * | ||||
| 	temp(const char *zone) | ||||
| 	{ | ||||
| 		char buf[256]; | ||||
| 		int temp; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(temp); | ||||
| 		snprintf(buf, sizeof(buf), ACPI_TEMP, zone); | ||||
| 		if (sysctlbyname(buf, &temp, &len, NULL, 0) < 0 | ||||
| 				|| !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		/* kelvin to decimal celcius */ | ||||
| 		return bprintf("%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10)); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										34
									
								
								slstatus/components/uptime.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								slstatus/components/uptime.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(CLOCK_BOOTTIME) | ||||
| 	#define UPTIME_FLAG CLOCK_BOOTTIME | ||||
| #elif defined(CLOCK_UPTIME) | ||||
| 	#define UPTIME_FLAG CLOCK_UPTIME | ||||
| #else | ||||
| 	#define UPTIME_FLAG CLOCK_MONOTONIC | ||||
| #endif | ||||
|  | ||||
| const char * | ||||
| uptime(const char *unused) | ||||
| { | ||||
| 	char warn_buf[256]; | ||||
| 	uintmax_t h, m; | ||||
| 	struct timespec uptime; | ||||
|  | ||||
| 	if (clock_gettime(UPTIME_FLAG, &uptime) < 0) { | ||||
| 		snprintf(warn_buf, sizeof(warn_buf), "clock_gettime %d", UPTIME_FLAG); | ||||
| 		warn(warn_buf); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	h = uptime.tv_sec / 3600; | ||||
| 	m = uptime.tv_sec % 3600 / 60; | ||||
|  | ||||
| 	return bprintf("%juh %jum", h, m); | ||||
| } | ||||
							
								
								
									
										33
									
								
								slstatus/components/user.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								slstatus/components/user.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <pwd.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| gid(const char *unused) | ||||
| { | ||||
| 	return bprintf("%d", getgid()); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| username(const char *unused) | ||||
| { | ||||
| 	struct passwd *pw; | ||||
|  | ||||
| 	if (!(pw = getpwuid(geteuid()))) { | ||||
| 		warn("getpwuid '%d':", geteuid()); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%s", pw->pw_name); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| uid(const char *unused) | ||||
| { | ||||
| 	return bprintf("%d", geteuid()); | ||||
| } | ||||
							
								
								
									
										219
									
								
								slstatus/components/volume.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								slstatus/components/volume.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__OpenBSD__) | defined(__FreeBSD__) | ||||
| 	#include <poll.h> | ||||
| 	#include <sndio.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/queue.h> | ||||
|  | ||||
| 	struct control { | ||||
| 		LIST_ENTRY(control)	next; | ||||
| 		unsigned int		addr; | ||||
| 	#define CTRL_NONE	0 | ||||
| 	#define CTRL_LEVEL	1 | ||||
| 	#define CTRL_MUTE	2 | ||||
| 		unsigned int		type; | ||||
| 		unsigned int		maxval; | ||||
| 		unsigned int		val; | ||||
| 	}; | ||||
|  | ||||
| 	static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls); | ||||
| 	static struct pollfd *pfds; | ||||
| 	static struct sioctl_hdl *hdl; | ||||
| 	static int initialized; | ||||
|  | ||||
| 	/* | ||||
| 	 * Call-back to obtain the description of all audio controls. | ||||
| 	 */ | ||||
| 	static void | ||||
| 	ondesc(void *unused, struct sioctl_desc *desc, int val) | ||||
| 	{ | ||||
| 		struct control *c, *ctmp; | ||||
| 		unsigned int type = CTRL_NONE; | ||||
|  | ||||
| 		if (desc == NULL) | ||||
| 			return; | ||||
|  | ||||
| 		/* Delete existing audio control with the same address. */ | ||||
| 		LIST_FOREACH_SAFE(c, &controls, next, ctmp) { | ||||
| 			if (desc->addr == c->addr) { | ||||
| 				LIST_REMOVE(c, next); | ||||
| 				free(c); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* Only match output.level and output.mute audio controls. */ | ||||
| 		if (desc->group[0] != 0 || | ||||
| 		    strcmp(desc->node0.name, "output") != 0) | ||||
| 			return; | ||||
| 		if (desc->type == SIOCTL_NUM && | ||||
| 		    strcmp(desc->func, "level") == 0) | ||||
| 			type = CTRL_LEVEL; | ||||
| 		else if (desc->type == SIOCTL_SW && | ||||
| 			 strcmp(desc->func, "mute") == 0) | ||||
| 			type = CTRL_MUTE; | ||||
| 		else | ||||
| 			return; | ||||
|  | ||||
| 		c = malloc(sizeof(struct control)); | ||||
| 		if (c == NULL) { | ||||
| 			warn("sndio: failed to allocate audio control\n"); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		c->addr = desc->addr; | ||||
| 		c->type = type; | ||||
| 		c->maxval = desc->maxval; | ||||
| 		c->val = val; | ||||
| 		LIST_INSERT_HEAD(&controls, c, next); | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Call-back invoked whenever an audio control changes. | ||||
| 	 */ | ||||
| 	static void | ||||
| 	onval(void *unused, unsigned int addr, unsigned int val) | ||||
| 	{ | ||||
| 		struct control *c; | ||||
|  | ||||
| 		LIST_FOREACH(c, &controls, next) { | ||||
| 			if (c->addr == addr) | ||||
| 				break; | ||||
| 		} | ||||
| 		c->val = val; | ||||
| 	} | ||||
|  | ||||
| 	static void | ||||
| 	cleanup(void) | ||||
| 	{ | ||||
| 		struct control *c; | ||||
|  | ||||
| 		if (hdl) { | ||||
| 			sioctl_close(hdl); | ||||
| 			hdl = NULL; | ||||
| 		} | ||||
|  | ||||
| 		free(pfds); | ||||
| 		pfds = NULL; | ||||
|  | ||||
| 		while (!LIST_EMPTY(&controls)) { | ||||
| 			c = LIST_FIRST(&controls); | ||||
| 			LIST_REMOVE(c, next); | ||||
| 			free(c); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static int | ||||
| 	init(void) | ||||
| 	{ | ||||
| 		hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); | ||||
| 		if (hdl == NULL) { | ||||
| 			warn("sndio: cannot open device"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		if (!sioctl_ondesc(hdl, ondesc, NULL)) { | ||||
| 			warn("sndio: cannot set control description call-back"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		if (!sioctl_onval(hdl, onval, NULL)) { | ||||
| 			warn("sndio: cannot set control values call-back"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		pfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd)); | ||||
| 		if (pfds == NULL) { | ||||
| 			warn("sndio: cannot allocate pollfd structures"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		return 1; | ||||
| 	failed: | ||||
| 		cleanup(); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	vol_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct control *c; | ||||
| 		int n, v, value; | ||||
|  | ||||
| 		if (!initialized) | ||||
| 			initialized = init(); | ||||
|  | ||||
| 		if (hdl == NULL) | ||||
| 			return NULL; | ||||
|  | ||||
| 		n = sioctl_pollfd(hdl, pfds, POLLIN); | ||||
| 		if (n > 0) { | ||||
| 			n = poll(pfds, n, 0); | ||||
| 			if (n > 0) { | ||||
| 				if (sioctl_revents(hdl, pfds) & POLLHUP) { | ||||
| 					warn("sndio: disconnected"); | ||||
| 					cleanup(); | ||||
| 					initialized = 0; | ||||
| 					return NULL; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		value = 100; | ||||
| 		LIST_FOREACH(c, &controls, next) { | ||||
| 			if (c->type == CTRL_MUTE && c->val == 1) | ||||
| 				value = 0; | ||||
| 			else if (c->type == CTRL_LEVEL) { | ||||
| 				v = (c->val * 100 + c->maxval / 2) / c->maxval; | ||||
| 				/* For multiple channels return the minimum. */ | ||||
| 				if (v < value) | ||||
| 					value = v; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return bprintf("%d", value); | ||||
| 	} | ||||
| #else | ||||
| 	#include <sys/soundcard.h> | ||||
|  | ||||
| 	const char * | ||||
| 	vol_perc(const char *card) | ||||
| 	{ | ||||
| 		size_t i; | ||||
| 		int v, afd, devmask; | ||||
| 		char *vnames[] = SOUND_DEVICE_NAMES; | ||||
|  | ||||
| 		if ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) { | ||||
| 			warn("open '%s':", card); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		if (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { | ||||
| 			warn("ioctl 'SOUND_MIXER_READ_DEVMASK':"); | ||||
| 			close(afd); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		for (i = 0; i < LEN(vnames); i++) { | ||||
| 			if (devmask & (1 << i) && !strcmp("vol", vnames[i])) { | ||||
| 				if (ioctl(afd, MIXER_READ(i), &v) < 0) { | ||||
| 					warn("ioctl 'MIXER_READ(%ld)':", i); | ||||
| 					close(afd); | ||||
| 					return NULL; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		close(afd); | ||||
|  | ||||
| 		return bprintf("%d", v & 0xff); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										267
									
								
								slstatus/components/wifi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								slstatus/components/wifi.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,267 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ifaddrs.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/socket.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #define RSSI_TO_PERC(rssi) \ | ||||
| 			rssi >= -50 ? 100 : \ | ||||
| 			(rssi <= -100 ? 0 : \ | ||||
| 			(2 * (rssi + 100))) | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <limits.h> | ||||
| 	#include <linux/wireless.h> | ||||
|  | ||||
| 	#define NET_OPERSTATE "/sys/class/net/%s/operstate" | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_perc(const char *interface) | ||||
| 	{ | ||||
| 		int cur; | ||||
| 		size_t i; | ||||
| 		char *p, *datastart; | ||||
| 		char path[PATH_MAX]; | ||||
| 		char status[5]; | ||||
| 		FILE *fp; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), NET_OPERSTATE, interface) < 0) | ||||
| 			return NULL; | ||||
| 		if (!(fp = fopen(path, "r"))) { | ||||
| 			warn("fopen '%s':", path); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		p = fgets(status, 5, fp); | ||||
| 		fclose(fp); | ||||
| 		if (!p || strcmp(status, "up\n") != 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!(fp = fopen("/proc/net/wireless", "r"))) { | ||||
| 			warn("fopen '/proc/net/wireless':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		for (i = 0; i < 3; i++) | ||||
| 			if (!(p = fgets(buf, sizeof(buf) - 1, fp))) | ||||
| 				break; | ||||
|  | ||||
| 		fclose(fp); | ||||
| 		if (i < 2 || !p) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!(datastart = strstr(buf, interface))) | ||||
| 			return NULL; | ||||
|  | ||||
| 		datastart = (datastart+(strlen(interface)+1)); | ||||
| 		sscanf(datastart + 1, " %*d   %d  %*d  %*d\t\t  %*d\t   " | ||||
| 		       "%*d\t\t%*d\t\t %*d\t  %*d\t\t %*d", &cur); | ||||
|  | ||||
| 		/* 70 is the max of /proc/net/wireless */ | ||||
| 		return bprintf("%d", (int)((float)cur / 70 * 100)); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_essid(const char *interface) | ||||
| 	{ | ||||
| 		static char id[IW_ESSID_MAX_SIZE+1]; | ||||
| 		int sockfd; | ||||
| 		struct iwreq wreq; | ||||
|  | ||||
| 		memset(&wreq, 0, sizeof(struct iwreq)); | ||||
| 		wreq.u.essid.length = IW_ESSID_MAX_SIZE+1; | ||||
| 		if (esnprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", | ||||
| 		              interface) < 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		wreq.u.essid.pointer = id; | ||||
| 		if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) { | ||||
| 			warn("ioctl 'SIOCGIWESSID':"); | ||||
| 			close(sockfd); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		close(sockfd); | ||||
|  | ||||
| 		if (!strcmp(id, "")) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return id; | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <net/if.h> | ||||
| 	#include <net/if_media.h> | ||||
| 	#include <net80211/ieee80211.h> | ||||
| 	#include <sys/select.h> /* before <sys/ieee80211_ioctl.h> for NBBY */ | ||||
| 	#include <net80211/ieee80211_ioctl.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/types.h> | ||||
|  | ||||
| 	static int | ||||
| 	load_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr) | ||||
| 	{ | ||||
| 		struct ieee80211_bssid bssid; | ||||
| 		int sockfd; | ||||
| 		uint8_t zero_bssid[IEEE80211_ADDR_LEN]; | ||||
|  | ||||
| 		memset(&bssid, 0, sizeof(bssid)); | ||||
| 		memset(nr, 0, sizeof(struct ieee80211_nodereq)); | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		strlcpy(bssid.i_name, interface, sizeof(bssid.i_name)); | ||||
| 		if ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) { | ||||
| 			warn("ioctl 'SIOCG80211BSSID':"); | ||||
| 			close(sockfd); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		memset(&zero_bssid, 0, sizeof(zero_bssid)); | ||||
| 		if (memcmp(bssid.i_bssid, zero_bssid, | ||||
| 		    IEEE80211_ADDR_LEN) == 0) { | ||||
| 			close(sockfd); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		strlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname)); | ||||
| 		memcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr)); | ||||
| 		if ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) { | ||||
| 			warn("ioctl 'SIOCG80211NODE':"); | ||||
| 			close(sockfd); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		return close(sockfd), 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_perc(const char *interface) | ||||
| 	{ | ||||
| 		struct ieee80211_nodereq nr; | ||||
| 		int q; | ||||
|  | ||||
| 		if (load_ieee80211_nodereq(interface, &nr)) { | ||||
| 			if (nr.nr_max_rssi) | ||||
| 				q = IEEE80211_NODEREQ_RSSI(&nr); | ||||
| 			else | ||||
| 				q = RSSI_TO_PERC(nr.nr_rssi); | ||||
|  | ||||
| 			return bprintf("%d", q); | ||||
| 		} | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_essid(const char *interface) | ||||
| 	{ | ||||
| 		struct ieee80211_nodereq nr; | ||||
|  | ||||
| 		if (load_ieee80211_nodereq(interface, &nr)) | ||||
| 			return bprintf("%s", nr.nr_nwid); | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <net/if.h> | ||||
| 	#include <net80211/ieee80211_ioctl.h> | ||||
|  | ||||
| 	int | ||||
| 	load_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len) | ||||
| 	{ | ||||
| 		char warn_buf[256]; | ||||
| 		struct ieee80211req ireq; | ||||
| 		memset(&ireq, 0, sizeof(ireq)); | ||||
| 		ireq.i_type = type; | ||||
| 		ireq.i_data = (caddr_t) data; | ||||
| 		ireq.i_len = *len; | ||||
|  | ||||
| 		strlcpy(ireq.i_name, interface, sizeof(ireq.i_name)); | ||||
| 		if (ioctl(sock, SIOCG80211, &ireq) < 0) { | ||||
| 			snprintf(warn_buf,  sizeof(warn_buf), | ||||
| 					"ioctl: 'SIOCG80211': %d", type); | ||||
| 			warn(warn_buf); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		*len = ireq.i_len; | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_perc(const char *interface) | ||||
| 	{ | ||||
| 		union { | ||||
| 			struct ieee80211req_sta_req sta; | ||||
| 			uint8_t buf[24 * 1024]; | ||||
| 		} info; | ||||
| 		uint8_t bssid[IEEE80211_ADDR_LEN]; | ||||
| 		int rssi_dbm; | ||||
| 		int sockfd; | ||||
| 		size_t len; | ||||
| 		const char *fmt; | ||||
|  | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		/* Retreive MAC address of interface */ | ||||
| 		len = IEEE80211_ADDR_LEN; | ||||
| 		fmt = NULL; | ||||
| 		if (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len)) | ||||
| 		{ | ||||
| 			/* Retrieve info on station with above BSSID */ | ||||
| 			memset(&info, 0, sizeof(info)); | ||||
| 			memcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid)); | ||||
|  | ||||
| 			len = sizeof(info); | ||||
| 			if (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) { | ||||
| 				rssi_dbm = info.sta.info[0].isi_noise + | ||||
|  					         info.sta.info[0].isi_rssi / 2; | ||||
|  | ||||
| 				fmt = bprintf("%d", RSSI_TO_PERC(rssi_dbm)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		close(sockfd); | ||||
| 		return fmt; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_essid(const char *interface) | ||||
| 	{ | ||||
| 		char ssid[IEEE80211_NWID_LEN + 1]; | ||||
| 		size_t len; | ||||
| 		int sockfd; | ||||
| 		const char *fmt; | ||||
|  | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		fmt = NULL; | ||||
| 		len = sizeof(ssid); | ||||
| 		memset(&ssid, 0, len); | ||||
| 		if (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) { | ||||
| 			if (len < sizeof(ssid)) | ||||
| 				len += 1; | ||||
| 			else | ||||
| 				len = sizeof(ssid); | ||||
|  | ||||
| 			ssid[len - 1] = '\0'; | ||||
| 			fmt = bprintf("%s", ssid); | ||||
| 		} | ||||
|  | ||||
| 		close(sockfd); | ||||
| 		return fmt; | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										69
									
								
								slstatus/config.def.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								slstatus/config.def.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* interval between updates (in ms) */ | ||||
| const unsigned int interval = 1000; | ||||
|  | ||||
| /* text to show if no value can be retrieved */ | ||||
| static const char unknown_str[] = "n/a"; | ||||
|  | ||||
| /* maximum output string length */ | ||||
| #define MAXLEN 2048 | ||||
|  | ||||
| /* | ||||
|  * function            description                     argument (example) | ||||
|  * | ||||
|  * battery_perc        battery percentage              battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_remaining   battery remaining HH:MM         battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_state       battery charging state          battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * cat                 read arbitrary file             path | ||||
|  * cpu_freq            cpu frequency in MHz            NULL | ||||
|  * cpu_perc            cpu usage in percent            NULL | ||||
|  * datetime            date and time                   format string (%F %T) | ||||
|  * disk_free           free disk space in GB           mountpoint path (/) | ||||
|  * disk_perc           disk usage in percent           mountpoint path (/) | ||||
|  * disk_total          total disk space in GB          mountpoint path (/) | ||||
|  * disk_used           used disk space in GB           mountpoint path (/) | ||||
|  * entropy             available entropy               NULL | ||||
|  * gid                 GID of current user             NULL | ||||
|  * hostname            hostname                        NULL | ||||
|  * ipv4                IPv4 address                    interface name (eth0) | ||||
|  * ipv6                IPv6 address                    interface name (eth0) | ||||
|  * kernel_release      `uname -r`                      NULL | ||||
|  * keyboard_indicators caps/num lock indicators        format string (c?n?) | ||||
|  *                                                     see keyboard_indicators.c | ||||
|  * keymap              layout (variant) of current     NULL | ||||
|  *                     keymap | ||||
|  * load_avg            load average                    NULL | ||||
|  * netspeed_rx         receive network speed           interface name (wlan0) | ||||
|  * netspeed_tx         transfer network speed          interface name (wlan0) | ||||
|  * num_files           number of files in a directory  path | ||||
|  *                                                     (/home/foo/Inbox/cur) | ||||
|  * ram_free            free memory in GB               NULL | ||||
|  * ram_perc            memory usage in percent         NULL | ||||
|  * ram_total           total memory size in GB         NULL | ||||
|  * ram_used            used memory in GB               NULL | ||||
|  * run_command         custom shell command            command (echo foo) | ||||
|  * swap_free           free swap in GB                 NULL | ||||
|  * swap_perc           swap usage in percent           NULL | ||||
|  * swap_total          total swap size in GB           NULL | ||||
|  * swap_used           used swap in GB                 NULL | ||||
|  * temp                temperature in degree celsius   sensor file | ||||
|  *                                                     (/sys/class/thermal/...) | ||||
|  *                                                     NULL on OpenBSD | ||||
|  *                                                     thermal zone on FreeBSD | ||||
|  *                                                     (tz0, tz1, etc.) | ||||
|  * uid                 UID of current user             NULL | ||||
|  * uptime              system uptime                   NULL | ||||
|  * username            username of current user        NULL | ||||
|  * vol_perc            OSS/ALSA volume in percent      mixer file (/dev/mixer) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * wifi_essid          WiFi ESSID                      interface name (wlan0) | ||||
|  * wifi_perc           WiFi signal in percent          interface name (wlan0) | ||||
|  */ | ||||
| static const struct arg args[] = { | ||||
| 	/* function format          argument */ | ||||
| 	{ datetime, "%s",           "%F %T" }, | ||||
| }; | ||||
							
								
								
									
										69
									
								
								slstatus/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								slstatus/config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* interval between updates (in ms) */ | ||||
| const unsigned int interval = 1000; | ||||
|  | ||||
| /* text to show if no value can be retrieved */ | ||||
| static const char unknown_str[] = "n/a"; | ||||
|  | ||||
| /* maximum output string length */ | ||||
| #define MAXLEN 2048 | ||||
|  | ||||
| /* | ||||
|  * function            description                     argument (example) | ||||
|  * | ||||
|  * battery_perc        battery percentage              battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_remaining   battery remaining HH:MM         battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_state       battery charging state          battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * cat                 read arbitrary file             path | ||||
|  * cpu_freq            cpu frequency in MHz            NULL | ||||
|  * cpu_perc            cpu usage in percent            NULL | ||||
|  * datetime            date and time                   format string (%F %T) | ||||
|  * disk_free           free disk space in GB           mountpoint path (/) | ||||
|  * disk_perc           disk usage in percent           mountpoint path (/) | ||||
|  * disk_total          total disk space in GB          mountpoint path (/) | ||||
|  * disk_used           used disk space in GB           mountpoint path (/) | ||||
|  * entropy             available entropy               NULL | ||||
|  * gid                 GID of current user             NULL | ||||
|  * hostname            hostname                        NULL | ||||
|  * ipv4                IPv4 address                    interface name (eth0) | ||||
|  * ipv6                IPv6 address                    interface name (eth0) | ||||
|  * kernel_release      `uname -r`                      NULL | ||||
|  * keyboard_indicators caps/num lock indicators        format string (c?n?) | ||||
|  *                                                     see keyboard_indicators.c | ||||
|  * keymap              layout (variant) of current     NULL | ||||
|  *                     keymap | ||||
|  * load_avg            load average                    NULL | ||||
|  * netspeed_rx         receive network speed           interface name (wlan0) | ||||
|  * netspeed_tx         transfer network speed          interface name (wlan0) | ||||
|  * num_files           number of files in a directory  path | ||||
|  *                                                     (/home/foo/Inbox/cur) | ||||
|  * ram_free            free memory in GB               NULL | ||||
|  * ram_perc            memory usage in percent         NULL | ||||
|  * ram_total           total memory size in GB         NULL | ||||
|  * ram_used            used memory in GB               NULL | ||||
|  * run_command         custom shell command            command (echo foo) | ||||
|  * swap_free           free swap in GB                 NULL | ||||
|  * swap_perc           swap usage in percent           NULL | ||||
|  * swap_total          total swap size in GB           NULL | ||||
|  * swap_used           used swap in GB                 NULL | ||||
|  * temp                temperature in degree celsius   sensor file | ||||
|  *                                                     (/sys/class/thermal/...) | ||||
|  *                                                     NULL on OpenBSD | ||||
|  *                                                     thermal zone on FreeBSD | ||||
|  *                                                     (tz0, tz1, etc.) | ||||
|  * uid                 UID of current user             NULL | ||||
|  * uptime              system uptime                   NULL | ||||
|  * username            username of current user        NULL | ||||
|  * vol_perc            OSS/ALSA volume in percent      mixer file (/dev/mixer) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * wifi_essid          WiFi ESSID                      interface name (wlan0) | ||||
|  * wifi_perc           WiFi signal in percent          interface name (wlan0) | ||||
|  */ | ||||
| static const struct arg args[] = { | ||||
| 	/* function format          argument */ | ||||
| 	{ datetime, "%s",           "%F %T" }, | ||||
| }; | ||||
							
								
								
									
										22
									
								
								slstatus/config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								slstatus/config.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| # slstatus version | ||||
| VERSION = 1.0 | ||||
|  | ||||
| # customize below to fit your system | ||||
|  | ||||
| # paths | ||||
| PREFIX = /usr/local | ||||
| MANPREFIX = $(PREFIX)/share/man | ||||
|  | ||||
| X11INC = /usr/X11R6/include | ||||
| X11LIB = /usr/X11R6/lib | ||||
|  | ||||
| # flags | ||||
| CPPFLAGS = -I$(X11INC) -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" | ||||
| CFLAGS   = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -Os | ||||
| LDFLAGS  = -L$(X11LIB) -s | ||||
| # OpenBSD: add -lsndio | ||||
| # FreeBSD: add -lkvm -lsndio | ||||
| LDLIBS   = -lX11 -lsndio | ||||
|  | ||||
| # compiler and linker | ||||
| CC = cc | ||||
							
								
								
									
										
											BIN
										
									
								
								slstatus/slstatus
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								slstatus/slstatus
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										47
									
								
								slstatus/slstatus.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								slstatus/slstatus.1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| .Dd 2023-04-23 | ||||
| .Dt SLSTATUS 1 | ||||
| .Os | ||||
| .Sh NAME | ||||
| .Nm slstatus | ||||
| .Nd suckless status | ||||
| .Sh SYNOPSIS | ||||
| .Nm | ||||
| .Op Fl s | ||||
| .Op Fl 1 | ||||
| .Sh DESCRIPTION | ||||
| .Nm | ||||
| is a small tool for providing system status information to other programs | ||||
| over the EWMH | ||||
| .Em WM_NAME | ||||
| property of the root window (used by | ||||
| .Xr dwm 1 ) or standard input/output. It is designed to be as efficient as possible by | ||||
| only issuing the minimum of system calls required. | ||||
| .P | ||||
| By default, | ||||
| .Nm | ||||
| outputs to WM_NAME. | ||||
| .Sh OPTIONS | ||||
| .Bl -tag -width Ds | ||||
| .It Fl v | ||||
| Print version information to stderr, then exit. | ||||
| .It Fl s | ||||
| Write to stdout instead of WM_NAME. | ||||
| .It Fl 1 | ||||
| Write once to stdout and quit. | ||||
| .El | ||||
| .Sh CUSTOMIZATION | ||||
| .Nm | ||||
| can be customized by creating a custom config.h and (re)compiling the source | ||||
| code. This keeps it fast, secure and simple. | ||||
| .Sh SIGNALS | ||||
| .Nm | ||||
| responds to the following signals: | ||||
| .Pp | ||||
| .Bl -tag -width TERM -compact | ||||
| .It USR1 | ||||
| Triggers an instant redraw. | ||||
| .El | ||||
| .Sh AUTHORS | ||||
| See the LICENSE file for the authors. | ||||
| .Sh SEE ALSO | ||||
| .Xr dwm 1 | ||||
							
								
								
									
										134
									
								
								slstatus/slstatus.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								slstatus/slstatus.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <errno.h> | ||||
| #include <signal.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #include "arg.h" | ||||
| #include "slstatus.h" | ||||
| #include "util.h" | ||||
|  | ||||
| struct arg { | ||||
| 	const char *(*func)(const char *); | ||||
| 	const char *fmt; | ||||
| 	const char *args; | ||||
| }; | ||||
|  | ||||
| char buf[1024]; | ||||
| static volatile sig_atomic_t done; | ||||
| static Display *dpy; | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| static void | ||||
| terminate(const int signo) | ||||
| { | ||||
| 	if (signo != SIGUSR1) | ||||
| 		done = 1; | ||||
| } | ||||
|  | ||||
| static void | ||||
| difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) | ||||
| { | ||||
| 	res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec); | ||||
| 	res->tv_nsec = a->tv_nsec - b->tv_nsec + | ||||
| 	               (a->tv_nsec < b->tv_nsec) * 1E9; | ||||
| } | ||||
|  | ||||
| static void | ||||
| usage(void) | ||||
| { | ||||
| 	die("usage: %s [-v] [-s] [-1]", argv0); | ||||
| } | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
| 	struct sigaction act; | ||||
| 	struct timespec start, current, diff, intspec, wait; | ||||
| 	size_t i, len; | ||||
| 	int sflag, ret; | ||||
| 	char status[MAXLEN]; | ||||
| 	const char *res; | ||||
|  | ||||
| 	sflag = 0; | ||||
| 	ARGBEGIN { | ||||
| 	case 'v': | ||||
| 		die("slstatus-"VERSION); | ||||
| 	case '1': | ||||
| 		done = 1; | ||||
| 		/* FALLTHROUGH */ | ||||
| 	case 's': | ||||
| 		sflag = 1; | ||||
| 		break; | ||||
| 	default: | ||||
| 		usage(); | ||||
| 	} ARGEND | ||||
|  | ||||
| 	if (argc) | ||||
| 		usage(); | ||||
|  | ||||
| 	memset(&act, 0, sizeof(act)); | ||||
| 	act.sa_handler = terminate; | ||||
| 	sigaction(SIGINT,  &act, NULL); | ||||
| 	sigaction(SIGTERM, &act, NULL); | ||||
| 	act.sa_flags |= SA_RESTART; | ||||
| 	sigaction(SIGUSR1, &act, NULL); | ||||
|  | ||||
| 	if (!sflag && !(dpy = XOpenDisplay(NULL))) | ||||
| 		die("XOpenDisplay: Failed to open display"); | ||||
|  | ||||
| 	do { | ||||
| 		if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) | ||||
| 			die("clock_gettime:"); | ||||
|  | ||||
| 		status[0] = '\0'; | ||||
| 		for (i = len = 0; i < LEN(args); i++) { | ||||
| 			if (!(res = args[i].func(args[i].args))) | ||||
| 				res = unknown_str; | ||||
|  | ||||
| 			if ((ret = esnprintf(status + len, sizeof(status) - len, | ||||
| 			                     args[i].fmt, res)) < 0) | ||||
| 				break; | ||||
|  | ||||
| 			len += ret; | ||||
| 		} | ||||
|  | ||||
| 		if (sflag) { | ||||
| 			puts(status); | ||||
| 			fflush(stdout); | ||||
| 			if (ferror(stdout)) | ||||
| 				die("puts:"); | ||||
| 		} else { | ||||
| 			if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) | ||||
| 				die("XStoreName: Allocation failed"); | ||||
| 			XFlush(dpy); | ||||
| 		} | ||||
|  | ||||
| 		if (!done) { | ||||
| 			if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) | ||||
| 				die("clock_gettime:"); | ||||
| 			difftimespec(&diff, ¤t, &start); | ||||
|  | ||||
| 			intspec.tv_sec = interval / 1000; | ||||
| 			intspec.tv_nsec = (interval % 1000) * 1E6; | ||||
| 			difftimespec(&wait, &intspec, &diff); | ||||
|  | ||||
| 			if (wait.tv_sec >= 0 && | ||||
| 			    nanosleep(&wait, NULL) < 0 && | ||||
| 			    errno != EINTR) | ||||
| 					die("nanosleep:"); | ||||
| 		} | ||||
| 	} while (!done); | ||||
|  | ||||
| 	if (!sflag) { | ||||
| 		XStoreName(dpy, DefaultRootWindow(dpy), NULL); | ||||
| 		if (XCloseDisplay(dpy) < 0) | ||||
| 			die("XCloseDisplay: Failed to close display"); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										84
									
								
								slstatus/slstatus.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								slstatus/slstatus.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* battery */ | ||||
| const char *battery_perc(const char *); | ||||
| const char *battery_remaining(const char *); | ||||
| const char *battery_state(const char *); | ||||
|  | ||||
| /* cat */ | ||||
| const char *cat(const char *path); | ||||
|  | ||||
| /* cpu */ | ||||
| const char *cpu_freq(const char *unused); | ||||
| const char *cpu_perc(const char *unused); | ||||
|  | ||||
| /* datetime */ | ||||
| const char *datetime(const char *fmt); | ||||
|  | ||||
| /* disk */ | ||||
| const char *disk_free(const char *path); | ||||
| const char *disk_perc(const char *path); | ||||
| const char *disk_total(const char *path); | ||||
| const char *disk_used(const char *path); | ||||
|  | ||||
| /* entropy */ | ||||
| const char *entropy(const char *unused); | ||||
|  | ||||
| /* hostname */ | ||||
| const char *hostname(const char *unused); | ||||
|  | ||||
| /* ip */ | ||||
| const char *ipv4(const char *interface); | ||||
| const char *ipv6(const char *interface); | ||||
|  | ||||
| /* kernel_release */ | ||||
| const char *kernel_release(const char *unused); | ||||
|  | ||||
| /* keyboard_indicators */ | ||||
| const char *keyboard_indicators(const char *fmt); | ||||
|  | ||||
| /* keymap */ | ||||
| const char *keymap(const char *unused); | ||||
|  | ||||
| /* load_avg */ | ||||
| const char *load_avg(const char *unused); | ||||
|  | ||||
| /* netspeeds */ | ||||
| const char *netspeed_rx(const char *interface); | ||||
| const char *netspeed_tx(const char *interface); | ||||
|  | ||||
| /* num_files */ | ||||
| const char *num_files(const char *path); | ||||
|  | ||||
| /* ram */ | ||||
| const char *ram_free(const char *unused); | ||||
| const char *ram_perc(const char *unused); | ||||
| const char *ram_total(const char *unused); | ||||
| const char *ram_used(const char *unused); | ||||
|  | ||||
| /* run_command */ | ||||
| const char *run_command(const char *cmd); | ||||
|  | ||||
| /* swap */ | ||||
| const char *swap_free(const char *unused); | ||||
| const char *swap_perc(const char *unused); | ||||
| const char *swap_total(const char *unused); | ||||
| const char *swap_used(const char *unused); | ||||
|  | ||||
| /* temperature */ | ||||
| const char *temp(const char *); | ||||
|  | ||||
| /* uptime */ | ||||
| const char *uptime(const char *unused); | ||||
|  | ||||
| /* user */ | ||||
| const char *gid(const char *unused); | ||||
| const char *uid(const char *unused); | ||||
| const char *username(const char *unused); | ||||
|  | ||||
| /* volume */ | ||||
| const char *vol_perc(const char *card); | ||||
|  | ||||
| /* wifi */ | ||||
| const char *wifi_essid(const char *interface); | ||||
| const char *wifi_perc(const char *interface); | ||||
							
								
								
									
										141
									
								
								slstatus/util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								slstatus/util.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <errno.h> | ||||
| #include <stdarg.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "util.h" | ||||
|  | ||||
| char *argv0; | ||||
|  | ||||
| static void | ||||
| verr(const char *fmt, va_list ap) | ||||
| { | ||||
| 	vfprintf(stderr, fmt, ap); | ||||
|  | ||||
| 	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { | ||||
| 		fputc(' ', stderr); | ||||
| 		perror(NULL); | ||||
| 	} else { | ||||
| 		fputc('\n', stderr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| warn(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	verr(fmt, ap); | ||||
| 	va_end(ap); | ||||
| } | ||||
|  | ||||
| void | ||||
| die(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	verr(fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| static int | ||||
| evsnprintf(char *str, size_t size, const char *fmt, va_list ap) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = vsnprintf(str, size, fmt, ap); | ||||
|  | ||||
| 	if (ret < 0) { | ||||
| 		warn("vsnprintf:"); | ||||
| 		return -1; | ||||
| 	} else if ((size_t)ret >= size) { | ||||
| 		warn("vsnprintf: Output truncated"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| esnprintf(char *str, size_t size, const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	int ret; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	ret = evsnprintf(str, size, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| bprintf(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	int ret; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	ret = evsnprintf(buf, sizeof(buf), fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	return (ret < 0) ? NULL : buf; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| fmt_human(uintmax_t num, int base) | ||||
| { | ||||
| 	double scaled; | ||||
| 	size_t i, prefixlen; | ||||
| 	const char **prefix; | ||||
| 	const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z", | ||||
| 	                              "Y" }; | ||||
| 	const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", | ||||
| 	                              "Zi", "Yi" }; | ||||
|  | ||||
| 	switch (base) { | ||||
| 	case 1000: | ||||
| 		prefix = prefix_1000; | ||||
| 		prefixlen = LEN(prefix_1000); | ||||
| 		break; | ||||
| 	case 1024: | ||||
| 		prefix = prefix_1024; | ||||
| 		prefixlen = LEN(prefix_1024); | ||||
| 		break; | ||||
| 	default: | ||||
| 		warn("fmt_human: Invalid base"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	scaled = num; | ||||
| 	for (i = 0; i < prefixlen && scaled >= base; i++) | ||||
| 		scaled /= base; | ||||
|  | ||||
| 	return bprintf("%.1f %s", scaled, prefix[i]); | ||||
| } | ||||
|  | ||||
| int | ||||
| pscanf(const char *path, const char *fmt, ...) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 	va_list ap; | ||||
| 	int n; | ||||
|  | ||||
| 	if (!(fp = fopen(path, "r"))) { | ||||
| 		warn("fopen '%s':", path); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	va_start(ap, fmt); | ||||
| 	n = vfscanf(fp, fmt, ap); | ||||
| 	va_end(ap); | ||||
| 	fclose(fp); | ||||
|  | ||||
| 	return (n == EOF) ? -1 : n; | ||||
| } | ||||
							
								
								
									
										16
									
								
								slstatus/util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								slstatus/util.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
|  | ||||
| extern char buf[1024]; | ||||
|  | ||||
| #define LEN(x) (sizeof(x) / sizeof((x)[0])) | ||||
|  | ||||
| extern char *argv0; | ||||
|  | ||||
| void warn(const char *, ...); | ||||
| void die(const char *, ...); | ||||
|  | ||||
| int esnprintf(char *str, size_t size, const char *fmt, ...); | ||||
| const char *bprintf(const char *fmt, ...); | ||||
| const char *fmt_human(uintmax_t num, int base); | ||||
| int pscanf(const char *path, const char *fmt, ...); | ||||
		Reference in New Issue
	
	Block a user