From e06a17c6b8fd8198a503dae861fe9c86effc0152 Mon Sep 17 00:00:00 2001 From: Nash Brooks Date: Sat, 7 Aug 2021 01:31:57 -0400 Subject: [PATCH] added everything --- LICENSE | 40 +++++ Makefile | 68 ++++++++ README | 65 +++++++ arg.h | 33 ++++ components/battery.c | 252 +++++++++++++++++++++++++++ components/battery.o | Bin 0 -> 5528 bytes components/cpu.c | 164 ++++++++++++++++++ components/cpu.o | Bin 0 -> 3176 bytes components/datetime.c | 19 +++ components/datetime.o | Bin 0 -> 1968 bytes components/disk.c | 58 +++++++ components/disk.o | Bin 0 -> 3152 bytes components/entropy.c | 27 +++ components/entropy.o | Bin 0 -> 1824 bytes components/hostname.c | 16 ++ components/hostname.o | Bin 0 -> 1680 bytes components/ip.c | 60 +++++++ components/ip.o | Bin 0 -> 2600 bytes components/kernel_release.c | 18 ++ components/kernel_release.o | Bin 0 -> 1872 bytes components/keyboard_indicators.c | 48 ++++++ components/keyboard_indicators.o | Bin 0 -> 2440 bytes components/keymap.c | 87 ++++++++++ components/keymap.o | Bin 0 -> 4096 bytes components/load_avg.c | 18 ++ components/load_avg.o | Bin 0 -> 1904 bytes components/netspeeds.c | 139 +++++++++++++++ components/netspeeds.o | Bin 0 -> 2800 bytes components/num_files.c | 31 ++++ components/num_files.o | Bin 0 -> 2192 bytes components/ram.c | 222 ++++++++++++++++++++++++ components/ram.o | Bin 0 -> 3128 bytes components/run_command.c | 30 ++++ components/run_command.o | Bin 0 -> 2176 bytes components/separator.c | 10 ++ components/separator.o | Bin 0 -> 1200 bytes components/swap.c | 284 +++++++++++++++++++++++++++++++ components/swap.o | Bin 0 -> 3968 bytes components/temperature.c | 71 ++++++++ components/temperature.o | Bin 0 -> 1736 bytes components/uptime.c | 33 ++++ components/uptime.o | Bin 0 -> 2008 bytes components/user.c | 32 ++++ components/user.o | Bin 0 -> 2232 bytes components/volume.c | 217 +++++++++++++++++++++++ components/volume.o | Bin 0 -> 3656 bytes components/wifi.c | 272 +++++++++++++++++++++++++++++ components/wifi.o | Bin 0 -> 4336 bytes config.def.h | 73 ++++++++ config.h | 73 ++++++++ config.mk | 22 +++ slstatus | Bin 0 -> 31824 bytes slstatus.1 | 28 +++ slstatus.c | 141 +++++++++++++++ slstatus.h | 84 +++++++++ slstatus.o | Bin 0 -> 6184 bytes util.c | 146 ++++++++++++++++ util.h | 16 ++ util.o | Bin 0 -> 5976 bytes 59 files changed, 2897 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README create mode 100644 arg.h create mode 100644 components/battery.c create mode 100644 components/battery.o create mode 100644 components/cpu.c create mode 100644 components/cpu.o create mode 100644 components/datetime.c create mode 100644 components/datetime.o create mode 100644 components/disk.c create mode 100644 components/disk.o create mode 100644 components/entropy.c create mode 100644 components/entropy.o create mode 100644 components/hostname.c create mode 100644 components/hostname.o create mode 100644 components/ip.c create mode 100644 components/ip.o create mode 100644 components/kernel_release.c create mode 100644 components/kernel_release.o create mode 100644 components/keyboard_indicators.c create mode 100644 components/keyboard_indicators.o create mode 100644 components/keymap.c create mode 100644 components/keymap.o create mode 100644 components/load_avg.c create mode 100644 components/load_avg.o create mode 100644 components/netspeeds.c create mode 100644 components/netspeeds.o create mode 100644 components/num_files.c create mode 100644 components/num_files.o create mode 100644 components/ram.c create mode 100644 components/ram.o create mode 100644 components/run_command.c create mode 100644 components/run_command.o create mode 100644 components/separator.c create mode 100644 components/separator.o create mode 100644 components/swap.c create mode 100644 components/swap.o create mode 100644 components/temperature.c create mode 100644 components/temperature.o create mode 100644 components/uptime.c create mode 100644 components/uptime.o create mode 100644 components/user.c create mode 100644 components/user.o create mode 100644 components/volume.c create mode 100644 components/volume.o create mode 100644 components/wifi.c create mode 100644 components/wifi.o create mode 100644 config.def.h create mode 100644 config.h create mode 100644 config.mk create mode 100755 slstatus create mode 100644 slstatus.1 create mode 100644 slstatus.c create mode 100644 slstatus.h create mode 100644 slstatus.o create mode 100644 util.c create mode 100644 util.h create mode 100644 util.o diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b88a9cb --- /dev/null +++ b/LICENSE @@ -0,0 +1,40 @@ +ISC License + +Copyright 2016-2020 Aaron Marcher + +Copyright 2016 Roy Freytag +Copyright 2016 Vincent Loupmon +Copyright 2016 Daniel Walter +Copyright 2016-2018 Ali H. Fardan +Copyright 2016 Jody Leonard +Copyright 2016-2018 Quentin Rameau +Copyright 2016 Mike Coddington +Copyright 2016-2018 parazyd +Copyright 2017 Tobias Stoeckmann +Copyright 2017-2018 Laslo Hunhold +Copyright 2018 Darron Anderson +Copyright 2018 Josuah Demangeon +Copyright 2018 Tobias Tschinkowitz +Copyright 2018 David Demelier +Copyright 2018-2019 Michael Buch +Copyright 2018 Ian Remmler +Copyright 2016-2019 Joerg Jung +Copyright 2019 Ryan Kes +Copyright 2019 Cem Keylan +Copyright 2019 dsp +Copyright 2019-2020 Ingo Feinerer +Copyright 2020 Alexandre Ratchov +Copyright 2020 Mart Lubbers +Copyright 2020 Daniel Moch + +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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2f93b87 --- /dev/null +++ b/Makefile @@ -0,0 +1,68 @@ +# See LICENSE file for copyright and license details +# slstatus - suckless status monitor +.POSIX: + +include config.mk + +REQ = util +COM =\ + components/battery\ + 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/separator\ + components/swap\ + components/temperature\ + components/uptime\ + components/user\ + components/volume\ + components/wifi + +all: slstatus + +$(COM:=.o): config.mk $(REQ:=.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) + +dist: + rm -rf "slstatus-$(VERSION)" + mkdir -p "slstatus-$(VERSION)/components" + cp -R LICENSE Makefile README config.mk config.def.h \ + arg.h slstatus.c $(COM:=.c) $(REQ:=.c) $(REQ:=.h) \ + slstatus.1 "slstatus-$(VERSION)" + 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" diff --git a/README b/README new file mode 100644 index 0000000..86fe988 --- /dev/null +++ b/README @@ -0,0 +1,65 @@ +slstatus - suckless status +========================== +slstatus is a suckless status monitor for window managers that use WM_NAME +(e.g. dwm) or stdin to fill the status bar. + + +Features +-------- +- Battery percentage/state/time left +- 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. + + +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. + + +Upcoming +-------- + +A release (v1.0) will come soon... ;) +After a long phase of inactivity, development has been continued! diff --git a/arg.h b/arg.h new file mode 100644 index 0000000..e0adb9f --- /dev/null +++ b/arg.h @@ -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 diff --git a/components/battery.c b/components/battery.c new file mode 100644 index 0000000..f2b0f14 --- /dev/null +++ b/components/battery.c @@ -0,0 +1,252 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../util.h" + +#if defined(__linux__) + #include + #include + #include + + 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 perc; + char path[PATH_MAX]; + + if (esnprintf(path, sizeof(path), + "/sys/class/power_supply/%s/capacity", bat) < 0) { + return NULL; + } + if (pscanf(path, "%d", &perc) != 1) { + return NULL; + } + + return bprintf("%d", perc); + } + + const char * + battery_state(const char *bat) + { + static struct { + char *state; + char *symbol; + } map[] = { + { "Charging", "+" }, + { "Discharging", "-" }, + { "Full", "o" }, + }; + size_t i; + char path[PATH_MAX], state[12]; + + if (esnprintf(path, sizeof(path), + "/sys/class/power_supply/%s/status", bat) < 0) { + return NULL; + } + if (pscanf(path, "%12s", 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), + "/sys/class/power_supply/%s/status", bat) < 0) { + return NULL; + } + if (pscanf(path, "%12s", state) != 1) { + return NULL; + } + + if (!pick(bat, "/sys/class/power_supply/%s/charge_now", + "/sys/class/power_supply/%s/energy_now", path, + sizeof(path)) || + pscanf(path, "%ju", &charge_now) < 0) { + return NULL; + } + + if (!strcmp(state, "Discharging")) { + if (!pick(bat, "/sys/class/power_supply/%s/current_now", + "/sys/class/power_supply/%s/power_now", 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 + #include + #include + #include + + 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; + + if (load_apm_power_info(&apm_info)) { + if (apm_info.ac_state != APM_AC_ON) { + return bprintf("%uh %02um", + apm_info.minutes_left / 60, + apm_info.minutes_left % 60); + } else { + return ""; + } + } + + return NULL; + } +#elif defined(__FreeBSD__) + #include + + const char * + battery_perc(const char *unused) + { + int cap; + size_t len; + + len = sizeof(cap); + if (sysctlbyname("hw.acpi.battery.life", &cap, &len, NULL, 0) == -1 + || !len) + return NULL; + + return bprintf("%d", cap); + } + + const char * + battery_state(const char *unused) + { + int state; + size_t len; + + len = sizeof(state); + if (sysctlbyname("hw.acpi.battery.state", &state, &len, NULL, 0) == -1 + || !len) + return NULL; + + switch(state) { + case 0: + 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("hw.acpi.battery.time", &rem, &len, NULL, 0) == -1 + || !len + || rem == -1) + return NULL; + + return bprintf("%uh %02um", rem / 60, rem % 60); + } +#endif diff --git a/components/battery.o b/components/battery.o new file mode 100644 index 0000000000000000000000000000000000000000..f49e64d92dba41a2fb84a18e490c890959d4fd59 GIT binary patch literal 5528 zcmbW5aco;h9mmg(O&loCNt-fnnc!)1hDTecuUkifvBpW$yfSNTSu(oP&Utm7o3xH? z-h0s!gjT916_3`VNRtqMZJ_;uCWMMKfdo=9Er?RIsbL^ZXo3hKt*yss0|J3M!tZzQ z&i?gk7pW)t-reWEzu(>c?%v%?j*Vn@hC?AHQ;0pznl(uoOY}6$gSo0%tVCF#P;DyW>bQrj+uE%c1&ExMTpwCJ3RHQ$} zeJ&(p0HE*cWHOfZ-x0meM~qs1gIV2#W=74djwK_|YWnYS!Rp1?Kb`WD5g3zElW;Kdd^#Po1{0p^ucRUr4PEjbt-RluE2w%aBKVLIX?Fh$kwm~3o zn=MX=&-Q60_?dCs2RCsIwyBdwBb;0@nQAWce5X;n`U32?Y}HHN-&Ute$fODFyuGMBEJ zT}z05z7pS819>30h=TJcmO*gM>^hHvOCb35O8i+6cJtj_h!321(cQ-D^`3a@;!6C$ zC9K^r<3IWDc60HcfvY#_3Ddt0FPyn_1$*qejNU+v-VT7bXZW0(-Y(ZQXuv)0DrUHPk*dG^A9JMRwUi4RDSMGD(=tbs{SLh zcTxsZ`G4+a9mg(t(%+O0PG{H#wuzPTZM*vvR!m!+#f&Wv2eKyz+34`_r}fn6lj9HR zhLJYXn}ZfSPIdU5d(meljwurA|bj&^Cvk)=~g6S^@+^S}X<9F=6)&VRt&bM@yXS7}d_| zVMj}3xDeV<`&HCHdJi*j(a_fP@DkBJ2F>3`4JHg0XkQ5L)e_Z?Ax%FW*`cLQMn|<} zz2mKrmda@QkQ@=WXq#bNBJ9R$D?vviYR%RUK@now06aFL*1@CRXyOHoVTgU80mU-$ zdI#ZB@BlCH*H$9_{J7xBTPR~21%F84hTu;q{87R8DEu>mKcnzL!EJ?)2p){9+4wnL zjN$cvOWG~?Ef6ZfUWu}!O2d9$kFswnd_wRaE4(215rxAU0x8OVs&Gf}Wrff2x_mpD zjn4}nYa(7+;CYmFHn#*PUx!?c0XDqchQHc|{}A|E*gbxUIpB4Q_34b7LFJjb?WbWwN>5J9j=c zGL{?53}r`h%yvr^XS(DSn3d1luFJ%Da~0cxA-j32RA7gMB$tEhDStGVpE{Z=SkuLZ z7;i0`xt^1ssWhNt&sftXyuTpzV+IM&+&=i-gbxHvk0XSn^1T7(9M1}=pKilX3yxv$ zB>LBgp7wiz=yC5#|Gy{tj}rb4;U6Ph9*{VGo$x-f4{$vA)=2-uf~)f#C;AT({RGj| z@sx-j&tB=@C3-wFB|lE|YY0EtM*kwwf0*dM-A4Zk(Q8EiBf{f^|BP@v59Bz1Lpa_J zlK)k3HO^h)JyYYnO>i~Ndx@UL`2f+=I3FSU9x|RU5x$o2MZ(t+{;f9tzf1IVU0x;n z2Z*27h`yKbUlER<$}(#<^7Cf!zB4Sq1QQWa$D5#TMLuauUGUK2N5c+ z+sE^OA(!{hg2Ls!aaQ4t`yuVl&v@1$mWER^cuvWZV;8NoXU};oJ!yFsOCN%BIqj6O zf^zt*g(`|Tff6*Pi{-pkY{>Gihv&aAf*M>K`SQ#Re5A8{k8@E!T$)Ye z#bi71XG-ASp2`&*YevROOy#Z~I#^+7n_ql^o5A40Zi;;&s$46}_{6gt_r)OmXxfK| zA0!kQ={m6YI_rrsNE8VcigdH^BlEgM>u#HecpLc6-fGzsm0zaB$|Mw^z%Bp;h zfDx9}{wJb=x6RZkly#*(2=!L+o5O%XIuks2{BVub_~E|C{_(7%>5S-Krx42W{glrF zuvYeGg}u~CH?n{EbcOw9DG<+^u*b8OChQB7e13(Ld4tH_6!w&1S=vdC-xv5@LC*qg zdrR1>4W?J%hdx#Nn0O(spok>Z{v~K@wSF-XxCvp4%Zc~3w3qw8Ro`fGUGzU8 qHWs?OuZ2B+!>D@?5Zi;7D5R(oFr^Cr8EtJpCC2{)?xmTj_WuKadLQ5b literal 0 HcmV?d00001 diff --git a/components/cpu.c b/components/cpu.c new file mode 100644 index 0000000..9e28003 --- /dev/null +++ b/components/cpu.c @@ -0,0 +1,164 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include + +#include "../util.h" + +#if defined(__linux__) + const char * + cpu_freq(void) + { + uintmax_t freq; + + /* in kHz */ + if (pscanf("/sys/devices/system/cpu/cpu0/cpufreq/" + "scaling_cur_freq", "%ju", &freq) != 1) { + return NULL; + } + + return fmt_human(freq * 1000, 1000); + } + + const char * + cpu_perc(void) + { + 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 + #include + #include + + const char * + cpu_freq(void) + { + 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(void) + { + 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 + #include + #include + + const char * + cpu_freq(void) + { + int freq; + size_t size; + + size = sizeof(freq); + /* in MHz */ + if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) == -1 + || !size) { + warn("sysctlbyname 'hw.clockrate':"); + return NULL; + } + + return fmt_human(freq * 1E6, 1000); + } + + const char * + cpu_perc(void) + { + 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) == -1 + || !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 diff --git a/components/cpu.o b/components/cpu.o new file mode 100644 index 0000000000000000000000000000000000000000..19773cb91dad28fff114dfc8af53ee73953eacc6 GIT binary patch literal 3176 zcma);O>7%Q6o6-)gqSwiCIl(aO7&q4DYWajB&ezaa(BYMq}$K^y>aaAaaZC8R{Hs`SPIDZDp3&)H04sV~}j z?|t*$%c;eNYb>_(y&UqdyaFEs`_ z&|e%--Jz1ccy}9l?_#NU?@pmjpX^b$8yLHV4ez<5&?RHB9Wzh|2dDrt4Bvg7@F%^Ugc^WVMKR$&zj|2BKC-2wwTN2;sPhN0!_vs>~= zi@vnlS>AwXKhN>~xmr1;R@XLvf_L!QA<)f-sjimS%WDwotNvYiuvNY4vfkUAQD>_g zqU6b?0d*GA=YDBPLeXbJrRv7!&(&4<+bKVVm8w46Osg}M<0`1xr7l&U-?$EV2m7|l zTjhJLylugj{@_Qkqt-F1jsz|hSkRm{gA<8QCgTYcZ7Y!p#&ZRHI3+D1u@t|oL77I+k?05RuP=Eh9f5*_9@0|39LRv`cWULW- z{P5uBfDYzjN(mY5VMX|`*SNF^tz3PJDOY^Tv6g1{G6W+(F8an%4|x2pk38;EV0H<< zfP)TszEWHlJl`r2&k8&@l@C43itCRf9(UxZ;c<)5M--+uvWI(*bO30mt@dDV1An`N ztQlOz!E>VfDA)Xm97ym9jx}-0v)pN7=bRAi=LP>j;wJ=8NL=Oq6B1?YB#>6ed-0kA zI|Glsrh_SZ9X?!#zh8%60*>?2eEc^9X4Z*kus^jpGhi=i(SF{9&^m+7E7-h>O*h8b z`!+Td9q#Lm#)bz6-;RvNMtl3Bkr>Ot{>~;@GGoP3g^ZD9u^4RK_~lqUbvc$aCewU? zTp}N5J?(5V1kO==`wxGeK4~N8> zhD01ak%B{KWaL|i7Weqt5208R`KAg3L-|M4%l7uaALJhc18W&3AoQHLa&w}XxKD5> z`Vh2>I6Sw=={qDa3y3`ONlVLNxIb`AIX^7&={rFAelmm(fyOcM{&foFr<@RMnxAx7 zuvRHr%WPfx(eafBvMy@s9A&2Gr#YETlQ@JJQ{|_I>&x8N~ literal 0 HcmV?d00001 diff --git a/components/datetime.c b/components/datetime.c new file mode 100644 index 0000000..c3efae3 --- /dev/null +++ b/components/datetime.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#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; +} diff --git a/components/datetime.o b/components/datetime.o new file mode 100644 index 0000000000000000000000000000000000000000..2f168a5239b5e6c994333572be8953073d69ca57 GIT binary patch literal 1968 zcmb_c&1(};5T8v`8?}b06@pdSLzIfTWW`g#k`J3~akWq*B371dvS~u|QFk}k)DaCi7wOvZZD%!OPzot9dE4TG2`6Rpe(Q)mn zTW?y^@`B}b8m^2)y|pY`Yh}x-IPy}bTD5H1sc%>S#e9BRo+{pdcvV(aMOD(c34NA~ zGKzv8h=9}$d@A;$XLC;`FpeN?EP%9@kS52+V!P-}A$P&|0Bq8lizi-13i0ID$lZ84 zQi~_E@kA~j6Cp52`A|X5kaBu?d|tK^CQsg$55E3J3=6yhR1xKNCff6 zQJ8;3B!cRXpfJBkB!c2kpfK+ci6EZN#=ML=f$EU-p*ZVJ*IWVxzqPm4ShKB$skqjf z3kr781ZBx_K(X6oP&nRsP|EFQ(`sQztL<6}Uilk-lZ3t8>L{yrd)2btbxfs#R?Vo| zCN}rKK*lO`*N=s&WrWT5mEHXA*q%g%dX-^9tiME)-Uyp|NxA&sl7hb?c$!TR?}J7_ z5AS~+eN^*b^Ht2Hnm18`;Qgt75WGLH8FZ4)_mX3O2<0pjV&yzu=a6ST82Tq@1oUw1 zWAxGcICLi|UId2E#r>xc!ZQ>K4d@SOT968!2oKH2wvquVc#RoklBLGpZ&(Qz#p!~Oje9@2WDdGITC->W{ literal 0 HcmV?d00001 diff --git a/components/disk.c b/components/disk.c new file mode 100644 index 0000000..15a221b --- /dev/null +++ b/components/disk.c @@ -0,0 +1,58 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#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.0f - ((float)fs.f_bavail / (float)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); +} diff --git a/components/disk.o b/components/disk.o new file mode 100644 index 0000000000000000000000000000000000000000..7bf88cb9b84ec56c020b0510a6c9ceabde03e38c GIT binary patch literal 3152 zcmcIl&2Jk;6o2a`jSIzVLMtqa&>kFWXuGOgB&3QD=X;S1mD&Uq30OAv8i&MoWN(6l zB5D*B)iRZGgbN2wy}@6AOv)i34shVk5dlI}z9CR~zuB31vWWpj>XY8=%Vx9 zr}Hy0!yrWly+HkyLW#EG{drDIb7WG2=AHK6&gR#xqSF}~%do&{Poy0~y z54GlWrqUVbMz=ZAbIhj^yS=^nli~dEi*sxn(00$f)`eDTS8Hd#*0-$nP0xJutDc#B z2z!xR%65C^>pMO3H39a_vvtz&&f4b*=S~*$Ff$7%Mn)Hy>On)Uk1+;1 z5q`*c?+O{sq;cx_NPLTxEyf?0vL$@S6Uh%_vxzMu<|UHji8wjq2H;l*;HW+FQF(}SVyrqqe@*H?i^4J~ zyAOB{Kc7iloD&p^i;X3_Kz4reJccZWix@5lkz1w;TiNgnaSK;S0T+e@A!}YrPnt#1+?`ZmZ z-8MB`uiM8OuE*_axE}X=iAT@tM@?Uk+tYA8ZX6DnPzOD(1&|41sUp@>V(jCp|H~0v z-H(qVxVj%?H`XhGx4_?^9)8PeR`-`ZJMfzU*+nn#$X;kP$gbD0fI2_ryURi&c!umk zty1x;tY57KzRmCYIdMhg`t9nfy;8674GGrS5Z?VVUp%kk%j^#SvDg%)jlPUI#z3Qb z@pvtdLC7$iVn*$A%sREu#7r4!kF$Yo_&yV*AY{V32^_tr)0IeEC5y&C%L4d3tbLYk z;qwBsPAdMxI>>VsUwv~D3;!d1<)X}A?N>=qE0FrW%yanSU;7?fmiCYALHEahmE|fI zUG@6^tY3+ZMwp}OEeS;Pitguq89!?Og#>QvN%1^tzs}e}{c{^hF})?m@NVNhQ1+^S xu=i+em|T+$q249@|KT!fk2fjWI}Fhu@_;&6XcVnA`r{z`xD0etv&A%O{|`rd0 + #include + + #include "../util.h" + + const char * + entropy(void) + { + uintmax_t num; + + if (pscanf("/proc/sys/kernel/random/entropy_avail", "%ju", &num) + != 1) { + return NULL; + } + + return bprintf("%ju", num); + } +#elif defined(__OpenBSD__) | defined(__FreeBSD__) + const char * + entropy(void) + { + /* Unicode Character 'INFINITY' (U+221E) */ + return "\xe2\x88\x9e"; + } +#endif diff --git a/components/entropy.o b/components/entropy.o new file mode 100644 index 0000000000000000000000000000000000000000..6c1447987e0cf30f1b9f99817c777ac7e01ca710 GIT binary patch literal 1824 zcmbtU&1(};5T8vO8!?7eD+pECLn`&7FJ1Le3QE$LW`$tEHU|%~Y&IKP+ic?QRvJBc zC2^skIxzcYe)IL-o7wleQd>zW3NR^f4~{fO z0p3j<$;D7CLJrPC-PoTe)!4rqF8v?I-gmWW3?^si2=3p{XY`@b|N4#0rT$PKmJUDe zWR1a{ywU#|qQ+o7pJ^I5ro)gR9f5lv)Fvimc-}4Jwj^{et1r=>x8`3RI< zRhh|7We(7I8F6AFlRl-K`X*J+X{l;XE#)!fBGHFI@kWv#Mq zu9uc;6%)F?ZMiLIbiGYCXn|?^fn{%*_Qsak3Oh(U<=&)Frjh$|7*TXDfc=Yn7{87> z5yed*GhRfQh;V8S<8=a&2tSR?xP~$j%qG<&d zh=%Wj@H(WBJ5C`8yVGvtU4d{rfg^AP=fh)5{i(YnaJ;*Y7xXZc5;_}Z%d^_fXb1l# zXc$d1cq);lD0Q9}HuHbL`V0zmS49TodLS=pSL)Osisc{SlEkk{JobEqmbcQLT$1%~ zq66jp*LWRcDd#QZIB|WRAGUFQUW;fTIeJal3*eI!FC0Ok#BsbnK$PXU>*u%Rxx6l9p literal 0 HcmV?d00001 diff --git a/components/hostname.c b/components/hostname.c new file mode 100644 index 0000000..23da677 --- /dev/null +++ b/components/hostname.c @@ -0,0 +1,16 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../util.h" + +const char * +hostname(void) +{ + if (gethostname(buf, sizeof(buf)) < 0) { + warn("gethostbyname:"); + return NULL; + } + + return buf; +} diff --git a/components/hostname.o b/components/hostname.o new file mode 100644 index 0000000000000000000000000000000000000000..bcc0e4dac33c26a140f7196c66589a60a76d949e GIT binary patch literal 1680 zcmb_cO=}Zj5S~q|typ8~2NbH1i{j@?*NakAl7@T;!Gf&^@sMufwt+Su?rt&BgNS&@ zq0oZ|e~kpZ_!DyT>eahY=h@68n4Oxw1x%^K9GMrj_WcyNpoWc9(RS%P)1mn2}leMVL%WvwnPEFN?4 z3iBASd-%yFQy&xURtjLi7mM&MM*_<=W^>*{&#fnx%< z6Oei31P+<1@00Ob0FZO{kg2sA4Y$dXW-D+Fx6WNZaBBO4_nL>M?X}vj7j!ul1>JgO z*TdQWi>0{=dgpYkT1K$GzlODc6|b^`yUHjb^NL*3j^MLABUk%)MfmH&NB*v1#FKb@ zim!i%1*rM2`8MaGX8fGG{&|i?P1n~s!$J7NufSOOLEMXDD)cl@=O@gnAC-QNf`}j2 zzTg=8dZH&8f03N{zV!YjOt0BN&3OKI5j;?#%<=pK=BK@XM+)jY +#include +#include +#include +#if defined(__OpenBSD__) + #include + #include +#elif defined(__FreeBSD__) + #include + #include +#endif + +#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); +} diff --git a/components/ip.o b/components/ip.o new file mode 100644 index 0000000000000000000000000000000000000000..81b173c75f83acd4d94da98f64ef172c2c1ce26c GIT binary patch literal 2600 zcmbuBO>7%g5XZ+((wfq4160CNL9CFAj3_H_L5N18@;Y&{sW!Bb1gSu<9DAL(jXzj# zAb|>0HLh5hAdZ|6$D9xnr}hw8A|P?A1P8>S%Ap6MfDlM<0b%C9ey`rF>%0&@nPzG3E{L4`XhA*7W`|ul=kJ6BW(Y z@TnwwnchYs&OmRQn^zMtYtv0U{1c+BRxuH4w%1RXn=hcRw|%_7Hq%NZW}0`8Z`@!y z-MX5Ho6U~9ckyO~hq1ihv--D}BU!z@{RrFr7&ygD?~eDi-+lE`v%PwAx;2rAmnP08 zS3fsl_f5@T+(*4%eN{|rdf$kdv-;hA)$;y4xSnZmXa7iV0JGKIPSJd-yFYiNJKD7! zY}@j7Ut2In9F-ELc^A)>XE!D=4&-4;^yQtM5QfM*FH>Y~G;;Fj;n>G) zyvQ6!28qKtql|tO%_#BBp{$~QIBY1%8zY92x_;=qayu5CRep%gD7&!*ZViBSB{iWW z4MpV;4$UYrqEQ~EjsaP)NeJfO@U;Qgl06#x~zchd^4B(dsaAyF&&ip|>H+f$2 zzCIBAadD)QQ@O4cxFXFOPodILouS;6bs=L|xeJq%v)Q@aoRP7zIb^fQYQr)UTly^J%Q?ojlXc`>Z(?EYIWOj*Etje+RM3;!%t*)J^!~>c>tt%;AhMqGVRwyr+ZI| zPeNTf$rNXs_N~2Y3y|e`5rEu*iX4UDJ%K#I1$+pdfUJZk61Fft%^YL?*La;{G3FUA zL6P%67KE(J`DL3HEEV!=35V``+B3>H*-nf2o<~>vR62wVVSI`0hq(lE7$Kht$MCx3 z`NIeDCKtGd<8O=jPv8`gaQq6}`rZGo_{lLvEbbrQw~Uwf-*0Y&EQ +#include + +#include "../util.h" + +const char * +kernel_release(void) +{ + struct utsname udata; + + if (uname(&udata) < 0) { + warn("uname:"); + return NULL; + } + + return bprintf("%s", udata.release); +} diff --git a/components/kernel_release.o b/components/kernel_release.o new file mode 100644 index 0000000000000000000000000000000000000000..31ffaa747951fc159fc5f10aa1d38761fbfa105f GIT binary patch literal 1872 zcmbtU&r4KM6h3d%v@$W13T!b84a2Bv95~9-l{7inlbmzgfyz44g zO`&`@w>-BVZXBW4mu z#!XhSvQMl+1lElx$ju;#DC{3woB@LxurvvG${Syc+g zm-{ARXtNk$2YXe>l5D>>o3wBEvpgbK-qU5nUp0K@ccUX8Oxzyq`LDA8HUBl=VFJ&X+|^i_naAJ|1hk^Pe^cBIk_r$2*gJ;oHv5x@q&FeP--u4u4HMA2sc> dXNn5ugY0Kw%0Z%Wp8IzBcMbW>=wz_-e*;L}yFLH_ literal 0 HcmV?d00001 diff --git a/components/keyboard_indicators.c b/components/keyboard_indicators.c new file mode 100644 index 0000000..b35eba1 --- /dev/null +++ b/components/keyboard_indicators.c @@ -0,0 +1,48 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#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; +} diff --git a/components/keyboard_indicators.o b/components/keyboard_indicators.o new file mode 100644 index 0000000000000000000000000000000000000000..e6e872382e0ad8f133611257c63415a164c71193 GIT binary patch literal 2440 zcmbuA-*4Mg6vwaIv<;BCg(0nC(`2L!1wpNP8`7vWh@CWb!BA~&A!r-MOI1;5I;1gX>WVj6wYz(&DIJ+|T`< zbFY1`uRohLazlbZxC!Jn^0>t*A@R}2aXJXoL?ru&`mXwpx~wiO>y1ZBXHnn$r&QFN zu_Gza=#6YLueAR{`F!K1zSXYn*IOsC$>`s^5bG_PoYWh)lwW6+yMfqf{AsjaL0!NQc|Y4s{+Mn2pfN+S%tHY<1{!TWvZK6n$%a=Xa>5T{(VD-9CQ! zP8@o!sN0FddS~~}=SJ%Y&QSe1c8KUrc+#T&Qun#(NRX~?-Ygl7-_D#<&#LFt_f>N@ zzfiH=>{_+rSoIkxXRSGQQKFvY0hWqgPRLv)Gb5$u-d=uDQWRN{r*Rm31rqoOICPOA zBD9fl6Ih$C-LtGi`1mvtHYS9FiLv`eH;C zr!SA@#1oriS@D`MoDjqlS#eqwQy>8;q-bKC6^XcE=@_}+8Pq*IV22$Dg!puO4d?ny zNFU4@7`~K=z0#nSi{Oh9JRiZG2wsWcpGNS@5&UWd{~>~tb-TXeS$@%6bBk*Qi+X-l zE)dzsOb_ZJ=A5yhsfM|b%Pr0>nM%$g*;0m%i+cS(NErf;&+8PBD@=a7}!D#>RY zuWGZsN~+X%9or?QS)lcbZBoziF4(^5c!dzFRVqDJrB-3xER@#GRoLc)B;mQxaL?jV z^03pjV+g^9z=y#(pFs$Q`Y~|MPayYoJXyo?YG`BUJW zZz2Rko&e|kHbOAu`@lJWgb=KM+ym@GM7;>k^%BHrs7LRaT&wL)Zg*WG)GN51V? zGPO4-k&70!h`ds*6502#fpRz`h+Oc>W!nXb>rq>VBVsC80@nV}t;rQ1&KaN9Ar%YS zC3Drc%64xC|0|Fn8y`9Jn+WQqgDWBYyJgML7u_WX;fC)j-EH=+C4^vc_C9f~FyzP2 zBzA(m0FE5@P}s^WFU&CR$1elJn*TLlVKtA!J#2jZ;9n8y;N$aq8u~B}4*QVq8z$Hv zVi@u~exDDqu=IN_2*Ux|_kiJdwr5X5`#Q_-pBI1sAPMX|Tv6Jef1Bl(y0YH2KOfKA zLF->(zXZO{xc>Nk^L)++jg5n)*@Q}L9{5e;IQ{upvw!UYk?RcJz(&YexgL2MqCxrF NZ2q70l--~||6ehXY03Zq literal 0 HcmV?d00001 diff --git a/components/keymap.c b/components/keymap.c new file mode 100644 index 0000000..ddf7a15 --- /dev/null +++ b/components/keymap.c @@ -0,0 +1,87 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#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(void) +{ + Display *dpy; + XkbDescRec *desc; + XkbStateRec state; + char *symbols, *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 = (char *)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; +} diff --git a/components/keymap.o b/components/keymap.o new file mode 100644 index 0000000000000000000000000000000000000000..d23e66dac4f30b96a717f237463e566a97a737cc GIT binary patch literal 4096 zcmb`JTWB0r7=X{_(xjSB(u*~Rl2lqIbl*1j=kP^)8%iK}+u@?*`Vu z!CLO%CS4c{_ngCN>#l6?G7S68NOiCeywGZ?i}#Lr7jZi4Yt!NM`ehib^V3+kCoU!u z_kNFi|G*kLgwHQq!Z>^CEzwgyvR7jJSh(W^qYG;|twyL94|h}VFY2+d7>HJ(M!lb5 zDcl7tVHd5U)

cnm^x8_nn`<06Jofs}9vBRNuHUaa9EDP=}-I$}* zo#Fb)!(3rrTw}!hDem3;98Zw%pERp&;--4b8>^|eC2TKWzVRNd!g;0XHgS5aRankn zq;c<;=O*mu?Fst@JFzr=sN@!6nMx_=%&qV}-M4mx?aqAQkNR?fIHT+yt|=99%-Me2?+a1f-+M>H#_LdL085MfTl7<*3nhx+!LKzu6o$%!QVy(fdZLZS=ji$~N}Sx5bRPQ1iDTV{gppvyEO* zi5lHt5;fYTlYjzUw~*V*jk=o~M-?r$9G8ngOBf#{Hl*X2JLm){_rybHUO#1r;E*J z1NdYB&j#=l0sQp<{&oQWAb_6@;2#I@&jR?R0RB|~|1N<48o+M{a01~e@06?*eCjh! zE|Z22(~1x9EP}Nim_3TwPRw>;wi~lO(v&2IH$#?cy-Z?R9Kl6vsmQZ0v3f-zC;p<6q_x%iDUwzEJ>EinF5<6<3nW^f?+m^ zr3%XR0S_!8WTvu-)KoSx31J=f1?53ez_%^#^f zM?d#y{0qrZA7hmAvn08HToo5k|87km?;#56Z-k`$s3#ceV>DBIBL-Fw)V~*!;yoJg z*7$D8l^+%Rhc$iO&yyO*n5q0{G_KEcR`ZWfLZv^a>EEaEs>U~K{C$n%9F?E58oyuT zpGc1DTBC9P)Pc5t|F3F(Fy<@&Q00Q%&5+c-<6S~gyiMAx7_4}QE`4>IztSU*sRkZ_8v49b`v};g zPx0S}iWD{e2H$|Hsmejn$GU&~qY{|XpDO(Ae&}elf44A5fgI(z_-62o{QEZ!49Azx zPN_}EoE#rxuP$ods&t@J)pfly{sqZSzwV2`G4A`1>s@K@pO>1y8q0$U`t;jhk@izc zQI>xDSAjR$zrz@`LDW6N`-e!`E8b{qwCh8sAlKx?45(xB+vC5d(N=Zirhqj0Hq6)L S|JX+MQ*!=igqvFKxBnNrM71mc literal 0 HcmV?d00001 diff --git a/components/load_avg.c b/components/load_avg.c new file mode 100644 index 0000000..5c2e252 --- /dev/null +++ b/components/load_avg.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../util.h" + +const char * +load_avg(void) +{ + 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]); +} diff --git a/components/load_avg.o b/components/load_avg.o new file mode 100644 index 0000000000000000000000000000000000000000..0287b71ef62d6cab859845f260a1a89e849345ed GIT binary patch literal 1904 zcmbu9%}*0S6u{q>B2^J95<`N9Jrq;F#x98mNi^l7r6yGpEQwxRx9zqi&~Dw12zu~9 zJP=~SpTb{Yn&`p*M2#NQGYP)8owqFmO^m)|I`947$4uwV?AuH}8!-%EG2lLQEv5iJ z2fBJXP}491=ODNJBl&@R<=k#`Dv3&NXCX0ewR1aPzEa$~_SPs`@9&Wj5Uc%t^7r|8 zArZ&ld?KcN`vYi36G2FBw~!bw=WdJz73E+DZhuOCth#dDbIQ&}b;is(tLtvrl%DAo zrL)>F$zwVjuJ2S`m=e@eM;F?!(kWlZ2 za2y(Dsh>};YyA2F!c+wSkWp4#%q3mko zrD*zI)Ai*Rrcyz-W>eDrsf&J!3b&Beo|{p|eUeQ1fSXNPEgY zi!RxG8(eN*;D zjdLE)4^+Mu1_wG&Hs`VXDJt|nj@(Idsz7~TeEt+d@&X5i>iMa^%%`_{QvaW*hH#&$ z|MbpyedZ^vjbZRytshe}eJ|;2spnHoz4wTqrvA_~GI~Un3kiL1Ps(p9_$G|(D0==M D#3{%~ literal 0 HcmV?d00001 diff --git a/components/netspeeds.c b/components/netspeeds.c new file mode 100644 index 0000000..0029177 --- /dev/null +++ b/components/netspeeds.c @@ -0,0 +1,139 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../util.h" + +#if defined(__linux__) + #include + + 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), + "/sys/class/net/%s/statistics/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), + "/sys/class/net/%s/statistics/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 + #include + #include + #include + #include + + 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) == -1) { + 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) == -1) { + 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 diff --git a/components/netspeeds.o b/components/netspeeds.o new file mode 100644 index 0000000000000000000000000000000000000000..db5a6709b4ec7fb5c7e53f9da1f121c3ec4c7750 GIT binary patch literal 2800 zcmdUv&x;&I6vtoBZjzNG<3=McL}dcIk{{ZW4tPU-PYZ`=*L zd%(K~@eO{wMdR#r{HL(idoae@?~lUG@3I-g?iblYE8)q**~)rPpI^I!ye_|e`+t}+ zQBieNu~LtfDmD{coKZ!kV_j3aR#C;Y9W8fsqG;ybjeqvk;z^5hb1xT;EuOt}ybuI_ z;Ge?55{{J$+;G}#q#SuYFcHs;rA7`LgZKUg^4gQ$kpufCK4T;9{262W2K{V)@{`>8 z{M1Kdi}{;{+>QJcliBL{NYt0d9C<;c zf0}i05#dKOkkzJ`vi^C)`~ARl((n@llxaBrC#*cPb71x=H!j;Xlp{PJA(380zMpyrN~d$F@QTiljK*{8;zvNF3okF`20k^n3bRzzti0CTj_c$Np*)qF=4VA zRnxeUNM`@7FK{@H0<~;Q$qcIIoW$k~33ZPjHvy=9sPfKD!N`L53>i{%hmtzIC#`tQD{V*V6(_FY)IcF6&EQVmoxax3>IY9Gk=pZ z>lU+J_uIv186-~7Tdd%}aor~kaPxBak9Pudy746gT5Pk$jjywD*!}lRLCN~K|HrsV xyxjk=wXxn!v;GaUVZ3?6;=$azM|^1N?{f?+anJ7%+lIyeX7c~QiiPUN{|z^Tn^yn; literal 0 HcmV?d00001 diff --git a/components/num_files.c b/components/num_files.c new file mode 100644 index 0000000..fb55df9 --- /dev/null +++ b/components/num_files.c @@ -0,0 +1,31 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include + +#include "../util.h" + +const char * +num_files(const char *path) +{ + struct dirent *dp; + DIR *fd; + int num; + + if (!(fd = opendir(path))) { + warn("opendir '%s':", path); + return NULL; + } + + num = 0; + while ((dp = readdir(fd))) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) { + continue; /* skip self and parent */ + } + num++; + } + + closedir(fd); + + return bprintf("%d", num); +} diff --git a/components/num_files.o b/components/num_files.o new file mode 100644 index 0000000000000000000000000000000000000000..2f800b1895e3012c22f1f4062d9352d0273e5eac GIT binary patch literal 2192 zcmbu9OHUI~6vyur5acmd@Iitm;{vHcCk)1gB$^IwVMrQ?JPe3UGqi&=_T|hFK^Mjl zNt)P%g$qAU6J7WL+-ltUiWqk;BzXSQd&@9sH~LS`+;e~DF^_xaK1(F0LXyOUBzBt} z%>-pE+;QYbJvYi^*2navg!V&UTrw&L3r6)KB6q*wI#YRTyr{X$$;xMMj>)J|-54+` zAC1aSj}iK0RBs?%pq<~6zVqSm`#Vv$60hv98r54!N@+FyzMlG8FWA>=oO{jgX|>f9 z!f#4ttC-E%%E+)YGQm`)s%$vR*mNv5p+u%Udcn}EkJ(b(_1ulMf6M#+M`QKGltGcEX?7JRt{H(T&r3(kt0h4gwZZ#im)smYjz z%Q!CAaTz;`v-EUwZc5{v0YeKMIyGrrlFZJAlxbj)$>Orgv&`I2K{zE-w# zMR%P&Htixk!znT-MAk<3=diA`fF$g_lVpMq1CqeI$ppU%NCNL66Fd$`LVv^r$Nq$Z z`KdbgcrW=PAKwc?AFR6I&jCr`C&&cf1tg(A_L|_EfFyA2MZp#FA@qSYq&nLL*IZ*N zeaQN_Aw1j4o2qMVxlGNPuF2Fj$6=~n!UXB`Q!_PFDio|Dr4&o9rP42b&2i1lLq2~{ z+*Hdpt(om^Qz;r+8|ii1ELe>v_%BDHYKaWr#;+)!i2p;xkn7hFP4KOven@^9n}yWH z3$W&J#c?r+An7t0I8O)i^juirqDPr>>; z#hR`E79dHiGu9vHgs2z1*}YNsTHK$H_}B5C!Fu!zu05d!#2MxnZ`VMl$!k`>$DjXc KBeU)V>;D47a|xXQ literal 0 HcmV?d00001 diff --git a/components/ram.c b/components/ram.c new file mode 100644 index 0000000..47e6fda --- /dev/null +++ b/components/ram.c @@ -0,0 +1,222 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include "../util.h" + +#if defined(__linux__) + #include + + const char * + ram_free(void) + { + 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(void) + { + uintmax_t total, free, buffers, cached; + + 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; + } + + return bprintf("%d", 100 * ((total - free) - (buffers + cached)) + / total); + } + + const char * + ram_total(void) + { + 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(void) + { + uintmax_t total, free, buffers, cached; + + 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; + } + + return fmt_human((total - free - buffers - cached) * 1024, + 1024); + } +#elif defined(__OpenBSD__) + #include + #include + #include + #include + + #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(void) + { + struct uvmexp uvmexp; + int free_pages; + + if (load_uvmexp(&uvmexp)) { + free_pages = uvmexp.npages - uvmexp.active; + return fmt_human(pagetok(free_pages, uvmexp.pageshift) * + 1024, 1024); + } + + return NULL; + } + + const char * + ram_perc(void) + { + struct uvmexp uvmexp; + int percent; + + if (load_uvmexp(&uvmexp)) { + percent = uvmexp.active * 100 / uvmexp.npages; + return bprintf("%d", percent); + } + + return NULL; + } + + const char * + ram_total(void) + { + struct uvmexp uvmexp; + + if (load_uvmexp(&uvmexp)) { + return fmt_human(pagetok(uvmexp.npages, + uvmexp.pageshift) * 1024, + 1024); + } + + return NULL; + } + + const char * + ram_used(void) + { + struct uvmexp uvmexp; + + if (load_uvmexp(&uvmexp)) { + return fmt_human(pagetok(uvmexp.active, + uvmexp.pageshift) * 1024, + 1024); + } + + return NULL; + } +#elif defined(__FreeBSD__) + #include + #include + #include + #include + + const char * + ram_free(void) { + 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) == -1 + || !len) + return NULL; + + return fmt_human(vm_stats.t_free * getpagesize(), 1024); + } + + const char * + ram_total(void) { + long npages; + size_t len; + + len = sizeof(npages); + if (sysctlbyname("vm.stats.vm.v_page_count", &npages, &len, NULL, 0) == -1 + || !len) + return NULL; + + return fmt_human(npages * getpagesize(), 1024); + } + + const char * + ram_perc(void) { + long npages; + long active; + size_t len; + + len = sizeof(npages); + if (sysctlbyname("vm.stats.vm.v_page_count", &npages, &len, NULL, 0) == -1 + || !len) + return NULL; + + if (sysctlbyname("vm.stats.vm.v_active_count", &active, &len, NULL, 0) == -1 + || !len) + return NULL; + + return bprintf("%d", active * 100 / npages); + } + + const char * + ram_used(void) { + long active; + size_t len; + + len = sizeof(active); + if (sysctlbyname("vm.stats.vm.v_active_count", &active, &len, NULL, 0) == -1 + || !len) + return NULL; + + return fmt_human(active * getpagesize(), 1024); + } +#endif diff --git a/components/ram.o b/components/ram.o new file mode 100644 index 0000000000000000000000000000000000000000..011426bc6cb1224793fc1e9698c68f9f76579317 GIT binary patch literal 3128 zcmchYO>7%Q6vxL-(wfk&LWxkMa@d1|93^bCrIe`R!_J2@kz5)k` zv3Ag^9P>SYy;*Cq`!g~h)oNbQx$9}ct<=5h-65N-?lsKV^1{L?Gq?QwOH-z8TedZe zy9lA{$4n|CRA`!|S*i~vB_+o4O^l0))ax&>)RnQ+(L)C_*J%>`Q89M`?V@3(%SOhe z?g@-Z-b1x$aPlDAOlx+_KoI7zVIVRm~b zX>KUtg&&L;A`17)p?EmLp1K#ahXh~J_#=Y9qw%AHzpHVR#z&O>#IYkbMP-bNF3%B2 z;>CUV>OR~h4!_c0oEu^n_gNo^^#{a7i1S2jQ}DXrah`~=!1b*Pvq}rIsBBcnQ9Xg` z1g4!Dy%^>!m(I)=O3s;L@x`SzXRR<_T5?#sQ*oO$R`Wxr9{FyQIZh{ZD;rLwzTwp9 zVZ{d8UQl7>cCg+IYcUA%DC1t#@v7LyAg_$>HDg0m{@59afk_f@+;_=m07<|`sYt#8 zNCN&K70F)(Bmu`=k-P~=0{ggCl1G3fy5IK)c#q$21jqUVRHU8wV@hNA#aSf(lll;S zKZiwrU&F!i9m!_|2UFuvRJa-kN8xH5T8e!&4wn_K`u#w$qx!w2aMkZG3RnG_ zv~LK`iy~!CbR?Je|7DHKdmd_B-g9PkuKJ-{rZx-)ZC&;Pui;vucO_(2)eT){l{+0~ z1uYD)oIb$Js(b$T$a@5z(=x7H+e zgbsH~mAn}ID&i{Vv?0Uy40+4T1)}{HNhY}?6p$-)<%fC#lO&H(0mqwE<)oS{WkUCl zcM6;Lt8bGoY#yhgiuC`X3aKys%Qi3AthVlZvHyoPF7;%K?}_ZIOMm~D=RZeEc*lE| zi-73+lJS?mE>Q>mb^TePe_bvVt*+l7o|OMv;)DB|&_n(opd$5U{*!z|r7!%yErNqL k4P9LyHuc;SVrRwuyM}=xdaUvPPST$fj^0po(be_;0-i7ap8x;= literal 0 HcmV?d00001 diff --git a/components/run_command.c b/components/run_command.c new file mode 100644 index 0000000..e00b478 --- /dev/null +++ b/components/run_command.c @@ -0,0 +1,30 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#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; +} diff --git a/components/run_command.o b/components/run_command.o new file mode 100644 index 0000000000000000000000000000000000000000..0394b194c547935358f9ab401818c352f384e22e GIT binary patch literal 2176 zcmbuAPfrt35WuG`2r8@y9xxcQ2N6Wsv_vl?nr@+Gi5o$o2NlvR?Up9eKW?`X^dN}= zvxzl+20jRB#P}t=5M!c=iN>=MoY}r9%d)-bB(HDgH#2YE-|fq!o(hLTz!HKxaAYyX zzVk?ryJ{RH=mj;c)o+olE~Yi-VB!8ZGG?6*+E$}BpgBLZ`fVbyhU@sA*X!eCYtH-K z!w7)x{B#|<^Hp>9Ty?9l5s)~hZGEzbch6uh=U@pt@)2OutpIv`m`1KelCdw3bZ7tZ zvbv-$?^#eOSIm+;GF%;*gi3a;Ts4IOGgDKO^61RH^ffsaQ({UKI&cIT8!Z<(gdx-* z#u5@X@6iR}2t9uQq4mDdP)}F)J9OSeeo6Rts82|J_3*4T_$H!C@^;6xH2SJjm7?L- z(&)4#tI{9_B&2SUa-ySp9q{Y$gabh&;Ka_kfu2JXiOu+{8u8OIjHQ*HR&HhiuPPq*PqZ8%u9QYKq27L8I)$%3L!Md>F-KNDUjWM=fa zgsNxeQmKXHVrEfI=*dj;?!Ys{D#1!E5BXKou8KpNuqplI zM4>xGhs*p5K@^H7AM@)3QHY(!#+>dG3B}VJU_MO{h2qa*V@~@=Lc9kX^JRi4G!ESk z<~f2W6z{FO?$RdjMV;ff1?Tzv7VCZM;~X!0IOViNscsZ)V+9o4&1PR<%`(>v#WvS% zP;!QCfU;7pf?}1)pm2P#pwQWxB@8K*ZBxM~J6^So>=R+HmTF4H!uN048< zGKywv2LGkVm`!iIcFe@Nv%Leir?#dqewz zU_k6cWL?<8-elA{-#;(je-3|&3YGHb$3^{l4ivpVe+_xi`4Ye#_K09#EGS2YN5pU~avrsy{7o_c7p=&q;?MsJUTY13 literal 0 HcmV?d00001 diff --git a/components/separator.c b/components/separator.c new file mode 100644 index 0000000..40fec52 --- /dev/null +++ b/components/separator.c @@ -0,0 +1,10 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include "../util.h" + +const char * +separator(const char *separator) +{ + return separator; +} diff --git a/components/separator.o b/components/separator.o new file mode 100644 index 0000000000000000000000000000000000000000..e9bf5ea90c08b5916eb8e9da716c5507972eef51 GIT binary patch literal 1200 zcmbVKJxc>Y5S>e+i5kH#Fc6Dash~?z*jUIxj7cFDf@mYUiE9FyT)0~yv9Z<8pJHh# z_>1i9bSAfRZkB-Hz~0PzJ8x!p=N@ZEhbhkkHV^jU7cmR)YLWhk_8|{*(0Km(fO@sM zSK6!}pKg^Z6;TmofDGo8a82RD4M>6aP8^$OFqd618{WeSc!LG6n9t^3aFh5ovuEqM zj_avj20p)Co^X1?&E}C`viPJ&r1~K~@yJ9p>}uHr5$Q1Y9gegb zXb{&@OAyT{0?`V(UDZRb7icB$d3GW#Tek+cd-tLr27MLkA&5}jNufHIH=*n*ZuWm) zL@B+|v{S-2IJv*UJReS9$AGvr6UHAnn4zoRz>OTP|LV67BQNnZ^ literal 0 HcmV?d00001 diff --git a/components/swap.c b/components/swap.c new file mode 100644 index 0000000..2509db1 --- /dev/null +++ b/components/swap.c @@ -0,0 +1,284 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#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(void) + { + long free; + + if (get_swap_info(NULL, &free, NULL)) { + return NULL; + } + + return fmt_human(free * 1024, 1024); + } + + const char * + swap_perc(void) + { + 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(void) + { + long total; + + if (get_swap_info(&total, NULL, NULL)) { + return NULL; + } + + return fmt_human(total * 1024, 1024); + } + + const char * + swap_used(void) + { + 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 + #include + #include + #include + + 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(void) + { + int total, used; + + if (getstats(&total, &used)) { + return NULL; + } + + return fmt_human((total - used) * 1024, 1024); + } + + const char * + swap_perc(void) + { + int total, used; + + if (getstats(&total, &used)) { + return NULL; + } + + if (total == 0) { + return NULL; + } + + return bprintf("%d", 100 * used / total); + } + + const char * + swap_total(void) + { + int total, used; + + if (getstats(&total, &used)) { + return NULL; + } + + return fmt_human(total * 1024, 1024); + } + + const char * + swap_used(void) + { + int total, used; + + if (getstats(&total, &used)) { + return NULL; + } + + return fmt_human(used * 1024, 1024); + } +#elif defined(__FreeBSD__) + #include + #include + #include + #include + #include + + 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 */) == -1) { + warn("kvm_getswapinfo:"); + kvm_close(kd); + return 0; + } + + kvm_close(kd); + return 1; + } + + const char * + swap_free(void) + { + 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(void) + { + 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(void) + { + 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(void) + { + 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 diff --git a/components/swap.o b/components/swap.o new file mode 100644 index 0000000000000000000000000000000000000000..499b27d472f9b1ff964423c0c180b4ef6b66bf25 GIT binary patch literal 3968 zcmb`JU5pb|6o7B{2MWSaSJXy`>BArew6y%_EGixLcp!JjDgoICe+?@rppL{BpJ zp8MT%&i$KvW?mZ7hdX>eBE&~_kolINP%oR;`Y&{Mt$A zO4DlBnlLET8B`}}tsBj0r9qu3wV&1=#^#FGKc&;ReAKbkCuwafvzWfzpwoZ)=of=( z?-FzY*aMC1QfxR0wS$iL3{g1HKF=Ps#{duf&ECR0oNO7KnKfUr9KfHsZHJO)18~TbAdL# zWCm9cG#ZVO>Di#(msb4~?_J#u?O0v=7>|ls{OqTE#uVaArs)Rv4D4=qgyXX(!F161 z{;7l7)7nAp8O?wbxE73k6>BUwFn_F0oge4aTaAY1)MND_m{Jd|ZdX4cU9bn|uPk)~ z;zD4QmF%R&C@@2e8eR}F2oYPnq4LndqMDQNeCXitk6d~h_8-Jh>y2L zZdl1Xd`BNAzR7@Z)w0F@SD}*vU(Ng2+Zk5^uXMzf;OWk|5~_8@mGG%#=WV?C&ZIv!K}$d6$gKgz(Ahm^hpbdYw z4L90w9IsXULL2^k8-AhpM@gNotVbM#B zo%)`*rW<>PhxZO8jD!}~hYUBhkc??rMN1?SQnsx^DqkXoF;*_7`udD=Ih8DA$l;__ zAemIIST>=rY$sFWMk+gQWRhb!!lsqMOqR*pMs^~fEV!&>S}8JGvc?K_#w9k(e9U2@ z4Ec@_6&@5^Hs&Enu}n521VN6sO7LNXAjlWNBlwF5L69$oNAQ;sf*{AcEBHGIL2yh3 z9>MXPQP3WLP6V%mj)ENTrr>yPC>Uo2Jc56V5Cl2C2ZCQm2!e5LgGcaAo>I{Mc8O~e z?~(YZ#4#s`I5QH*{3-ZpiQg&lvl7P~ChUKeIObKsm*B)faGtWg!8um=3n}ailKnjr zpO&~BXIA3!xZg-zwqM@~K|ydnvi&0xm+eDn41(c!NY>7=a-NI(KjY!zp1Zk&AtTrr@TH8NH*Z}JKK$0`K=_)6fNlck?GDBo|<$6p`O zWZywNqy8pwl{5V7T;hj;cLIGmW@n0)_i^qShMe>QGzRgGe?Ksc={5hi{xKeN6V$Q@ z|1lYYF2)yiKW9;o-3>k=?{{7JiF!neDTnC7O>H5VtY1&GCu literal 0 HcmV?d00001 diff --git a/components/temperature.c b/components/temperature.c new file mode 100644 index 0000000..8e1f222 --- /dev/null +++ b/components/temperature.c @@ -0,0 +1,71 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include "../util.h" + + +#if defined(__linux__) + #include + + 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 + #include /* before for struct timeval */ + #include + #include + + 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 + #include + #include + + const char * + temp(const char *zone) + { + char buf[256]; + int temp; + size_t len; + + len = sizeof(temp); + snprintf(buf, sizeof(buf), "hw.acpi.thermal.%s.temperature", zone); + if (sysctlbyname(buf, &temp, &len, NULL, 0) == -1 + || !len) + return NULL; + + /* kelvin to decimal celcius */ + return bprintf("%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10)); + } +#endif diff --git a/components/temperature.o b/components/temperature.o new file mode 100644 index 0000000000000000000000000000000000000000..cce0bca170b19356ebd5d7f3acfe36c1c1044611 GIT binary patch literal 1736 zcmbtT&ubG=5S~p_8?nZyJt$QOm`X+a%z6;ZvjPm_T<@9K~a11BE*@OH_2v6E;=xoneUsK_jcaoMLL%WXd19+unMDy zQ2=9RvHLwzHui!`%QC(d3+X+h`}Kh6WVe^>?|0549eaO( zz4XsU_owmu(CB{Bdotx)0Mqvhu~6B#ydZnHvyw1&KSmyYSbEX{$fi;^qs!U#jZ0Bo z7rKZ;5SvF)XHgM{0BAkJSTq&$H!Ubadv+JJ?TEHGKNot9?~?zJXJ1^VxwHwbcFAf~pxAP14YvZO*>ZqLIu1J%<(>Ryoe6XHo<_hchry`srVRLs^x_~qwtFg z_x#Nz^G5N0<3IljCQ#3Rt=F-ZdR{~I3ZKt=#T=i{Hh~2BaZXV7t+JV(x;3+!P(_jBfCEVadW&QQ|*PHnM?^Hv6XL|pm zs9ewZq_gR$W%Z$7C_tG +#include +#include + +#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(void) +{ + char warn_buf[256]; + uintmax_t h, m; + struct timespec uptime; + + if (clock_gettime(UPTIME_FLAG, &uptime) < 0) { + snprintf(warn_buf, 256, "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); +} diff --git a/components/uptime.o b/components/uptime.o new file mode 100644 index 0000000000000000000000000000000000000000..aa8f4edaf0b561fcd518814822b13f9b581c8b84 GIT binary patch literal 2008 zcmbtU&1(}u6n{xu8@0x$6$16Jhg2%+()H+P(%N>FXhmDlgDl%*)5PY>%@$idNI}I= z0v^105szMkUVG7?;@P8rf}kRvL=fux?apjBYjV*ayq))c?_*}?&CLC&>~u5|A&Cf` zrEN>HMA!Sb^|Y&|DNcK6{>>m;`r228v-0|S|L7R(=7Us{39YTSoK);H5+1f!RlQYC zB{$uS)duD35oFA3d;ZsJ1I($c3>-b@t)1~T?~sca`!4lRuYksp~2V_cBYs=Bz&(h zX5xuQ(QJGp8hsv5Wa2U5>ouT$KmFM1=I_H6hOo=EvFc9jbz9Tu1ZN9I4sKaeOpEkuj58h>2Kb#Uk}rW|pbmVJe+-fV4n36o3)TVfyICZ!unwRO#E05gtvKcasSU^W z#-h}0t8A){wc?PPHyxAIg+_x^y9NW{eEdnx)hZRM$|2R7W2t=fkGp#$?8WM`TDNO; z%XU^d6$P!LQLxR5<*(qs6os>Ks&|B{q=hZdr*wyJ0M0G;DlG%Vm_*YUFTKItOXQ+w zK++rB{(~3cf+hOqYn@7X{$uP$&410u{X)$XEJ4Wm@qa +#include +#include +#include + +#include "../util.h" + +const char * +gid(void) +{ + return bprintf("%d", getgid()); +} + +const char * +username(void) +{ + struct passwd *pw; + + if (!(pw = getpwuid(geteuid()))) { + warn("getpwuid '%d':", geteuid()); + return NULL; + } + + return bprintf("%s", pw->pw_name); +} + +const char * +uid(void) +{ + return bprintf("%d", geteuid()); +} diff --git a/components/user.o b/components/user.o new file mode 100644 index 0000000000000000000000000000000000000000..7a69e2bb5c8bae08faf36571b5f076606f7c37d8 GIT binary patch literal 2232 zcmb`H&rcIk5XWZ`qzW{M8Z~(61<^!SmYCQOHHD^tNfDz+0He)9mqMUF+%5t1;K>6q zCjKA(10I{0=pW#PKS7V)O>n+%XUcYIFUCoBXWnOiytnVozIVC&OqXSmibW6UWTccR z-E(4RjG3V%4bYRH7|eZq0JVDf&1w9CwPf(&_t5*k5e&_J7?&ugv0`GPnMgEar?L9A zL(P#QmAs&~x4TtLjgAyYCuyWkG@H#%rf$wYets+EIJRStV|t=)ep38k+3ch)vKnA2 zmW=gVFNwo?^OUUpL2J0bH}Q#`;Mc`>1$rtuIG;=yc2~IhcIL0nClk58W%h=7i{g*w z2|A^)j&AyWe9FP#Oq&zI9O2g)qxl*zRu2s|Noa)Q9pB=|*0xyROv-ySTseEB! zX69LLv9LHbozE4}R;8^Xt=0UkO0Z#4D{k2X_qf}dZAW{qUqNx=ehLLWg|ql`9LhQ2 z@MEu)UlWe_z6ei6cz=Z75so^@(K^^qNW4xq#AaRSd5zBtM?88%IrbA0uk$j*rcQMI z7lk7p->7x&b>O8AJS808rF#gJj&bdm%~!-&J#g2zWn8N4+BLsg^Zej|Q&G^{ENuAb zivJ=hu7ZF5Y^+*F#@jKj_mtvcHgFah1)|gPgQq0{y#_P9FNm&6+zsIpE|lnV(`q&1 z^WSDSYW{1!!?~zA!B13l{>xFww$86QBTTOQW^_X=?N@bZo@(41YHJMikLVy`$75I6 z*UL||hY@~+7fXCyy8oe<=rtRt8P8A1M4K8YI-bA7yxsZN09ocjW$qgMubQvt-)?TC s)O3E)xRcPM@qE;bpFJZwk`H=;K}4inlU!h{UH%tY|J!C{XvFjX0&42_zW@LL literal 0 HcmV?d00001 diff --git a/components/volume.c b/components/volume.c new file mode 100644 index 0000000..b6665da --- /dev/null +++ b/components/volume.c @@ -0,0 +1,217 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "../util.h" + +#if defined(__OpenBSD__) + #include + #include + #include + #include + + 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(); + 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 + + 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 diff --git a/components/volume.o b/components/volume.o new file mode 100644 index 0000000000000000000000000000000000000000..4b9f16e14eff5bd580fe91892cfa5134c75aae0a GIT binary patch literal 3656 zcmds(O>7%g5P-+|X(UDLTe8E z^)<9hH%ecqE8~G?^~RU~3^f!f|74&w7W&DFiLV@_49suco_xE1IT~n=mVWr=?<*cV zdUW~FkMYtSG1>f~>wvYWuD5h2zWWw0V*idsh@8;c?MDVT*9XsUJUIWpU@ceefOq?> z>hhb;Qzq5Uz0PCXjZSIx+&by!ry?gKQ=ij{|A%7cjhw%uz0h$4(xz@_{2gN>6T?w$ zXmBz%s*T1XQ7sxfF%%g)h7k*9hNHH|gYB8*0UT^k!gQig0NXOAGX@lva&`*xdKL~H8*)L;owuq_lvO*1^4<|SL%j+ZEw^^eg0P)BEI1H#sS}@x_Y0- z7mWD)5nmgI^!mIasfMCb4e-Ziwc+}zCmWz1|Eftn?An3dpMjmc)rs5%&WWtZx?k|S zD;Syk1P@94VZo0|yaW9`73+8288Z4T?%dlG`fKoGHTdxw{6q~tRfFp__*@N6XJI~T zC^{(dzVH*&cRA)^r+g(+8&$R?ajN;{;JC{vK@17YU*e_hDmxmLLk%q20v%b%H3wo3JszOb|t`|DlT=-hwvA zuUGKOdA}B%>eEr;`0py>E7$*h1*d(+@qg9eyhW-0?uz&(I+!T5{(G@;orfy;o(hhp zBkp;I^10&U&z!#pp8@8hBELH`-P_cNv$kOVJT}Tra{5q4p*nx zvW!eZv5iF=6vs>^>;x#&ct5`=w6A-xZ4*&&m5QU#Zy}jp za!}e_1)Zpg%QtCJg_s97QXi!Z#|CGp|FguWmB55@V+tIbV$*Tnoc#RJpb kR4t#TsrIUhbV;L}aaFmO-yhvc)$+YG8A{RVw>mlhUoRlUuK)l5 literal 0 HcmV?d00001 diff --git a/components/wifi.c b/components/wifi.c new file mode 100644 index 0000000..92c252e --- /dev/null +++ b/components/wifi.c @@ -0,0 +1,272 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include + +#include "../util.h" + +#define RSSI_TO_PERC(rssi) \ + rssi >= -50 ? 100 : \ + (rssi <= -100 ? 0 : \ + (2 * (rssi + 100))) + +#if defined(__linux__) + #include + #include + + 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), "/sys/class/net/%s/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 + #include + #include + #include /* before for NBBY */ + #include + #include + #include + + 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 + #include + + 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 diff --git a/components/wifi.o b/components/wifi.o new file mode 100644 index 0000000000000000000000000000000000000000..3381045881936f11f5234ccccc3b992eb7bbe1b8 GIT binary patch literal 4336 zcmbW3du&rx7{E{4l|6*p$+HURopx*v>{=8RjIws?b{h&4w?Py}>DpUp=-SzPCz~39 z>=AFa8jOiiV*Cpe5{Zd_`pBqk3;Kr%F)<;*1Y(SUfMAyRh>-bx=bqCYuI)d5={=9% z_c-T#_ujAfNGQ^7x7i368+o2A%s3^)w`5`5LWeEHMI;i~r5Jxtky=8O{0iiOo^X4_QqZ#eDjjB~E0HdL^4&$;&DImw*sCDw1a&2})W zOqjV%DC^B+>rPX3YzFUvVqD$R8`vA@4eXo7yYtuQRS;+jG^B^!wk~DlhEKRxZJtJd zA#D5{F|N#g5;4ApK6$Rq&w{SC_O&7To{DJC==bDMmXhi`bhCpj?DP*eABp& zMVhr?tvQ~KX`_m)bMaBr>0d+ z<0k*rfQww;l#pe)9vV7=rn;Jrp+!_(Z6a(LKuqf4rx7h1Kcwn%L!dnx-Vy4CfT?U; zPs-YKysQ|4E7d{f8Aa-Ia zAmi__jm@ipp)5B$VtegHVjHTptzKMNbsUUafUjY?&(Jw2)xK@tDY^5Gpd?RLv`LNQ z&Vb|_S=1q&mmQ-v$p z;(+yL&YYyl!p(J@#B1T}=-f#H7QUYGUJJ*Z;@y4E!fB->i!787d|C+bg%g`5TWRMc zADGi(8)E#!A~6Ts82{A5cfx$BkbnBD0NVo>))T9|0-zLsy$nBAhL4xwlV$k3W%!9Q z9BX{3eSTbqpDx3{D#K^W@E?Fg{&B{p*$8s5xJfP}OO5^FQrV>rh#rp?H-(V7l@WU>xW=J%ef|9s-b5zsf zu}qTmu|Ux%)a&@6X#C)zXfl>cn|pxboJz17Y8FmN0pXu1_@{(#_Z|47MKS+H%zBA6 zkn>I$qo6&$O`N}s5Cq>N{I20VjSvLwE8*f?LkNQQE8*fC?+XfYtRbAgj}Qd88!paI zA_T$sSi3mK=M4qzAApPVFA##DJ=S>6&msgtdvX8YQfk^i2xD%4LEtq4zr;Ak5zlp3 z;NrQK*h~f5i|1M|@YSH>>uwb|)>6*5F^=cDPvE-+`?Ug32=3)P zBkN_$+z)e%xzWP8|BQw6^?Ba{dK{bIX$!_D*@pOexdwBE!u#zoMt>hdK~6LOWdg$? zUzhj01SXoEu_lBmxgWPp!T|p_tm!T=f9t-i=Xn!+F{ai3HuFCYI#I0t!=Nnn{0!j( z1H#wGDgF;|f2`#wrPfA%lqGmS+XvQKyhm1l{EsS?s>_%Zkeg;#Y_0jj+EvQ`6x;t> KMNe~J_5T-PPY%cc literal 0 HcmV?d00001 diff --git a/config.def.h b/config.def.h new file mode 100644 index 0000000..3693afa --- /dev/null +++ b/config.def.h @@ -0,0 +1,73 @@ +/* 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_state battery charging state battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * battery_remaining battery remaining HH:MM battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * cpu_perc cpu usage in percent NULL + * cpu_freq cpu frequency in MHz 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) + * separator string to echo NULL + * 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 + * wifi_perc WiFi signal in percent interface name (wlan0) + * wifi_essid WiFi ESSID interface name (wlan0) + */ +static const struct arg args[] = { + /* function format argument */ + { cpu_perc, "[CPU %5s%%] ", NULL }, + { ram_used, "[RAM %4s] ", NULL }, + { username, "%3s@", NULL }, + { hostname, "%2s ", NULL }, + { datetime, "%s", "%A %B %d %Y %r" }, +}; diff --git a/config.h b/config.h new file mode 100644 index 0000000..3693afa --- /dev/null +++ b/config.h @@ -0,0 +1,73 @@ +/* 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_state battery charging state battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * battery_remaining battery remaining HH:MM battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * cpu_perc cpu usage in percent NULL + * cpu_freq cpu frequency in MHz 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) + * separator string to echo NULL + * 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 + * wifi_perc WiFi signal in percent interface name (wlan0) + * wifi_essid WiFi ESSID interface name (wlan0) + */ +static const struct arg args[] = { + /* function format argument */ + { cpu_perc, "[CPU %5s%%] ", NULL }, + { ram_used, "[RAM %4s] ", NULL }, + { username, "%3s@", NULL }, + { hostname, "%2s ", NULL }, + { datetime, "%s", "%A %B %d %Y %r" }, +}; diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..2516e6e --- /dev/null +++ b/config.mk @@ -0,0 +1,22 @@ +# slstatus version +VERSION = 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 +CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os +LDFLAGS = -L$(X11LIB) -s +# OpenBSD: add -lsndio +# FreeBSD: add -lkvm +LDLIBS = -lX11 + +# compiler and linker +CC = cc diff --git a/slstatus b/slstatus new file mode 100755 index 0000000000000000000000000000000000000000..3d30027e483e900aed88c8528dfaa17ed8cf3f7e GIT binary patch literal 31824 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 +#include +#include +#include +#include +#include +#include + +#include "arg.h" +#include "slstatus.h" +#include "util.h" + +struct arg { + const char *(*func)(); + 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 [-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 '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) { + if (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; +} diff --git a/slstatus.h b/slstatus.h new file mode 100644 index 0000000..b0f2564 --- /dev/null +++ b/slstatus.h @@ -0,0 +1,84 @@ +/* See LICENSE file for copyright and license details. */ + +/* battery */ +const char *battery_perc(const char *); +const char *battery_state(const char *); +const char *battery_remaining(const char *); + +/* cpu */ +const char *cpu_freq(void); +const char *cpu_perc(void); + +/* 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(void); + +/* hostname */ +const char *hostname(void); + +/* ip */ +const char *ipv4(const char *interface); +const char *ipv6(const char *interface); + +/* kernel_release */ +const char *kernel_release(void); + +/* keyboard_indicators */ +const char *keyboard_indicators(void); + +/* keymap */ +const char *keymap(void); + +/* load_avg */ +const char *load_avg(void); + +/* 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(void); +const char *ram_perc(void); +const char *ram_total(void); +const char *ram_used(void); + +/* run_command */ +const char *run_command(const char *cmd); + +/* separator */ +const char *separator(const char *separator); + +/* swap */ +const char *swap_free(void); +const char *swap_perc(void); +const char *swap_total(void); +const char *swap_used(void); + +/* temperature */ +const char *temp(const char *); + +/* uptime */ +const char *uptime(void); + +/* user */ +const char *gid(void); +const char *username(void); +const char *uid(void); + +/* volume */ +const char *vol_perc(const char *card); + +/* wifi */ +const char *wifi_perc(const char *interface); +const char *wifi_essid(const char *interface); diff --git a/slstatus.o b/slstatus.o new file mode 100644 index 0000000000000000000000000000000000000000..88fd6daa98da19eae83fe77f76399fa1499921ee GIT binary patch literal 6184 zcmc&&Z){sv6~B)2Z(XsojrbMJfi+D{L~hnqYero_V@Ve2i0G8VdXUGEoaKl>!RlPxv2 zSX+MEf(V+uCb~#bGLy4EBipUh3I9$+;!HikRCKvj&;bbPOr!_0DiBT(G)DI;A(V|&kB&|%|&}M`SW+aWgnbq|I5C^h( zQ{N;8xHa{)Ad>?}#uG*yLl;N44M{7$plnWcIV*ZWA<<1*2LprUlbl@Te9n zvgqT{uSLhBW8=K?&(X@i`N0XK06@I*Ctk}2dLk?Tc!^j3#%p5q=bA*2tKaH~ z)Z?|YqO&p1e#6=^t>f)qsU6q{spXaP+&{P+@47DMTCUIg`17y~ogqB1o9q+n) zjr$+C44o&u{>SUU_yj~?k(F!yqvx;rCoVwuu1m_0m*4cic!76a;FU}K#uZ)}3utKn zd+2!DwqLh`qz(o`yu30Wf??E71T--hm}#d_mU^2l$Lg)k^VIf_8x7nQF_{L~O76*{ zsoE@&_DhzAEQq(xY7z1I$=C5^jMOKmqF;|rMZXbE-10@jT>SsVcreM{_o{Jx_+`}e zx891fg98J7TIk@R@h&YA2}i;`Hm4aX4IW%<=wwaIQ%4Nn8x)Uh-)1-A+iZ*HsmGXS zzQc3(*0%ODK<)tev$79$6b_FJ!+wTiiupRe-xTw8e$N~8X|?8g)M#>!7c9 zscpn}W}CO>_4N+;dZNA%P=E?1F(0JfO>mse?C*`u`n_wj*x2g@3#V)a0Or01t2ulM z5D)O%r3tn4ima`ftSMgBx~41TZcxyV3azGeufXv`XN&T`6Ph0U@<^Fi3e;YL6BzJy zKMJ?=FJ5H@iCTQ~Vf<=6RcD`2TG)OC$XaY9;NzN785E5cc8G$YkBIi|4wOmW?YGQe zR4`ju)?qOr@h2Vl6tuUIJd6DW*fcz9?WoC|3;t~v{5vlAX&3y5F8EJe@SnTjzjVQ0 zb-`bE!Ixd|%P#mkF8F&c_`h86R{1S}?hSI63$D4~T`u@;7yOGZ_#ohSzg4`Hzf zi@jJpj71L?`>^Q6Vn53zGX|PH(Zdo4c;fKz@aWK3Vk{bq4<%SSqcbxzn@r*L zbHjahnsmQd1=DZErO7?)mr zBAI2=r5Uve+N6TFK5;zBe2c3WV2IxZ&qobgVxXfSj@Jx@e-l9vC%KN9?N z1b>_O!823&xk~sN!QXS?e?a)3C;S_PkLQQ-|1sgyd9`8UL7e#yN*vesK6sR$9>Twa z;QI)l`hSG*acR~14iNtR#LtL>-z?v+V}wuF@i^hrbu1D-9nW)wzm3HG1;O#ByqfPa z!71M__bCo9K=_>m4-z~eadd}w73F^?;nQ(O2p?6Iham^9@;OcX+(-OpT=)jz?;!jI z!rxBtMZ%}!e4gN6Abe1T;I<1%9V>McL>zCIFCqxiX;*MpWUNc-SZPvM{Fh|gz7OKv zlCcLQhE=cB6(8>*DC)k4_)dY?#Sy71zWSaXBls?pcDAYM%CezX~D^!%I9*r0nUxQrHA21RJS-hWqZ~rg$qUa3#w=>NSFFt zVg}ApT~6hHsx+`xxucHyWdpxuRFF#r&lG$Y`zZ)|2Ob6>YJcH33vJatR5-o^h|BE^ znk{O7sJ5z|@o|r!PpADcX|Pp($7GXfN|AL0YV^6=fgh9Y6$h^3t9l6fQO9?R3f?nO z)b9$rWpkB|bw50tAyVi&22D2Kg5^5jZrQPvj&%+mw8w8el|^aq+xbvGvRCilX0d_Bj>ru?C*L1*hyP_b?eTw|TlOAcugJd=zUoMr Uqbc_FX7&X+{+GcQ6{r1w0C&mvRsaA1 literal 0 HcmV?d00001 diff --git a/util.c b/util.c new file mode 100644 index 0000000..85366bf --- /dev/null +++ b/util.c @@ -0,0 +1,146 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include + +#include "util.h" + +char *argv0; + +static void +verr(const char *fmt, va_list ap) +{ + if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) { + fprintf(stderr, "%s: ", argv0); + } + + 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; +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..7f1f26c --- /dev/null +++ b/util.h @@ -0,0 +1,16 @@ +/* See LICENSE file for copyright and license details. */ +#include + +extern char buf[1024]; + +#define LEN(x) (sizeof (x) / sizeof *(x)) + +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, ...); diff --git a/util.o b/util.o new file mode 100644 index 0000000000000000000000000000000000000000..49112be5fa60387b0f68fe7fdeb2368126837c24 GIT binary patch literal 5976 zcmdUzeQevs8OP6gp=l|$+rbF1mmlDaq+PwZ4BBQd#Cd71;Iv_gZHSgN+GwOp_{YgTfyyUCUtUkV;oAd%pL( zvoBYBe@tT99_ijb_uSocchBAZ?5}r5HdlE(Oo@kmo|Q_9GIr!crF^T%wlW{{vT$#> zXN&Xq9o+c`pFHo6OszxZ)wa8IIX-;{z&xTu1-qV4eGb`(^A}kYDu_DCx$|1Y zc~g+_&oDkE8r!#X=XLJbfjX&5x$*tgi!J#ZPgvBMODE_2p~YR{2g1A0Vgyd*6DugA zp^5XSQA0g7a;GQI%$-PJW5nqQv_>e$4;JhVzNU^qx34J@=<_x81Twy+?*zuFjj!pM zz+sU-7kFBv&j*f)^rwLWr2~AbrlFBCoO-Jd75MbQz!_0|>&2Qtovf(i(;Wc|D*hKc z0yWKq=YR6g#YH|vjRyEyw+p-0ozTP_tUby9H>_3$3+v}=$?6mE6JaXt{sl7gl$hoR zzoc)Fm%t2nIca_CY2c;y5g^wSu6C#}=Hu~GeADk9S|yS6xyhGk<$J`+Un@4RwDOqB zu9G{qIG2j^`foVRM`3rwd6heFlsxG5pR*d8pXo*wC+z%!ro5Uvrzb8gRx@_MzjW5* zod0&xG~pSt!dc+XMRMzv(ybp293dL|6`$UZg%=0&N2>{4cowL8DVn%6Pea>lCoaKu zdks#6*bUdUrw)qVN-n?eT$WGMu|8Leq?^+WmMw7Kn!>s3xHCI>#>0PmmM@HE}d_L>FXgR^|Gz$Y&*&%e#59#>tvdz!z2Pks8Aa`a;!J~4;coxPbH zSlB|Ax#(oLcZ>5LZnMk1#ZCW!FA1@V5$DhDsyHvuyz|#boVSWQ7M}c#Yv#GTxbqHo z-i$bZB~S3v6yPB5QmXrbcEQLl-w8W&ZnnZ515fX8&g{m;d6M$~r;^Xb_9R$CuEk=b zxpXF*O54d6Eo*Jh+nKy=+1Y$L9ka6*SZPweC1x|8S{H?TDh$5 zFe!hQ_(x>jb4c5~{^_bVZ~ddy9bRj)rpw!0bzp_pYWLPtO`Er_^J?OoRf*xMd_cDU zA<{1I8Bf(wZyjYZ<`@{scM+kE5{trN3Xs!?!e0Mm)!k_LvezFLZ7ssjqmJY~L?xYh zr31S~drIGjPM7zXr|Pv8FmfC9f|a@mPEw75#oRjO+`d6`d)HGn@3lILvk|IgBQ&pJ ze_Je9SzTQ9rM18dMwx(%(}kH|`%Q@beWo%iF1;V4RI6vRM|4 zw1+k!Uf(R@kciid_zn@@DdG(x-pFFvJ)_Mm+7;Q}7LG)>Z{ED4vnSdUZi{qAS%&X%>y<>{xtnG(NaDnvA7}*gz`55@RWw zCDesqy6;)P?5;nbEZy`hlZ(gF1aMzdhpF61eAA}rXj0<%&R+{BxXPNxmf7qj#2u3 zlAHP?nm+D(rH}Ig!MN8^Q2ajW|KRl+_n>1E@Ea*8{cma<_r2mzN{$3~isC=eINmxk?7-oU(?6iq4a;I>Ff5~RZB`F7Ff4+p&I1?W~&)s$4cP6bsskF`ETNb|7ZQ zSg=2rqw)v}XhWa=EEpdd9!{i5FFj%>g7n?LPP}2VyeFLxX0r4aW$k^ktHfY5nT-u6 zq*ecUVo_80tobF{N(}OfJeO|C)m3?b%thlHhw3 zT&e*Hv7|vW3Mg)rKSAYk;}`I_k{m1NFK{{qnK|F!@C literal 0 HcmV?d00001