[
  {
    "path": "LICENSE",
    "content": "ISC License\n\nCopyright 2016-2026 Aaron Marcher <me@drkhsh.at>\n\nCopyright 2016 Roy Freytag <rfreytag@hs-mittweida.de>\nCopyright 2016 Vincent Loupmon <vincentloupmon@gmail.com>\nCopyright 2016 Daniel Walter <d.walter@0x90.at>\nCopyright 2016-2018 Ali H. Fardan <raiz@firemail.cc>\nCopyright 2016 Jody Leonard <me@jodyleonard.com>\nCopyright 2016-2018 Quentin Rameau <quinq@fifth.space>\nCopyright 2016 Mike Coddington <mike@coddington.us>\nCopyright 2016-2018 Ivan J. <parazyd@dyne.org>\nCopyright 2017 Tobias Stoeckmann <tobias@stoeckmann.org>\nCopyright 2017-2018 Laslo Hunhold <dev@frign.de>\nCopyright 2018 Darron Anderson <darronanderson@protonmail.com>\nCopyright 2018 Josuah Demangeon <mail@josuah.net>\nCopyright 2018 Tobias Tschinkowitz <tobias@he4d.net>\nCopyright 2018 David Demelier <markand@malikania.fr>\nCopyright 2018-2012 Michael Buch <michaelbuch12@gmail.com>\nCopyright 2018 Ian Remmler <ian@remmler.org>\nCopyright 2016-2019 Joerg Jung <jung@openbsd.org>\nCopyright 2019 Ryan Kes <alrayyes@gmail.com>\nCopyright 2019 Cem Keylan <cem@ckyln.com>\nCopyright 2019 Spiros Thanasoulas <dsp@2f30.org>\nCopyright 2019-2022 Ingo Feinerer <feinerer@logic.at>\nCopyright 2020 Alexandre Ratchov <alex@caoua.org>\nCopyright 2020 Mart Lubbers <mart@martlubbers.net>\nCopyright 2020 Daniel Moch <daniel@danielmoch.com>\nCopyright 2022 Nickolas Raymond Kaczynski <nrk@disroot.org>\nCopyright 2022 Patrick Iacob <iacobp@oregonstate.edu>\nCopyright 2021-2022 Steven Ward <planet36@gmail.com>\nCopyright 2025 Joakim Sindholt <opensource@zhasha.com>\nCopyright 2025 Al <eirann@disroot.org>\nCopyright 2025 sewn <sewn@disroot.org>\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "# See LICENSE file for copyright and license details\n# slstatus - suckless status monitor\n.POSIX:\n\ninclude config.mk\n\nREQ = util\nCOM =\\\n\tcomponents/battery\\\n\tcomponents/cat\\\n\tcomponents/cpu\\\n\tcomponents/datetime\\\n\tcomponents/disk\\\n\tcomponents/entropy\\\n\tcomponents/hostname\\\n\tcomponents/ip\\\n\tcomponents/kernel_release\\\n\tcomponents/keyboard_indicators\\\n\tcomponents/keymap\\\n\tcomponents/load_avg\\\n\tcomponents/netspeeds\\\n\tcomponents/num_files\\\n\tcomponents/ram\\\n\tcomponents/run_command\\\n\tcomponents/swap\\\n\tcomponents/temperature\\\n\tcomponents/uptime\\\n\tcomponents/user\\\n\tcomponents/volume\\\n\tcomponents/wifi\n\nall: slstatus\n\n$(COM:=.o): config.mk $(REQ:=.h) slstatus.h\nslstatus.o: slstatus.c slstatus.h arg.h config.h config.mk $(REQ:=.h)\n\n.c.o:\n\t$(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $<\n\nconfig.h:\n\tcp config.def.h $@\n\nslstatus: slstatus.o $(COM:=.o) $(REQ:=.o)\n\t$(CC) -o $@ $(LDFLAGS) $(COM:=.o) $(REQ:=.o) slstatus.o $(LDLIBS)\n\nclean:\n\trm -f slstatus slstatus.o $(COM:=.o) $(REQ:=.o) slstatus-${VERSION}.tar.gz\n\ndist:\n\trm -rf \"slstatus-$(VERSION)\"\n\tmkdir -p \"slstatus-$(VERSION)/components\"\n\tcp -R LICENSE Makefile README config.mk config.def.h \\\n\t      arg.h slstatus.h slstatus.c $(REQ:=.c) $(REQ:=.h) \\\n\t      slstatus.1 \"slstatus-$(VERSION)\"\n\tcp -R $(COM:=.c) \"slstatus-$(VERSION)/components\"\n\ttar -cf - \"slstatus-$(VERSION)\" | gzip -c > \"slstatus-$(VERSION).tar.gz\"\n\trm -rf \"slstatus-$(VERSION)\"\n\ninstall: all\n\tmkdir -p \"$(DESTDIR)$(PREFIX)/bin\"\n\tcp -f slstatus \"$(DESTDIR)$(PREFIX)/bin\"\n\tchmod 755 \"$(DESTDIR)$(PREFIX)/bin/slstatus\"\n\tmkdir -p \"$(DESTDIR)$(MANPREFIX)/man1\"\n\tcp -f slstatus.1 \"$(DESTDIR)$(MANPREFIX)/man1\"\n\tchmod 644 \"$(DESTDIR)$(MANPREFIX)/man1/slstatus.1\"\n\nuninstall:\n\trm -f \"$(DESTDIR)$(PREFIX)/bin/slstatus\"\n\trm -f \"$(DESTDIR)$(MANPREFIX)/man1/slstatus.1\"\n"
  },
  {
    "path": "README",
    "content": "slstatus - suckless status\n==========================\nslstatus is a small tool for providing system status information to other\nprograms over the EWMH property of the root window (used by dwm(1)) or\nstandard input/output. It is designed to be as efficient as possible by\nonly issuing the minimum of system calls required.\n\n\nFeatures\n--------\n- Battery percentage/state/time left\n- Cat (read file)\n- CPU usage\n- CPU frequency\n- Custom shell commands\n- Date and time\n- Disk status (free storage, percentage, total storage and used storage)\n- Available entropy\n- Username/GID/UID\n- Hostname\n- IP address (IPv4 and IPv6), interface status\n- Kernel version\n- Keyboard indicators\n- Keymap\n- Load average\n- Network speeds (RX and TX)\n- Number of files in a directory (hint: Maildir)\n- Memory status (free memory, percentage, total memory and used memory)\n- Swap status (free swap, percentage, total swap and used swap)\n- Temperature\n- Uptime\n- Volume percentage\n- WiFi signal percentage and ESSID\n\n\nRequirements\n------------\nCurrently slstatus works on FreeBSD, Linux and OpenBSD.\nIn order to build slstatus you need the Xlib header files.\n\n- For volume percentage on Linux the kernel module `snd-mixer-oss` must be\n  loaded.\n- For volume percentage on FreeBSD, `sndio` must be installed.\n\n\nInstallation\n------------\nEdit config.mk to match your local setup (slstatus is installed into the\n/usr/local namespace by default).\n\nAfterwards enter the following command to build and install slstatus (if\nnecessary as root):\n\n    make clean install\n\n\nRunning slstatus\n----------------\nSee the man page for details.\n\n\nConfiguration\n-------------\nslstatus can be customized by creating a custom config.h and (re)compiling the\nsource code. This keeps it fast, secure and simple.\n"
  },
  {
    "path": "arg.h",
    "content": "/* See LICENSE file for copyright and license details. */\n#ifndef ARG_H\n#define ARG_H\n\nextern char *argv0;\n\n/* int main(int argc, char *argv[]) */\n#define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0);      \\\n                      *argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \\\n                 \tint i_, argused_;                                         \\\n                 \tif ((*argv)[1] == '-' && !(*argv)[2]) {                   \\\n                 \t\targc--, argv++;                                   \\\n                 \t\tbreak;                                            \\\n                 \t}                                                         \\\n                 \tfor (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) {           \\\n\t\t\t\tswitch ((*argv)[i_])\n#define ARGEND   \t\tif (argused_) {                                   \\\n                 \t\t\tif ((*argv)[i_ + 1]) {                    \\\n                 \t\t\t\tbreak;                            \\\n                 \t\t\t} else {                                  \\\n                 \t\t\t\targc--, argv++;                   \\\n                 \t\t\t\tbreak;                            \\\n                 \t\t\t}                                         \\\n                 \t\t}                                                 \\\n                 \t}                                                         \\\n                 }\n#define ARGC()    ((*argv)[i_])\n#define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) :        \\\n                  (*(argv + 1))     ? (argused_ = 1, *(argv + 1))        : (x))\n#define EARGF(x) ARGF_(((x), exit(1), (char *)0))\n#define ARGF()   ARGF_((char *)0)\n\n#endif\n"
  },
  {
    "path": "components/battery.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <string.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#if defined(__linux__)\n/*\n * https://www.kernel.org/doc/html/latest/power/power_supply_class.html\n */\n\t#include <limits.h>\n\t#include <stdint.h>\n\t#include <unistd.h>\n\n\t#define POWER_SUPPLY_CAPACITY \"/sys/class/power_supply/%s/capacity\"\n\t#define POWER_SUPPLY_STATUS   \"/sys/class/power_supply/%s/status\"\n\t#define POWER_SUPPLY_CHARGE   \"/sys/class/power_supply/%s/charge_now\"\n\t#define POWER_SUPPLY_ENERGY   \"/sys/class/power_supply/%s/energy_now\"\n\t#define POWER_SUPPLY_CURRENT  \"/sys/class/power_supply/%s/current_now\"\n\t#define POWER_SUPPLY_POWER    \"/sys/class/power_supply/%s/power_now\"\n\n\tstatic const char *\n\tpick(const char *bat, const char *f1, const char *f2, char *path,\n\t     size_t length)\n\t{\n\t\tif (esnprintf(path, length, f1, bat) > 0 &&\n\t\t    access(path, R_OK) == 0)\n\t\t\treturn f1;\n\n\t\tif (esnprintf(path, length, f2, bat) > 0 &&\n\t\t    access(path, R_OK) == 0)\n\t\t\treturn f2;\n\n\t\treturn NULL;\n\t}\n\n\tconst char *\n\tbattery_perc(const char *bat)\n\t{\n\t\tint cap_perc;\n\t\tchar path[PATH_MAX];\n\n\t\tif (esnprintf(path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0)\n\t\t\treturn NULL;\n\t\tif (pscanf(path, \"%d\", &cap_perc) != 1)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", cap_perc);\n\t}\n\n\tconst char *\n\tbattery_state(const char *bat)\n\t{\n\t\tstatic struct {\n\t\t\tchar *state;\n\t\t\tchar *symbol;\n\t\t} map[] = {\n\t\t\t{ \"Charging\",    \"+\" },\n\t\t\t{ \"Discharging\", \"-\" },\n\t\t\t{ \"Full\",        \"o\" },\n\t\t\t{ \"Not charging\", \"o\" },\n\t\t};\n\t\tsize_t i;\n\t\tchar path[PATH_MAX], state[13];\n\n\t\tif (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0)\n\t\t\treturn NULL;\n\t\tif (pscanf(path, \"%12[a-zA-Z ]\", state) != 1)\n\t\t\treturn NULL;\n\n\t\tfor (i = 0; i < LEN(map); i++)\n\t\t\tif (!strcmp(map[i].state, state))\n\t\t\t\tbreak;\n\n\t\treturn (i == LEN(map)) ? \"?\" : map[i].symbol;\n\t}\n\n\tconst char *\n\tbattery_remaining(const char *bat)\n\t{\n\t\tuintmax_t charge_now, current_now, m, h;\n\t\tdouble timeleft;\n\t\tchar path[PATH_MAX], state[13];\n\n\t\tif (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0)\n\t\t\treturn NULL;\n\t\tif (pscanf(path, \"%12[a-zA-Z ]\", state) != 1)\n\t\t\treturn NULL;\n\n\t\tif (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path,\n\t\t          sizeof(path)) ||\n\t\t    pscanf(path, \"%ju\", &charge_now) < 0)\n\t\t\treturn NULL;\n\n\t\tif (!strcmp(state, \"Discharging\")) {\n\t\t\tif (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path,\n\t\t\t          sizeof(path)) ||\n\t\t\t    pscanf(path, \"%ju\", &current_now) < 0)\n\t\t\t\treturn NULL;\n\n\t\t\tif (current_now == 0)\n\t\t\t\treturn NULL;\n\n\t\t\ttimeleft = (double)charge_now / (double)current_now;\n\t\t\th = timeleft;\n\t\t\tm = (timeleft - (double)h) * 60;\n\n\t\t\treturn bprintf(\"%juh %jum\", h, m);\n\t\t}\n\n\t\treturn \"\";\n\t}\n#elif defined(__OpenBSD__)\n\t#include <fcntl.h>\n\t#include <machine/apmvar.h>\n\t#include <sys/ioctl.h>\n\t#include <unistd.h>\n\n\tstatic int\n\tload_apm_power_info(struct apm_power_info *apm_info)\n\t{\n\t\tint fd;\n\n\t\tfd = open(\"/dev/apm\", O_RDONLY);\n\t\tif (fd < 0) {\n\t\t\twarn(\"open '/dev/apm':\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tmemset(apm_info, 0, sizeof(struct apm_power_info));\n\t\tif (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) {\n\t\t\twarn(\"ioctl 'APM_IOC_GETPOWER':\");\n\t\t\tclose(fd);\n\t\t\treturn 0;\n\t\t}\n\t\treturn close(fd), 1;\n\t}\n\n\tconst char *\n\tbattery_perc(const char *unused)\n\t{\n\t\tstruct apm_power_info apm_info;\n\n\t\tif (load_apm_power_info(&apm_info))\n\t\t\treturn bprintf(\"%d\", apm_info.battery_life);\n\n\t\treturn NULL;\n\t}\n\n\tconst char *\n\tbattery_state(const char *unused)\n\t{\n\t\tstruct {\n\t\t\tunsigned int state;\n\t\t\tchar *symbol;\n\t\t} map[] = {\n\t\t\t{ APM_AC_ON,      \"+\" },\n\t\t\t{ APM_AC_OFF,     \"-\" },\n\t\t};\n\t\tstruct apm_power_info apm_info;\n\t\tsize_t i;\n\n\t\tif (load_apm_power_info(&apm_info)) {\n\t\t\tfor (i = 0; i < LEN(map); i++)\n\t\t\t\tif (map[i].state == apm_info.ac_state)\n\t\t\t\t\tbreak;\n\n\t\t\treturn (i == LEN(map)) ? \"?\" : map[i].symbol;\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\tconst char *\n\tbattery_remaining(const char *unused)\n\t{\n\t\tstruct apm_power_info apm_info;\n\t\tunsigned int h, m;\n\n\t\tif (load_apm_power_info(&apm_info)) {\n\t\t\tif (apm_info.ac_state != APM_AC_ON) {\n\t\t\t\th = apm_info.minutes_left / 60;\n\t\t\t\tm = apm_info.minutes_left % 60;\n\t\t\t\treturn bprintf(\"%uh %02um\", h, m);\n\t\t\t} else {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn NULL;\n\t}\n#elif defined(__FreeBSD__)\n\t#include <sys/sysctl.h>\n\n\t#define BATTERY_LIFE  \"hw.acpi.battery.life\"\n\t#define BATTERY_STATE \"hw.acpi.battery.state\"\n\t#define BATTERY_TIME  \"hw.acpi.battery.time\"\n\n\tconst char *\n\tbattery_perc(const char *unused)\n\t{\n\t\tint cap_perc;\n\t\tsize_t len;\n\n\t\tlen = sizeof(cap_perc);\n\t\tif (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", cap_perc);\n\t}\n\n\tconst char *\n\tbattery_state(const char *unused)\n\t{\n\t\tint state;\n\t\tsize_t len;\n\n\t\tlen = sizeof(state);\n\t\tif (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len)\n\t\t\treturn NULL;\n\n\t\tswitch (state) {\n\t\tcase 0: /* FALLTHROUGH */\n\t\tcase 2:\n\t\t\treturn \"+\";\n\t\tcase 1:\n\t\t\treturn \"-\";\n\t\tdefault:\n\t\t\treturn \"?\";\n\t\t}\n\t}\n\n\tconst char *\n\tbattery_remaining(const char *unused)\n\t{\n\t\tint rem;\n\t\tsize_t len;\n\n\t\tlen = sizeof(rem);\n\t\tif (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len\n\t\t    || rem < 0)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%uh %02um\", rem / 60, rem % 60);\n\t}\n#endif\n"
  },
  {
    "path": "components/cat.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <string.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\ncat(const char *path)\n{\n        char *f;\n        FILE *fp;\n\n        if (!(fp = fopen(path, \"r\"))) {\n                warn(\"fopen '%s':\", path);\n                return NULL;\n        }\n\n        f = fgets(buf, sizeof(buf) - 1, fp);\n        if (fclose(fp) < 0) {\n                warn(\"fclose '%s':\", path);\n                return NULL;\n        }\n        if (!f)\n                return NULL;\n\n        if ((f = strrchr(buf, '\\n')))\n                f[0] = '\\0';\n\n        return buf[0] ? buf : NULL;\n}\n\n"
  },
  {
    "path": "components/cpu.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#if defined(__linux__)\n\t#define CPU_FREQ \"/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq\"\n\n\tconst char *\n\tcpu_freq(const char *unused)\n\t{\n\t\tuintmax_t freq;\n\n\t\t/* in kHz */\n\t\tif (pscanf(CPU_FREQ, \"%ju\", &freq) != 1)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(freq * 1000, 1000);\n\t}\n\n\tconst char *\n\tcpu_perc(const char *unused)\n\t{\n\t\tstatic long double a[7];\n\t\tlong double b[7], sum;\n\n\t\tmemcpy(b, a, sizeof(b));\n\t\t/* cpu user nice system idle iowait irq softirq */\n\t\tif (pscanf(\"/proc/stat\", \"%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf\",\n\t\t           &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6])\n\t\t    != 7)\n\t\t\treturn NULL;\n\n\t\tif (b[0] == 0)\n\t\t\treturn NULL;\n\n\t\tsum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) -\n\t\t      (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]);\n\n\t\tif (sum == 0)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", (int)(100 *\n\t\t               ((b[0] + b[1] + b[2] + b[5] + b[6]) -\n\t\t                (a[0] + a[1] + a[2] + a[5] + a[6])) / sum));\n\t}\n#elif defined(__OpenBSD__)\n\t#include <sys/param.h>\n\t#include <sys/sched.h>\n\t#include <sys/sysctl.h>\n\n\tconst char *\n\tcpu_freq(const char *unused)\n\t{\n\t\tint freq, mib[2];\n\t\tsize_t size;\n\n\t\tmib[0] = CTL_HW;\n\t\tmib[1] = HW_CPUSPEED;\n\n\t\tsize = sizeof(freq);\n\n\t\t/* in MHz */\n\t\tif (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) {\n\t\t\twarn(\"sysctl 'HW_CPUSPEED':\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\treturn fmt_human(freq * 1E6, 1000);\n\t}\n\n\tconst char *\n\tcpu_perc(const char *unused)\n\t{\n\t\tint mib[2];\n\t\tstatic uintmax_t a[CPUSTATES];\n\t\tuintmax_t b[CPUSTATES], sum;\n\t\tsize_t size;\n\n\t\tmib[0] = CTL_KERN;\n\t\tmib[1] = KERN_CPTIME;\n\n\t\tsize = sizeof(a);\n\n\t\tmemcpy(b, a, sizeof(b));\n\t\tif (sysctl(mib, 2, &a, &size, NULL, 0) < 0) {\n\t\t\twarn(\"sysctl 'KERN_CPTIME':\");\n\t\t\treturn NULL;\n\t\t}\n\t\tif (b[0] == 0)\n\t\t\treturn NULL;\n\n\t\tsum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) -\n\t\t      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]);\n\n\t\tif (sum == 0)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", 100 *\n\t\t               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] +\n\t\t                 a[CP_INTR]) -\n\t\t                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] +\n\t\t                 b[CP_INTR])) / sum);\n\t}\n#elif defined(__FreeBSD__)\n\t#include <devstat.h>\n\t#include <sys/param.h>\n\t#include <sys/sysctl.h>\n\n\tconst char *\n\tcpu_freq(const char *unused)\n\t{\n\t\tint freq;\n\t\tsize_t size;\n\n\t\tsize = sizeof(freq);\n\t\t/* in MHz */\n\t\tif (sysctlbyname(\"hw.clockrate\", &freq, &size, NULL, 0) < 0 || !size) {\n\t\t\twarn(\"sysctlbyname 'hw.clockrate':\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\treturn fmt_human(freq * 1E6, 1000);\n\t}\n\n\tconst char *\n\tcpu_perc(const char *unused)\n\t{\n\t\tsize_t size;\n\t\tstatic long a[CPUSTATES];\n\t\tlong b[CPUSTATES], sum;\n\n\t\tsize = sizeof(a);\n\t\tmemcpy(b, a, sizeof(b));\n\t\tif (sysctlbyname(\"kern.cp_time\", &a, &size, NULL, 0) < 0 || !size) {\n\t\t\twarn(\"sysctlbyname 'kern.cp_time':\");\n\t\t\treturn NULL;\n\t\t}\n\t\tif (b[0] == 0)\n\t\t\treturn NULL;\n\n\t\tsum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) -\n\t\t      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]);\n\n\t\tif (sum == 0)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", 100 *\n\t\t               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] +\n\t\t                 a[CP_INTR]) -\n\t\t                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] +\n\t\t                 b[CP_INTR])) / sum);\n\t}\n#endif\n"
  },
  {
    "path": "components/datetime.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <time.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\ndatetime(const char *fmt)\n{\n\ttime_t t;\n\n\tt = time(NULL);\n\tif (!strftime(buf, sizeof(buf), fmt, localtime(&t))) {\n\t\twarn(\"strftime: Result string exceeds buffer size\");\n\t\treturn NULL;\n\t}\n\n\treturn buf;\n}\n"
  },
  {
    "path": "components/disk.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <sys/statvfs.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\ndisk_free(const char *path)\n{\n\tstruct statvfs fs;\n\n\tif (statvfs(path, &fs) < 0) {\n\t\twarn(\"statvfs '%s':\", path);\n\t\treturn NULL;\n\t}\n\n\treturn fmt_human(fs.f_frsize * fs.f_bavail, 1024);\n}\n\nconst char *\ndisk_perc(const char *path)\n{\n\tstruct statvfs fs;\n\n\tif (statvfs(path, &fs) < 0) {\n\t\twarn(\"statvfs '%s':\", path);\n\t\treturn NULL;\n\t}\n\n\treturn bprintf(\"%d\", (int)(100 *\n\t               (1 - ((double)fs.f_bavail / (double)fs.f_blocks))));\n}\n\nconst char *\ndisk_total(const char *path)\n{\n\tstruct statvfs fs;\n\n\tif (statvfs(path, &fs) < 0) {\n\t\twarn(\"statvfs '%s':\", path);\n\t\treturn NULL;\n\t}\n\n\treturn fmt_human(fs.f_frsize * fs.f_blocks, 1024);\n}\n\nconst char *\ndisk_used(const char *path)\n{\n\tstruct statvfs fs;\n\n\tif (statvfs(path, &fs) < 0) {\n\t\twarn(\"statvfs '%s':\", path);\n\t\treturn NULL;\n\t}\n\n\treturn fmt_human(fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024);\n}\n"
  },
  {
    "path": "components/entropy.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include \"../slstatus.h\"\n#if defined(__linux__)\n\t#include <stdint.h>\n\t#include <stdio.h>\n\n\t#include \"../util.h\"\n\n\t#define ENTROPY_AVAIL \"/proc/sys/kernel/random/entropy_avail\"\n\n\tconst char *\n\tentropy(const char *unused)\n\t{\n\t\tuintmax_t num;\n\n\t\tif (pscanf(ENTROPY_AVAIL, \"%ju\", &num) != 1)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%ju\", num);\n\t}\n#elif defined(__OpenBSD__) | defined(__FreeBSD__)\n\tconst char *\n\tentropy(const char *unused)\n\t{\n\t\t// https://www.unicode.org/charts/PDF/U2200.pdf\n\t\t/* Unicode Character 'INFINITY' (U+221E) */\n\t\treturn \"\\u221E\";\n\t}\n#endif\n"
  },
  {
    "path": "components/hostname.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <unistd.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\nhostname(const char *unused)\n{\n\tif (gethostname(buf, sizeof(buf)) < 0) {\n\t\twarn(\"gethostbyname:\");\n\t\treturn NULL;\n\t}\n\n\treturn buf;\n}\n"
  },
  {
    "path": "components/ip.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <ifaddrs.h>\n#include <netdb.h>\n#include <net/if.h>\n#include <stdio.h>\n#include <string.h>\n#if defined(__OpenBSD__)\n\t#include <sys/socket.h>\n\t#include <sys/types.h>\n#elif defined(__FreeBSD__)\n\t#include <netinet/in.h>\n\t#include <sys/socket.h>\n#endif\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nstatic const char *\nip(const char *interface, unsigned short sa_family)\n{\n\tstruct ifaddrs *ifaddr, *ifa;\n\tint s;\n\tchar host[NI_MAXHOST];\n\n\tif (getifaddrs(&ifaddr) < 0) {\n\t\twarn(\"getifaddrs:\");\n\t\treturn NULL;\n\t}\n\n\tfor (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {\n\t\tif (!ifa->ifa_addr)\n\t\t\tcontinue;\n\n\t\ts = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),\n\t\t                host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);\n\t\tif (!strcmp(ifa->ifa_name, interface) &&\n\t\t    (ifa->ifa_addr->sa_family == sa_family)) {\n\t\t\tfreeifaddrs(ifaddr);\n\t\t\tif (s != 0) {\n\t\t\t\twarn(\"getnameinfo: %s\", gai_strerror(s));\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\treturn bprintf(\"%s\", host);\n\t\t}\n\t}\n\n\tfreeifaddrs(ifaddr);\n\n\treturn NULL;\n}\n\nconst char *\nipv4(const char *interface)\n{\n\treturn ip(interface, AF_INET);\n}\n\nconst char *\nipv6(const char *interface)\n{\n\treturn ip(interface, AF_INET6);\n}\n\nconst char *\nup(const char *interface)\n{\n\tstruct ifaddrs *ifaddr, *ifa;\n\n\tif (getifaddrs(&ifaddr) < 0) {\n\t\twarn(\"getifaddrs:\");\n\t\treturn NULL;\n\t}\n\n\tfor (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {\n\t\tif (!ifa->ifa_addr)\n\t\t\tcontinue;\n\n\t\tif (!strcmp(ifa->ifa_name, interface)) {\n\t\t\tfreeifaddrs(ifaddr);\n\t\t\treturn ifa->ifa_flags & IFF_UP ? \"up\" : \"down\";\n\t\t}\n\t}\n\n\tfreeifaddrs(ifaddr);\n\n\treturn NULL;\n}\n"
  },
  {
    "path": "components/kernel_release.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <sys/utsname.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\nkernel_release(const char *unused)\n{\n\tstruct utsname udata;\n\n\tif (uname(&udata) < 0) {\n\t\twarn(\"uname:\");\n\t\treturn NULL;\n\t}\n\n\treturn bprintf(\"%s\", udata.release);\n}\n"
  },
  {
    "path": "components/keyboard_indicators.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <ctype.h>\n#include <stdio.h>\n#include <string.h>\n#include <X11/Xlib.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n/*\n * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num\n * lock, each optionally followed by '?', in the order of indicators desired.\n * If followed by '?', the letter with case preserved is included in the output\n * if the corresponding indicator is on.  Otherwise, the letter is always\n * included, lowercase when off and uppercase when on.\n */\nconst char *\nkeyboard_indicators(const char *fmt)\n{\n\tDisplay *dpy;\n\tXKeyboardState state;\n\tsize_t fmtlen, i, n;\n\tint togglecase, isset;\n\tchar key;\n\n\tif (!(dpy = XOpenDisplay(NULL))) {\n\t\twarn(\"XOpenDisplay: Failed to open display\");\n\t\treturn NULL;\n\t}\n\tXGetKeyboardControl(dpy, &state);\n\tXCloseDisplay(dpy);\n\n\tfmtlen = strnlen(fmt, 4);\n\tfor (i = n = 0; i < fmtlen; i++) {\n\t\tkey = tolower(fmt[i]);\n\t\tif (key != 'c' && key != 'n')\n\t\t\tcontinue;\n\n\t\ttogglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?');\n\t\tisset = (state.led_mask & (1 << (key == 'n')));\n\n\t\tif (togglecase)\n\t\t\tbuf[n++] = isset ? toupper(key) : key;\n\t\telse if (isset)\n\t\t\tbuf[n++] = fmt[i];\n\t}\n\n\tbuf[n] = 0;\n\treturn buf;\n}\n"
  },
  {
    "path": "components/keymap.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include <X11/XKBlib.h>\n#include <X11/Xlib.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nstatic int\nvalid_layout_or_variant(char *sym)\n{\n\tsize_t i;\n\t/* invalid symbols from xkb rules config */\n\tstatic const char *invalid[] = { \"evdev\", \"inet\", \"pc\", \"base\" };\n\n\tfor (i = 0; i < LEN(invalid); i++)\n\t\tif (!strncmp(sym, invalid[i], strlen(invalid[i])))\n\t\t\treturn 0;\n\n\treturn 1;\n}\n\nstatic char *\nget_layout(char *syms, int grp_num)\n{\n\tchar *tok, *layout;\n\tint grp;\n\n\tlayout = NULL;\n\ttok = strtok(syms, \"+:_\");\n\tfor (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, \"+:_\")) {\n\t\tif (!valid_layout_or_variant(tok)) {\n\t\t\tcontinue;\n\t\t} else if (strlen(tok) == 1 && isdigit(tok[0])) {\n\t\t\t/* ignore :2, :3, :4 (additional layout groups) */\n\t\t\tcontinue;\n\t\t}\n\t\tlayout = tok;\n\t\tgrp++;\n\t}\n\n\treturn layout;\n}\n\nconst char *\nkeymap(const char *unused)\n{\n\tDisplay *dpy;\n\tXkbDescRec *desc;\n\tXkbStateRec state;\n\tchar *symbols;\n\tconst char *layout;\n\n\tlayout = NULL;\n\n\tif (!(dpy = XOpenDisplay(NULL))) {\n\t\twarn(\"XOpenDisplay: Failed to open display\");\n\t\treturn NULL;\n\t}\n\tif (!(desc = XkbAllocKeyboard())) {\n\t\twarn(\"XkbAllocKeyboard: Failed to allocate keyboard\");\n\t\tgoto end;\n\t}\n\tif (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) {\n\t\twarn(\"XkbGetNames: Failed to retrieve key symbols\");\n\t\tgoto end;\n\t}\n\tif (XkbGetState(dpy, XkbUseCoreKbd, &state)) {\n\t\twarn(\"XkbGetState: Failed to retrieve keyboard state\");\n\t\tgoto end;\n\t}\n\tif (!(symbols = XGetAtomName(dpy, desc->names->symbols))) {\n\t\twarn(\"XGetAtomName: Failed to get atom name\");\n\t\tgoto end;\n\t}\n\tlayout = bprintf(\"%s\", get_layout(symbols, state.group));\n\tXFree(symbols);\nend:\n\tXkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);\n\tif (XCloseDisplay(dpy))\n\t\twarn(\"XCloseDisplay: Failed to close display\");\n\n\treturn layout;\n}\n"
  },
  {
    "path": "components/load_avg.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\nload_avg(const char *unused)\n{\n\tdouble avgs[3];\n\n\tif (getloadavg(avgs, 3) < 0) {\n\t\twarn(\"getloadavg: Failed to obtain load average\");\n\t\treturn NULL;\n\t}\n\n\treturn bprintf(\"%.2f %.2f %.2f\", avgs[0], avgs[1], avgs[2]);\n}\n"
  },
  {
    "path": "components/netspeeds.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <limits.h>\n#include <stdio.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#if defined(__linux__)\n\t#include <stdint.h>\n\n\t#define NET_RX_BYTES \"/sys/class/net/%s/statistics/rx_bytes\"\n\t#define NET_TX_BYTES \"/sys/class/net/%s/statistics/tx_bytes\"\n\n\tconst char *\n\tnetspeed_rx(const char *interface)\n\t{\n\t\tuintmax_t oldrxbytes;\n\t\tstatic uintmax_t rxbytes;\n\t\textern const unsigned int interval;\n\t\tchar path[PATH_MAX];\n\n\t\toldrxbytes = rxbytes;\n\n\t\tif (esnprintf(path, sizeof(path), NET_RX_BYTES, interface) < 0)\n\t\t\treturn NULL;\n\t\tif (pscanf(path, \"%ju\", &rxbytes) != 1)\n\t\t\treturn NULL;\n\t\tif (oldrxbytes == 0)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human((rxbytes - oldrxbytes) * 1000 / interval,\n\t\t                 1024);\n\t}\n\n\tconst char *\n\tnetspeed_tx(const char *interface)\n\t{\n\t\tuintmax_t oldtxbytes;\n\t\tstatic uintmax_t txbytes;\n\t\textern const unsigned int interval;\n\t\tchar path[PATH_MAX];\n\n\t\toldtxbytes = txbytes;\n\n\t\tif (esnprintf(path, sizeof(path), NET_TX_BYTES, interface) < 0)\n\t\t\treturn NULL;\n\t\tif (pscanf(path, \"%ju\", &txbytes) != 1)\n\t\t\treturn NULL;\n\t\tif (oldtxbytes == 0)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human((txbytes - oldtxbytes) * 1000 / interval,\n\t\t                 1024);\n\t}\n#elif defined(__OpenBSD__) | defined(__FreeBSD__)\n\t#include <ifaddrs.h>\n\t#include <net/if.h>\n\t#include <string.h>\n\t#include <sys/types.h>\n\t#include <sys/socket.h>\n\n\tconst char *\n\tnetspeed_rx(const char *interface)\n\t{\n\t\tstruct ifaddrs *ifal, *ifa;\n\t\tstruct if_data *ifd;\n\t\tuintmax_t oldrxbytes;\n\t\tstatic uintmax_t rxbytes;\n\t\textern const unsigned int interval;\n\t\tint if_ok = 0;\n\n\t\toldrxbytes = rxbytes;\n\n\t\tif (getifaddrs(&ifal) < 0) {\n\t\t\twarn(\"getifaddrs failed\");\n\t\t\treturn NULL;\n\t\t}\n\t\trxbytes = 0;\n\t\tfor (ifa = ifal; ifa; ifa = ifa->ifa_next)\n\t\t\tif (!strcmp(ifa->ifa_name, interface) &&\n\t\t\t   (ifd = (struct if_data *)ifa->ifa_data))\n\t\t\t\trxbytes += ifd->ifi_ibytes, if_ok = 1;\n\n\t\tfreeifaddrs(ifal);\n\t\tif (!if_ok) {\n\t\t\twarn(\"reading 'if_data' failed\");\n\t\t\treturn NULL;\n\t\t}\n\t\tif (oldrxbytes == 0)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human((rxbytes - oldrxbytes) * 1000 / interval,\n\t\t                 1024);\n\t}\n\n\tconst char *\n\tnetspeed_tx(const char *interface)\n\t{\n\t\tstruct ifaddrs *ifal, *ifa;\n\t\tstruct if_data *ifd;\n\t\tuintmax_t oldtxbytes;\n\t\tstatic uintmax_t txbytes;\n\t\textern const unsigned int interval;\n\t\tint if_ok = 0;\n\n\t\toldtxbytes = txbytes;\n\n\t\tif (getifaddrs(&ifal) < 0) {\n\t\t\twarn(\"getifaddrs failed\");\n\t\t\treturn NULL;\n\t\t}\n\t\ttxbytes = 0;\n\t\tfor (ifa = ifal; ifa; ifa = ifa->ifa_next)\n\t\t\tif (!strcmp(ifa->ifa_name, interface) &&\n\t\t\t   (ifd = (struct if_data *)ifa->ifa_data))\n\t\t\t\ttxbytes += ifd->ifi_obytes, if_ok = 1;\n\n\t\tfreeifaddrs(ifal);\n\t\tif (!if_ok) {\n\t\t\twarn(\"reading 'if_data' failed\");\n\t\t\treturn NULL;\n\t\t}\n\t\tif (oldtxbytes == 0)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human((txbytes - oldtxbytes) * 1000 / interval,\n\t\t                 1024);\n\t}\n#endif\n"
  },
  {
    "path": "components/num_files.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <dirent.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\nnum_files(const char *path)\n{\n\tstruct dirent *dp;\n\tDIR *dir;\n\tint num;\n\n\tif (!(dir = opendir(path))) {\n\t\twarn(\"opendir '%s':\", path);\n\t\treturn NULL;\n\t}\n\n\tnum = 0;\n\twhile ((dp = readdir(dir))) {\n\t\tif (!strcmp(dp->d_name, \".\") || !strcmp(dp->d_name, \"..\"))\n\t\t\tcontinue; /* skip self and parent */\n\n\t\tnum++;\n\t}\n\n\tclosedir(dir);\n\n\treturn bprintf(\"%d\", num);\n}\n"
  },
  {
    "path": "components/ram.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#if defined(__linux__)\n\t#include <stdint.h>\n\n\tconst char *\n\tram_free(const char *unused)\n\t{\n\t\tuintmax_t free;\n\t\tFILE *fp;\n\n\t\tif (!(fp = fopen(\"/proc/meminfo\", \"r\")))\n\t\t\treturn NULL;\n\n\t\tif (lscanf(fp, \"MemFree:\", \"%ju kB\", &free) != 1) {\n\t\t\tfclose(fp);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tfclose(fp);\n\t\treturn fmt_human(free * 1024, 1024);\n\t}\n\n\tconst char *\n\tram_perc(const char *unused)\n\t{\n\t\tuintmax_t total, free, buffers, cached, shmem, sreclaimable;\n\t\tint percent;\n\t\tFILE *fp;\n\n\t\tif (!(fp = fopen(\"/proc/meminfo\", \"r\")))\n\t\t\treturn NULL;\n\n\t\tif (lscanf(fp, \"MemTotal:\", \"%ju kB\", &total)  != 1 ||\n\t\t    lscanf(fp, \"MemFree:\", \"%ju kB\", &free)    != 1 ||\n\t\t    lscanf(fp, \"Buffers:\", \"%ju kB\", &buffers) != 1 ||\n\t\t    lscanf(fp, \"Cached:\", \"%ju kB\", &cached)   != 1 ||\n\t\t    lscanf(fp, \"Shmem:\", \"%ju kB\", &shmem)     != 1 ||\n\t\t    lscanf(fp, \"SReclaimable:\", \"%ju kB\", &sreclaimable) != 1) {\n\t\t\tfclose(fp);\n\t\t\treturn NULL;\n\t\t}\n\t\tfclose(fp);\n\n\t\tif (total == 0)\n\t\t\treturn NULL;\n\n\t\tpercent = 100 * (total - free - buffers - cached - sreclaimable + shmem) / total;\n\t\treturn bprintf(\"%d\", percent);\n\t}\n\n\tconst char *\n\tram_total(const char *unused)\n\t{\n\t\tuintmax_t total;\n\n\t\tif (pscanf(\"/proc/meminfo\", \"MemTotal: %ju kB\\n\", &total)\n\t\t    != 1)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(total * 1024, 1024);\n\t}\n\n\tconst char *\n\tram_used(const char *unused)\n\t{\n\t\tuintmax_t total, free, buffers, cached, used, shmem, sreclaimable;\n\t\tFILE *fp;\n\n\t\tif (!(fp = fopen(\"/proc/meminfo\", \"r\")))\n\t\t\treturn NULL;\n\n\t\tif (lscanf(fp, \"MemTotal:\", \"%ju kB\", &total)  != 1 ||\n\t\t    lscanf(fp, \"MemFree:\", \"%ju kB\", &free)    != 1 ||\n\t\t    lscanf(fp, \"Buffers:\", \"%ju kB\", &buffers) != 1 ||\n\t\t    lscanf(fp, \"Cached:\", \"%ju kB\", &cached)   != 1 ||\n\t\t    lscanf(fp, \"Shmem:\", \"%ju kB\", &shmem)     != 1 ||\n\t\t    lscanf(fp, \"SReclaimable:\", \"%ju kB\", &sreclaimable) != 1) {\n\t\t\tfclose(fp);\n\t\t\treturn NULL;\n\t\t}\n\t\tfclose(fp);\n\n\t\tused = total - free - buffers - cached - sreclaimable + shmem;\n\t\treturn fmt_human(used * 1024, 1024);\n\t}\n#elif defined(__OpenBSD__)\n\t#include <stdlib.h>\n\t#include <sys/sysctl.h>\n\t#include <sys/types.h>\n\t#include <unistd.h>\n\n\t#define LOG1024 10\n\t#define pagetok(size, pageshift) (size_t)(size << (pageshift - LOG1024))\n\n\tinline int\n\tload_uvmexp(struct uvmexp *uvmexp)\n\t{\n\t\tint uvmexp_mib[] = {CTL_VM, VM_UVMEXP};\n\t\tsize_t size;\n\n\t\tsize = sizeof(*uvmexp);\n\n\t\tif (sysctl(uvmexp_mib, 2, uvmexp, &size, NULL, 0) >= 0)\n\t\t\treturn 1;\n\n\t\treturn 0;\n\t}\n\n\tconst char *\n\tram_free(const char *unused)\n\t{\n\t\tstruct uvmexp uvmexp;\n\t\tint free_pages;\n\n\t\tif (!load_uvmexp(&uvmexp))\n\t\t\treturn NULL;\n\n\t\tfree_pages = uvmexp.npages - uvmexp.active;\n\t\treturn fmt_human(pagetok(free_pages, uvmexp.pageshift) *\n\t\t\t\t 1024, 1024);\n\t}\n\n\tconst char *\n\tram_perc(const char *unused)\n\t{\n\t\tstruct uvmexp uvmexp;\n\t\tint percent;\n\n\t\tif (!load_uvmexp(&uvmexp))\n\t\t\treturn NULL;\n\n\t\tpercent = uvmexp.active * 100 / uvmexp.npages;\n\t\treturn bprintf(\"%d\", percent);\n\t}\n\n\tconst char *\n\tram_total(const char *unused)\n\t{\n\t\tstruct uvmexp uvmexp;\n\n\t\tif (!load_uvmexp(&uvmexp))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(pagetok(uvmexp.npages,\n\t\t\t\t\t uvmexp.pageshift) * 1024, 1024);\n\t}\n\n\tconst char *\n\tram_used(const char *unused)\n\t{\n\t\tstruct uvmexp uvmexp;\n\n\t\tif (!load_uvmexp(&uvmexp))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(pagetok(uvmexp.active,\n\t\t\t\t\t uvmexp.pageshift) * 1024, 1024);\n\t}\n#elif defined(__FreeBSD__)\n\t#include <sys/sysctl.h>\n\t#include <sys/vmmeter.h>\n\t#include <unistd.h>\n\t#include <vm/vm_param.h>\n\n\tconst char *\n\tram_free(const char *unused) {\n\t\tstruct vmtotal vm_stats;\n\t\tint mib[] = {CTL_VM, VM_TOTAL};\n\t\tsize_t len;\n\n\t\tlen = sizeof(struct vmtotal);\n\t\tif (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0\n\t\t    || !len)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(vm_stats.t_free * getpagesize(), 1024);\n\t}\n\n\tconst char *\n\tram_total(const char *unused) {\n\t\tunsigned int npages;\n\t\tsize_t len;\n\n\t\tlen = sizeof(npages);\n\t\tif (sysctlbyname(\"vm.stats.vm.v_page_count\",\n\t\t                 &npages, &len, NULL, 0) < 0 || !len)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(npages * getpagesize(), 1024);\n\t}\n\n\tconst char *\n\tram_perc(const char *unused) {\n\t\tunsigned int npages;\n\t\tunsigned int active;\n\t\tsize_t len;\n\n\t\tlen = sizeof(npages);\n\t\tif (sysctlbyname(\"vm.stats.vm.v_page_count\",\n\t\t                 &npages, &len, NULL, 0) < 0 || !len)\n\t\t\treturn NULL;\n\n\t\tif (sysctlbyname(\"vm.stats.vm.v_active_count\",\n\t\t                 &active, &len, NULL, 0) < 0 || !len)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", active * 100 / npages);\n\t}\n\n\tconst char *\n\tram_used(const char *unused) {\n\t\tunsigned int active;\n\t\tsize_t len;\n\n\t\tlen = sizeof(active);\n\t\tif (sysctlbyname(\"vm.stats.vm.v_active_count\",\n\t\t                 &active, &len, NULL, 0) < 0 || !len)\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(active * getpagesize(), 1024);\n\t}\n#endif\n"
  },
  {
    "path": "components/run_command.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdio.h>\n#include <string.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\nrun_command(const char *cmd)\n{\n\tchar *p;\n\tFILE *fp;\n\n\tif (!(fp = popen(cmd, \"r\"))) {\n\t\twarn(\"popen '%s':\", cmd);\n\t\treturn NULL;\n\t}\n\n\tp = fgets(buf, sizeof(buf) - 1, fp);\n\tif (pclose(fp) < 0) {\n\t\twarn(\"pclose '%s':\", cmd);\n\t\treturn NULL;\n\t}\n\tif (!p)\n\t\treturn NULL;\n\n\tif ((p = strrchr(buf, '\\n')))\n\t\tp[0] = '\\0';\n\n\treturn buf[0] ? buf : NULL;\n}\n"
  },
  {
    "path": "components/swap.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#if defined(__linux__)\n\tstatic int\n\tget_swap_info(long *s_total, long *s_free, long *s_cached)\n\t{\n\t\tFILE *fp;\n\t\tstruct {\n\t\t\tconst char *name;\n\t\t\tconst size_t len;\n\t\t\tlong *var;\n\t\t} ent[] = {\n\t\t\t{ \"SwapTotal\",  sizeof(\"SwapTotal\") - 1,  s_total  },\n\t\t\t{ \"SwapFree\",   sizeof(\"SwapFree\") - 1,   s_free   },\n\t\t\t{ \"SwapCached\", sizeof(\"SwapCached\") - 1, s_cached },\n\t\t};\n\t\tsize_t line_len = 0, i, left;\n\t\tchar *line = NULL;\n\n\t\t/* get number of fields we want to extract */\n\t\tfor (i = 0, left = 0; i < LEN(ent); i++)\n\t\t\tif (ent[i].var)\n\t\t\t\tleft++;\n\n\t\tif (!(fp = fopen(\"/proc/meminfo\", \"r\"))) {\n\t\t\twarn(\"fopen '/proc/meminfo':\");\n\t\t\treturn 1;\n\t\t}\n\n\t\t/* read file line by line and extract field information */\n\t\twhile (left > 0 && getline(&line, &line_len, fp) >= 0) {\n\t\t\tfor (i = 0; i < LEN(ent); i++) {\n\t\t\t\tif (ent[i].var &&\n\t\t\t\t    !strncmp(line, ent[i].name, ent[i].len)) {\n\t\t\t\t\tsscanf(line + ent[i].len + 1,\n\t\t\t\t\t       \"%ld kB\\n\", ent[i].var);\n\t\t\t\t\tleft--;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfree(line);\n\t\tif (ferror(fp)) {\n\t\t\twarn(\"getline '/proc/meminfo':\");\n\t\t\treturn 1;\n\t\t}\n\n\t\tfclose(fp);\n\t\treturn 0;\n\t}\n\n\tconst char *\n\tswap_free(const char *unused)\n\t{\n\t\tlong free;\n\n\t\tif (get_swap_info(NULL, &free, NULL))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(free * 1024, 1024);\n\t}\n\n\tconst char *\n\tswap_perc(const char *unused)\n\t{\n\t\tlong total, free, cached;\n\n\t\tif (get_swap_info(&total, &free, &cached) || total == 0)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", 100 * (total - free - cached) / total);\n\t}\n\n\tconst char *\n\tswap_total(const char *unused)\n\t{\n\t\tlong total;\n\n\t\tif (get_swap_info(&total, NULL, NULL))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(total * 1024, 1024);\n\t}\n\n\tconst char *\n\tswap_used(const char *unused)\n\t{\n\t\tlong total, free, cached;\n\n\t\tif (get_swap_info(&total, &free, &cached))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human((total - free - cached) * 1024, 1024);\n\t}\n#elif defined(__OpenBSD__)\n\t#include <stdlib.h>\n\t#include <sys/swap.h>\n\t#include <sys/types.h>\n\t#include <unistd.h>\n\n\tstatic int\n\tgetstats(int *total, int *used)\n\t{\n\t\tstruct swapent *sep, *fsep;\n\t\tint rnswap, nswap, i;\n\n\t\tif ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) {\n\t\t\twarn(\"swaptctl 'SWAP_NSWAP':\");\n\t\t\treturn 1;\n\t\t}\n\t\tif (!(fsep = sep = calloc(nswap, sizeof(*sep)))) {\n\t\t\twarn(\"calloc 'nswap':\");\n\t\t\treturn 1;\n\t\t}\n\t\tif ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) {\n\t\t\twarn(\"swapctl 'SWAP_STATA':\");\n\t\t\treturn 1;\n\t\t}\n\t\tif (nswap != rnswap) {\n\t\t\twarn(\"getstats: SWAP_STATS != SWAP_NSWAP\");\n\t\t\treturn 1;\n\t\t}\n\n\t\t*total = 0;\n\t\t*used = 0;\n\n\t\tfor (i = 0; i < rnswap; i++) {\n\t\t\t*total += sep->se_nblks >> 1;\n\t\t\t*used += sep->se_inuse >> 1;\n\t\t}\n\n\t\tfree(fsep);\n\n\t\treturn 0;\n\t}\n\n\tconst char *\n\tswap_free(const char *unused)\n\t{\n\t\tint total, used;\n\n\t\tif (getstats(&total, &used))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human((total - used) * 1024, 1024);\n\t}\n\n\tconst char *\n\tswap_perc(const char *unused)\n\t{\n\t\tint total, used;\n\n\t\tif (getstats(&total, &used))\n\t\t\treturn NULL;\n\n\t\tif (total == 0)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%d\", 100 * used / total);\n\t}\n\n\tconst char *\n\tswap_total(const char *unused)\n\t{\n\t\tint total, used;\n\n\t\tif (getstats(&total, &used))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(total * 1024, 1024);\n\t}\n\n\tconst char *\n\tswap_used(const char *unused)\n\t{\n\t\tint total, used;\n\n\t\tif (getstats(&total, &used))\n\t\t\treturn NULL;\n\n\t\treturn fmt_human(used * 1024, 1024);\n\t}\n#elif defined(__FreeBSD__)\n\t#include <fcntl.h>\n\t#include <kvm.h>\n\t#include <stdlib.h>\n\t#include <sys/types.h>\n\t#include <unistd.h>\n\n\tstatic int getswapinfo(struct kvm_swap *swap_info, size_t size)\n\t{\n\t\tkvm_t *kd;\n\n\t\tkd = kvm_openfiles(NULL, \"/dev/null\", NULL, 0, NULL);\n\t\tif (kd == NULL) {\n\t\t\twarn(\"kvm_openfiles '/dev/null':\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) {\n\t\t\twarn(\"kvm_getswapinfo:\");\n\t\t\tkvm_close(kd);\n\t\t\treturn 0;\n\t\t}\n\n\t\tkvm_close(kd);\n\t\treturn 1;\n\t}\n\n\tconst char *\n\tswap_free(const char *unused)\n\t{\n\t\tstruct kvm_swap swap_info[1];\n\t\tlong used, total;\n\n\t\tif (!getswapinfo(swap_info, 1))\n\t\t\treturn NULL;\n\n\t\ttotal = swap_info[0].ksw_total;\n\t\tused = swap_info[0].ksw_used;\n\n\t\treturn fmt_human((total - used) * getpagesize(), 1024);\n\t}\n\n\tconst char *\n\tswap_perc(const char *unused)\n\t{\n\t\tstruct kvm_swap swap_info[1];\n\t\tlong used, total;\n\n\t\tif (!getswapinfo(swap_info, 1))\n\t\t\treturn NULL;\n\n\t\ttotal = swap_info[0].ksw_total;\n\t\tused = swap_info[0].ksw_used;\n\n\t\treturn bprintf(\"%d\", used * 100 / total);\n\t}\n\n\tconst char *\n\tswap_total(const char *unused)\n\t{\n\t\tstruct kvm_swap swap_info[1];\n\t\tlong total;\n\n\t\tif (!getswapinfo(swap_info, 1))\n\t\t\treturn NULL;\n\n\t\ttotal = swap_info[0].ksw_total;\n\n\t\treturn fmt_human(total * getpagesize(), 1024);\n\t}\n\n\tconst char *\n\tswap_used(const char *unused)\n\t{\n\t\tstruct kvm_swap swap_info[1];\n\t\tlong used;\n\n\t\tif (!getswapinfo(swap_info, 1))\n\t\t\treturn NULL;\n\n\t\tused = swap_info[0].ksw_used;\n\n\t\treturn fmt_human(used * getpagesize(), 1024);\n\t}\n#endif\n"
  },
  {
    "path": "components/temperature.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stddef.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n\n#if defined(__linux__)\n\t#include <stdint.h>\n\n\tconst char *\n\ttemp(const char *file)\n\t{\n\t\tuintmax_t temp;\n\n\t\tif (pscanf(file, \"%ju\", &temp) != 1)\n\t\t\treturn NULL;\n\n\t\treturn bprintf(\"%ju\", temp / 1000);\n\t}\n#elif defined(__OpenBSD__)\n\t#include <stdio.h>\n\t#include <sys/time.h> /* before <sys/sensors.h> for struct timeval */\n\t#include <sys/sensors.h>\n\t#include <sys/sysctl.h>\n\n\tconst char *\n\ttemp(const char *unused)\n\t{\n\t\tint mib[5];\n\t\tsize_t size;\n\t\tstruct sensor temp;\n\n\t\tmib[0] = CTL_HW;\n\t\tmib[1] = HW_SENSORS;\n\t\tmib[2] = 0; /* cpu0 */\n\t\tmib[3] = SENSOR_TEMP;\n\t\tmib[4] = 0; /* temp0 */\n\n\t\tsize = sizeof(temp);\n\n\t\tif (sysctl(mib, 5, &temp, &size, NULL, 0) < 0) {\n\t\t\twarn(\"sysctl 'SENSOR_TEMP':\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\t/* kelvin to celsius */\n\t\treturn bprintf(\"%d\", (int)((float)(temp.value-273150000) / 1E6));\n\t}\n#elif defined(__FreeBSD__)\n\t#include <stdio.h>\n\t#include <stdlib.h>\n\t#include <sys/sysctl.h>\n\n\t#define ACPI_TEMP \"hw.acpi.thermal.%s.temperature\"\n\n\tconst char *\n\ttemp(const char *zone)\n\t{\n\t\tchar buf[256];\n\t\tint temp;\n\t\tsize_t len;\n\n\t\tlen = sizeof(temp);\n\t\tsnprintf(buf, sizeof(buf), ACPI_TEMP, zone);\n\t\tif (sysctlbyname(buf, &temp, &len, NULL, 0) < 0\n\t\t\t\t|| !len)\n\t\t\treturn NULL;\n\n\t\t/* kelvin to decimal celcius */\n\t\treturn bprintf(\"%d.%d\", (temp - 2731) / 10, abs((temp - 2731) % 10));\n\t}\n#endif\n"
  },
  {
    "path": "components/uptime.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdint.h>\n#include <stdio.h>\n#include <time.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#if defined(CLOCK_BOOTTIME)\n\t#define UPTIME_FLAG CLOCK_BOOTTIME\n#elif defined(CLOCK_UPTIME)\n\t#define UPTIME_FLAG CLOCK_UPTIME\n#else\n\t#define UPTIME_FLAG CLOCK_MONOTONIC\n#endif\n\nconst char *\nuptime(const char *unused)\n{\n\tchar warn_buf[256];\n\tuintmax_t h, m;\n\tstruct timespec uptime;\n\n\tif (clock_gettime(UPTIME_FLAG, &uptime) < 0) {\n\t\tsnprintf(warn_buf, sizeof(warn_buf), \"clock_gettime %d\", UPTIME_FLAG);\n\t\twarn(warn_buf);\n\t\treturn NULL;\n\t}\n\n\th = uptime.tv_sec / 3600;\n\tm = uptime.tv_sec % 3600 / 60;\n\n\treturn bprintf(\"%juh %jum\", h, m);\n}\n"
  },
  {
    "path": "components/user.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <pwd.h>\n#include <stdio.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\nconst char *\ngid(const char *unused)\n{\n\treturn bprintf(\"%d\", getgid());\n}\n\nconst char *\nusername(const char *unused)\n{\n\tstruct passwd *pw;\n\n\tif (!(pw = getpwuid(geteuid()))) {\n\t\twarn(\"getpwuid '%d':\", geteuid());\n\t\treturn NULL;\n\t}\n\n\treturn bprintf(\"%s\", pw->pw_name);\n}\n\nconst char *\nuid(const char *unused)\n{\n\treturn bprintf(\"%d\", geteuid());\n}\n"
  },
  {
    "path": "components/volume.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <fcntl.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#if defined(__OpenBSD__) | defined(__FreeBSD__)\n\t#include <poll.h>\n\t#include <sndio.h>\n\t#include <stdlib.h>\n\t#include <sys/queue.h>\n\n\tstruct control {\n\t\tLIST_ENTRY(control)\tnext;\n\t\tunsigned int\t\taddr;\n\t#define CTRL_NONE\t0\n\t#define CTRL_LEVEL\t1\n\t#define CTRL_MUTE\t2\n\t\tunsigned int\t\ttype;\n\t\tunsigned int\t\tmaxval;\n\t\tunsigned int\t\tval;\n\t};\n\n\tstatic LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls);\n\tstatic struct pollfd *pfds;\n\tstatic struct sioctl_hdl *hdl;\n\tstatic int initialized;\n\n\t/*\n\t * Call-back to obtain the description of all audio controls.\n\t */\n\tstatic void\n\tondesc(void *unused, struct sioctl_desc *desc, int val)\n\t{\n\t\tstruct control *c, *ctmp;\n\t\tunsigned int type = CTRL_NONE;\n\n\t\tif (desc == NULL)\n\t\t\treturn;\n\n\t\t/* Delete existing audio control with the same address. */\n\t\tLIST_FOREACH_SAFE(c, &controls, next, ctmp) {\n\t\t\tif (desc->addr == c->addr) {\n\t\t\t\tLIST_REMOVE(c, next);\n\t\t\t\tfree(c);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* Only match output.level and output.mute audio controls. */\n\t\tif (desc->group[0] != 0 ||\n\t\t    strcmp(desc->node0.name, \"output\") != 0)\n\t\t\treturn;\n\t\tif (desc->type == SIOCTL_NUM &&\n\t\t    strcmp(desc->func, \"level\") == 0)\n\t\t\ttype = CTRL_LEVEL;\n\t\telse if (desc->type == SIOCTL_SW &&\n\t\t\t strcmp(desc->func, \"mute\") == 0)\n\t\t\ttype = CTRL_MUTE;\n\t\telse\n\t\t\treturn;\n\n\t\tc = malloc(sizeof(struct control));\n\t\tif (c == NULL) {\n\t\t\twarn(\"sndio: failed to allocate audio control\\n\");\n\t\t\treturn;\n\t\t}\n\n\t\tc->addr = desc->addr;\n\t\tc->type = type;\n\t\tc->maxval = desc->maxval;\n\t\tc->val = val;\n\t\tLIST_INSERT_HEAD(&controls, c, next);\n\t}\n\n\t/*\n\t * Call-back invoked whenever an audio control changes.\n\t */\n\tstatic void\n\tonval(void *unused, unsigned int addr, unsigned int val)\n\t{\n\t\tstruct control *c;\n\n\t\tLIST_FOREACH(c, &controls, next) {\n\t\t\tif (c->addr == addr)\n\t\t\t\tbreak;\n\t\t}\n\t\tif (c == NULL)\n\t\t\treturn;\n\t\tc->val = val;\n\t}\n\n\tstatic void\n\tcleanup(void)\n\t{\n\t\tstruct control *c;\n\n\t\tif (hdl) {\n\t\t\tsioctl_close(hdl);\n\t\t\thdl = NULL;\n\t\t}\n\n\t\tfree(pfds);\n\t\tpfds = NULL;\n\n\t\twhile (!LIST_EMPTY(&controls)) {\n\t\t\tc = LIST_FIRST(&controls);\n\t\t\tLIST_REMOVE(c, next);\n\t\t\tfree(c);\n\t\t}\n\t}\n\n\tstatic int\n\tinit(void)\n\t{\n\t\thdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0);\n\t\tif (hdl == NULL) {\n\t\t\twarn(\"sndio: cannot open device\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tif (!sioctl_ondesc(hdl, ondesc, NULL)) {\n\t\t\twarn(\"sndio: cannot set control description call-back\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tif (!sioctl_onval(hdl, onval, NULL)) {\n\t\t\twarn(\"sndio: cannot set control values call-back\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tpfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd));\n\t\tif (pfds == NULL) {\n\t\t\twarn(\"sndio: cannot allocate pollfd structures\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\treturn 1;\n\tfailed:\n\t\tcleanup();\n\t\treturn 0;\n\t}\n\n\tconst char *\n\tvol_perc(const char *unused)\n\t{\n\t\tstruct control *c;\n\t\tint n, v, value;\n\n\t\tif (!initialized)\n\t\t\tinitialized = init();\n\n\t\tif (hdl == NULL)\n\t\t\treturn NULL;\n\n\t\tn = sioctl_pollfd(hdl, pfds, POLLIN);\n\t\tif (n > 0) {\n\t\t\tn = poll(pfds, n, 0);\n\t\t\tif (n > 0) {\n\t\t\t\tif (sioctl_revents(hdl, pfds) & POLLHUP) {\n\t\t\t\t\twarn(\"sndio: disconnected\");\n\t\t\t\t\tcleanup();\n\t\t\t\t\tinitialized = 0;\n\t\t\t\t\treturn NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvalue = 100;\n\t\tLIST_FOREACH(c, &controls, next) {\n\t\t\tif (c->type == CTRL_MUTE && c->val == 1)\n\t\t\t\tvalue = 0;\n\t\t\telse if (c->type == CTRL_LEVEL) {\n\t\t\t\tv = (c->val * 100 + c->maxval / 2) / c->maxval;\n\t\t\t\t/* For multiple channels return the minimum. */\n\t\t\t\tif (v < value)\n\t\t\t\t\tvalue = v;\n\t\t\t}\n\t\t}\n\n\t\treturn bprintf(\"%d\", value);\n\t}\n#else\n\t#include <sys/soundcard.h>\n\n\tconst char *\n\tvol_perc(const char *card)\n\t{\n\t\tsize_t i;\n\t\tint v, afd, devmask;\n\t\tchar *vnames[] = SOUND_DEVICE_NAMES;\n\n\t\tif ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) {\n\t\t\twarn(\"open '%s':\", card);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) < 0) {\n\t\t\twarn(\"ioctl 'SOUND_MIXER_READ_DEVMASK':\");\n\t\t\tclose(afd);\n\t\t\treturn NULL;\n\t\t}\n\t\tfor (i = 0; i < LEN(vnames); i++) {\n\t\t\tif (devmask & (1 << i) && !strcmp(\"vol\", vnames[i])) {\n\t\t\t\tif (ioctl(afd, MIXER_READ(i), &v) < 0) {\n\t\t\t\t\twarn(\"ioctl 'MIXER_READ(%ld)':\", i);\n\t\t\t\t\tclose(afd);\n\t\t\t\t\treturn NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tclose(afd);\n\n\t\treturn bprintf(\"%d\", v & 0xff);\n\t}\n#endif\n"
  },
  {
    "path": "components/wifi.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <ifaddrs.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/socket.h>\n#include <unistd.h>\n\n#include \"../slstatus.h\"\n#include \"../util.h\"\n\n#define RSSI_TO_PERC(rssi) \\\n\t\t\trssi >= -50 ? 100 : \\\n\t\t\t(rssi <= -100 ? 0 : \\\n\t\t\t(2 * (rssi + 100)))\n\n#if defined(__linux__)\n\t#include <stdint.h>\n\t#include <net/if.h>\n\t#include <linux/netlink.h>\n\t#include <linux/genetlink.h>\n\t#include <linux/nl80211.h>\n\n\tstatic int nlsock = -1;\n\tstatic uint32_t seq = 1;\n\tstatic char resp[4096];\n\n\tstatic char *\n\tfindattr(int attr, const char *p, const char *e, size_t *len)\n\t{\n\t\twhile (p < e) {\n\t\t\tstruct nlattr nla;\n\t\t\tmemcpy(&nla, p, sizeof(nla));\n\t\t\tif (nla.nla_type == attr) {\n\t\t\t\t*len = nla.nla_len - NLA_HDRLEN;\n\t\t\t\treturn (char *)(p + NLA_HDRLEN);\n\t\t\t}\n\t\t\tp += NLA_ALIGN(nla.nla_len);\n\t\t}\n\t\treturn NULL;\n\t}\n\n\tstatic uint16_t\n\tnl80211fam(void)\n\t{\n\t\tstatic const char family[] = \"nl80211\";\n\t\tstatic uint16_t id;\n\t\tssize_t r;\n\t\tsize_t len;\n\t\tchar ctrl[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(sizeof(family))] = {0}, *p = ctrl;\n\n\t\tif (id)\n\t\t\treturn id;\n\n\t\tmemcpy(p, &(struct nlmsghdr){\n\t\t\t.nlmsg_len = sizeof(ctrl),\n\t\t\t.nlmsg_type = GENL_ID_CTRL,\n\t\t\t.nlmsg_flags = NLM_F_REQUEST,\n\t\t\t.nlmsg_seq = seq++,\n\t\t\t.nlmsg_pid = 0,\n\t\t}, sizeof(struct nlmsghdr));\n\t\tp += NLMSG_HDRLEN;\n\t\tmemcpy(p, &(struct genlmsghdr){\n\t\t\t.cmd = CTRL_CMD_GETFAMILY,\n\t\t\t.version = 1,\n\t\t}, sizeof(struct genlmsghdr));\n\t\tp += GENL_HDRLEN;\n\t\tmemcpy(p, &(struct nlattr){\n\t\t\t.nla_len = NLA_HDRLEN+sizeof(family),\n\t\t\t.nla_type = CTRL_ATTR_FAMILY_NAME,\n\t\t}, sizeof(struct nlattr));\n\t\tp += NLA_HDRLEN;\n\t\tmemcpy(p, family, sizeof(family));\n\n\t\tif (nlsock < 0)\n\t\t\tnlsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);\n\t\tif (nlsock < 0) {\n\t\t\twarn(\"socket 'AF_NETLINK':\");\n\t\t\treturn 0;\n\t\t}\n\t\tif (send(nlsock, ctrl, sizeof(ctrl), 0) != sizeof(ctrl)) {\n\t\t\twarn(\"send 'AF_NETLINK':\");\n\t\t\treturn 0;\n\t\t}\n\t\tr = recv(nlsock, resp, sizeof(resp), 0);\n\t\tif (r < 0) {\n\t\t\twarn(\"recv 'AF_NETLINK':\");\n\t\t\treturn 0;\n\t\t}\n\t\tif ((size_t)r <= sizeof(ctrl))\n\t\t\treturn 0;\n\t\tp = findattr(CTRL_ATTR_FAMILY_ID, resp + sizeof(ctrl), resp + r, &len);\n\t\tif (p && len == 2)\n\t\t\tmemcpy(&id, p, 2);\n\n\t\treturn id;\n\t}\n\n\tstatic int\n\tifindex(const char *interface)\n\t{\n\t\tstatic struct ifreq ifr;\n\t\tstatic int ifsock = -1;\n\n\t\tif (ifsock < 0)\n\t\t\tifsock = socket(AF_UNIX, SOCK_DGRAM, 0);\n\t\tif (ifsock < 0) {\n\t\t\twarn(\"socket 'AF_UNIX':\");\n\t\t\treturn -1;\n\t\t}\n\t\tif (strcmp(ifr.ifr_name, interface) != 0) {\n\t\t\tstrcpy(ifr.ifr_name, interface);\n\t\t}\n\t\tif (ioctl(ifsock, SIOCGIFINDEX, &ifr) != 0) {\n\t\t\twarn(\"ioctl 'SIOCGIFINDEX':\");\n\t\t\treturn -1;\n\t\t}\n\t\treturn ifr.ifr_ifindex;\n\t}\n\n\tconst char *\n\twifi_essid(const char *interface)\n\t{\n\t\tuint16_t fam = nl80211fam();\n\t\tssize_t r;\n\t\tsize_t len;\n\t\tchar req[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(4)] = {0}, *p = req;\n\t\tint idx = ifindex(interface);\n\t\tif (!fam) {\n\t\t\tfprintf(stderr, \"nl80211 family not found\\n\");\n\t\t\treturn NULL;\n\t\t}\n\t\tif (idx < 0) {\n\t\t\tfprintf(stderr, \"interface %s not found\\n\", interface);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tmemcpy(p, &(struct nlmsghdr){\n\t\t\t.nlmsg_len = sizeof(req),\n\t\t\t.nlmsg_type = fam,\n\t\t\t.nlmsg_flags = NLM_F_REQUEST,\n\t\t\t.nlmsg_seq = seq++,\n\t\t\t.nlmsg_pid = 0,\n\t\t}, sizeof(struct nlmsghdr));\n\t\tp += NLMSG_HDRLEN;\n\t\tmemcpy(p, &(struct genlmsghdr){\n\t\t\t.cmd = NL80211_CMD_GET_INTERFACE,\n\t\t\t.version = 1,\n\t\t}, sizeof(struct genlmsghdr));\n\t\tp += GENL_HDRLEN;\n\t\tmemcpy(p, &(struct nlattr){\n\t\t\t.nla_len = NLA_HDRLEN+4,\n\t\t\t.nla_type = NL80211_ATTR_IFINDEX,\n\t\t}, sizeof(struct nlattr));\n\t\tp += NLA_HDRLEN;\n\t\tmemcpy(p, &(uint32_t){idx}, 4);\n\n\t\tif (send(nlsock, req, sizeof(req), 0) != sizeof(req)) {\n\t\t\twarn(\"send 'AF_NETLINK':\");\n\t\t\treturn NULL;\n\t\t}\n\t\tr = recv(nlsock, resp, sizeof(resp), 0);\n\t\tif (r < 0) {\n\t\t\twarn(\"recv 'AF_NETLINK':\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif ((size_t)r <= NLMSG_HDRLEN + GENL_HDRLEN)\n\t\t\treturn NULL;\n\t\tp = findattr(NL80211_ATTR_SSID, resp + NLMSG_HDRLEN + GENL_HDRLEN, resp + r, &len);\n\t\tif (p)\n\t\t\tp[len] = 0;\n\n\t\treturn p;\n\t}\n\n\tconst char *\n\twifi_perc(const char *interface)\n\t{\n\t\tstatic char strength[4];\n\t\tstruct nlmsghdr hdr;\n\t\tuint16_t fam = nl80211fam();\n\t\tssize_t r;\n\t\tsize_t len;\n\t\tchar req[NLMSG_HDRLEN + GENL_HDRLEN + NLA_HDRLEN + NLA_ALIGN(4)] = {0}, *p = req, *e;\n\t\tint idx = ifindex(interface);\n\n\t\tif (idx < 0) {\n\t\t\tfprintf(stderr, \"interface %s not found\\n\", interface);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tmemcpy(p, &(struct nlmsghdr){\n\t\t\t.nlmsg_len = sizeof(req),\n\t\t\t.nlmsg_type = fam,\n\t\t\t.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP,\n\t\t\t.nlmsg_seq = seq++,\n\t\t\t.nlmsg_pid = 0,\n\t\t}, sizeof(struct nlmsghdr));\n\t\tp += NLMSG_HDRLEN;\n\t\tmemcpy(p, &(struct genlmsghdr){\n\t\t\t.cmd = NL80211_CMD_GET_STATION,\n\t\t\t.version = 1,\n\t\t}, sizeof(struct genlmsghdr));\n\t\tp += GENL_HDRLEN;\n\t\tmemcpy(p, &(struct nlattr){\n\t\t\t.nla_len = NLA_HDRLEN + 4,\n\t\t\t.nla_type = NL80211_ATTR_IFINDEX,\n\t\t}, sizeof(struct nlattr));\n\t\tp += NLA_HDRLEN;\n\t\tmemcpy(p, &idx, 4);\n\n\t\tif (send(nlsock, req, sizeof(req), 0) != sizeof(req)) {\n\t\t\twarn(\"send 'AF_NETLINK':\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\t*strength = 0;\n\t\twhile (1) {\n\t\t\tr = recv(nlsock, resp, sizeof(resp), 0);\n\t\t\tif (r < 0) {\n\t\t\t\twarn(\"recv 'AF_NETLINK':\");\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\tif ((size_t)r < sizeof(hdr))\n\t\t\t\treturn NULL;\n\n\t\t\tfor (p = resp; p != resp + r && (size_t)(resp + r-p) >= sizeof(hdr); p = e) {\n\t\t\t\tmemcpy(&hdr, p, sizeof(hdr));\n\t\t\t\te = resp + r - p < hdr.nlmsg_len ? resp + r : p + hdr.nlmsg_len;\n\n\t\t\t\tif (!*strength && hdr.nlmsg_len > NLMSG_HDRLEN+GENL_HDRLEN) {\n\t\t\t\t\tp += NLMSG_HDRLEN+GENL_HDRLEN;\n\t\t\t\t\tp = findattr(NL80211_ATTR_STA_INFO, p, e, &len);\n\t\t\t\t\tif (p)\n\t\t\t\t\t\tp = findattr(NL80211_STA_INFO_SIGNAL_AVG, p, e, &len);\n\t\t\t\t\tif (p && len == 1)\n\t\t\t\t\t\tsnprintf(strength, sizeof(strength), \"%d\", RSSI_TO_PERC(*p));\n\t\t\t\t}\n\t\t\t\tif (hdr.nlmsg_type == NLMSG_DONE)\n\t\t\t\t\treturn *strength ? strength : NULL;\n\t\t\t}\n\t\t}\n\t}\n#elif defined(__OpenBSD__)\n\t#include <net/if.h>\n\t#include <net/if_media.h>\n\t#include <net80211/ieee80211.h>\n\t#include <sys/select.h> /* before <sys/ieee80211_ioctl.h> for NBBY */\n\t#include <net80211/ieee80211_ioctl.h>\n\t#include <stdlib.h>\n\t#include <sys/types.h>\n\n\tstatic int\n\tload_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr)\n\t{\n\t\tstruct ieee80211_bssid bssid;\n\t\tint sockfd;\n\t\tuint8_t zero_bssid[IEEE80211_ADDR_LEN];\n\n\t\tmemset(&bssid, 0, sizeof(bssid));\n\t\tmemset(nr, 0, sizeof(struct ieee80211_nodereq));\n\t\tif ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {\n\t\t\twarn(\"socket 'AF_INET':\");\n\t\t\treturn 0;\n\t\t}\n\t\tstrlcpy(bssid.i_name, interface, sizeof(bssid.i_name));\n\t\tif ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) {\n\t\t\twarn(\"ioctl 'SIOCG80211BSSID':\");\n\t\t\tclose(sockfd);\n\t\t\treturn 0;\n\t\t}\n\t\tmemset(&zero_bssid, 0, sizeof(zero_bssid));\n\t\tif (memcmp(bssid.i_bssid, zero_bssid,\n\t\t    IEEE80211_ADDR_LEN) == 0) {\n\t\t\tclose(sockfd);\n\t\t\treturn 0;\n\t\t}\n\t\tstrlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname));\n\t\tmemcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr));\n\t\tif ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) {\n\t\t\twarn(\"ioctl 'SIOCG80211NODE':\");\n\t\t\tclose(sockfd);\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn close(sockfd), 1;\n\t}\n\n\tconst char *\n\twifi_perc(const char *interface)\n\t{\n\t\tstruct ieee80211_nodereq nr;\n\t\tint q;\n\n\t\tif (load_ieee80211_nodereq(interface, &nr)) {\n\t\t\tif (nr.nr_max_rssi)\n\t\t\t\tq = IEEE80211_NODEREQ_RSSI(&nr);\n\t\t\telse\n\t\t\t\tq = RSSI_TO_PERC(nr.nr_rssi);\n\n\t\t\treturn bprintf(\"%d\", q);\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\tconst char *\n\twifi_essid(const char *interface)\n\t{\n\t\tstruct ieee80211_nodereq nr;\n\n\t\tif (load_ieee80211_nodereq(interface, &nr))\n\t\t\treturn bprintf(\"%s\", nr.nr_nwid);\n\n\t\treturn NULL;\n\t}\n#elif defined(__FreeBSD__)\n\t#include <net/if.h>\n\t#include <net80211/ieee80211_ioctl.h>\n\n\tint\n\tload_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len)\n\t{\n\t\tchar warn_buf[256];\n\t\tstruct ieee80211req ireq;\n\t\tmemset(&ireq, 0, sizeof(ireq));\n\t\tireq.i_type = type;\n\t\tireq.i_data = (caddr_t) data;\n\t\tireq.i_len = *len;\n\n\t\tstrlcpy(ireq.i_name, interface, sizeof(ireq.i_name));\n\t\tif (ioctl(sock, SIOCG80211, &ireq) < 0) {\n\t\t\tsnprintf(warn_buf,  sizeof(warn_buf),\n\t\t\t\t\t\"ioctl: 'SIOCG80211': %d\", type);\n\t\t\twarn(warn_buf);\n\t\t\treturn 0;\n\t\t}\n\n\t\t*len = ireq.i_len;\n\t\treturn 1;\n\t}\n\n\tconst char *\n\twifi_perc(const char *interface)\n\t{\n\t\tunion {\n\t\t\tstruct ieee80211req_sta_req sta;\n\t\t\tuint8_t buf[24 * 1024];\n\t\t} info;\n\t\tuint8_t bssid[IEEE80211_ADDR_LEN];\n\t\tint rssi_dbm;\n\t\tint sockfd;\n\t\tsize_t len;\n\t\tconst char *fmt;\n\n\t\tif ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {\n\t\t\twarn(\"socket 'AF_INET':\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\t/* Retreive MAC address of interface */\n\t\tlen = IEEE80211_ADDR_LEN;\n\t\tfmt = NULL;\n\t\tif (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len))\n\t\t{\n\t\t\t/* Retrieve info on station with above BSSID */\n\t\t\tmemset(&info, 0, sizeof(info));\n\t\t\tmemcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid));\n\n\t\t\tlen = sizeof(info);\n\t\t\tif (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) {\n\t\t\t\trssi_dbm = info.sta.info[0].isi_noise +\n \t\t\t\t\t         info.sta.info[0].isi_rssi / 2;\n\n\t\t\t\tfmt = bprintf(\"%d\", RSSI_TO_PERC(rssi_dbm));\n\t\t\t}\n\t\t}\n\n\t\tclose(sockfd);\n\t\treturn fmt;\n\t}\n\n\tconst char *\n\twifi_essid(const char *interface)\n\t{\n\t\tchar ssid[IEEE80211_NWID_LEN + 1];\n\t\tsize_t len;\n\t\tint sockfd;\n\t\tconst char *fmt;\n\n\t\tif ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {\n\t\t\twarn(\"socket 'AF_INET':\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\tfmt = NULL;\n\t\tlen = sizeof(ssid);\n\t\tmemset(&ssid, 0, len);\n\t\tif (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) {\n\t\t\tif (len < sizeof(ssid))\n\t\t\t\tlen += 1;\n\t\t\telse\n\t\t\t\tlen = sizeof(ssid);\n\n\t\t\tssid[len - 1] = '\\0';\n\t\t\tfmt = bprintf(\"%s\", ssid);\n\t\t}\n\n\t\tclose(sockfd);\n\t\treturn fmt;\n\t}\n#endif\n"
  },
  {
    "path": "config.def.h",
    "content": "/* See LICENSE file for copyright and license details. */\n\n/* interval between updates (in ms) */\nconst unsigned int interval = 1000;\n\n/* text to show if no value can be retrieved */\nstatic const char unknown_str[] = \"n/a\";\n\n/* maximum output string length */\n#define MAXLEN 2048\n\n/*\n * function            description                     argument (example)\n *\n * battery_perc        battery percentage              battery name (BAT0)\n *                                                     NULL on OpenBSD/FreeBSD\n * battery_remaining   battery remaining HH:MM         battery name (BAT0)\n *                                                     NULL on OpenBSD/FreeBSD\n * battery_state       battery charging state          battery name (BAT0)\n *                                                     NULL on OpenBSD/FreeBSD\n * cat                 read arbitrary file             path\n * cpu_freq            cpu frequency in MHz            NULL\n * cpu_perc            cpu usage in percent            NULL\n * datetime            date and time                   format string (%F %T)\n * disk_free           free disk space in GB           mountpoint path (/)\n * disk_perc           disk usage in percent           mountpoint path (/)\n * disk_total          total disk space in GB          mountpoint path (/)\n * disk_used           used disk space in GB           mountpoint path (/)\n * entropy             available entropy               NULL\n * gid                 GID of current user             NULL\n * hostname            hostname                        NULL\n * ipv4                IPv4 address                    interface name (eth0)\n * ipv6                IPv6 address                    interface name (eth0)\n * kernel_release      `uname -r`                      NULL\n * keyboard_indicators caps/num lock indicators        format string (c?n?)\n *                                                     see keyboard_indicators.c\n * keymap              layout (variant) of current     NULL\n *                     keymap\n * load_avg            load average                    NULL\n * netspeed_rx         receive network speed           interface name (wlan0)\n * netspeed_tx         transfer network speed          interface name (wlan0)\n * num_files           number of files in a directory  path\n *                                                     (/home/foo/Inbox/cur)\n * ram_free            free memory in GB               NULL\n * ram_perc            memory usage in percent         NULL\n * ram_total           total memory size in GB         NULL\n * ram_used            used memory in GB               NULL\n * run_command         custom shell command            command (echo foo)\n * swap_free           free swap in GB                 NULL\n * swap_perc           swap usage in percent           NULL\n * swap_total          total swap size in GB           NULL\n * swap_used           used swap in GB                 NULL\n * temp                temperature in degree celsius   sensor file\n *                                                     (/sys/class/thermal/...)\n *                                                     NULL on OpenBSD\n *                                                     thermal zone on FreeBSD\n *                                                     (tz0, tz1, etc.)\n * uid                 UID of current user             NULL\n * up                  interface is running            interface name (eth0)\n * uptime              system uptime                   NULL\n * username            username of current user        NULL\n * vol_perc            OSS/ALSA volume in percent      mixer file (/dev/mixer)\n *                                                     NULL on OpenBSD/FreeBSD\n * wifi_essid          WiFi ESSID                      interface name (wlan0)\n * wifi_perc           WiFi signal in percent          interface name (wlan0)\n */\nstatic const struct arg args[] = {\n\t/* function format          argument */\n\t{ datetime, \"%s\",           \"%F %T\" },\n};\n"
  },
  {
    "path": "config.mk",
    "content": "# slstatus version\nVERSION = 1.1\n\n# customize below to fit your system\n\n# paths\nPREFIX = /usr/local\nMANPREFIX = $(PREFIX)/share/man\n\nX11INC = /usr/X11R6/include\nX11LIB = /usr/X11R6/lib\n\n# flags\nCPPFLAGS = -I$(X11INC) -D_DEFAULT_SOURCE -DVERSION=\\\"${VERSION}\\\"\nCFLAGS   = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -Os\nLDFLAGS  = -L$(X11LIB) -s\n# OpenBSD: add -lsndio\n# FreeBSD: add -lkvm -lsndio\nLDLIBS   = -lX11\n\n# compiler and linker\nCC = cc\n"
  },
  {
    "path": "slstatus.1",
    "content": ".Dd 2023-04-23\n.Dt SLSTATUS 1\n.Os\n.Sh NAME\n.Nm slstatus\n.Nd suckless status\n.Sh SYNOPSIS\n.Nm\n.Op Fl s\n.Op Fl 1\n.Sh DESCRIPTION\n.Nm\nis a small tool for providing system status information to other programs\nover the EWMH\n.Em WM_NAME\nproperty of the root window (used by\n.Xr dwm 1 ) or standard input/output. It is designed to be as efficient as possible by\nonly issuing the minimum of system calls required.\n.P\nBy default,\n.Nm\noutputs to WM_NAME.\n.Sh OPTIONS\n.Bl -tag -width Ds\n.It Fl v\nPrint version information to stderr, then exit.\n.It Fl s\nWrite to stdout instead of WM_NAME.\n.It Fl 1\nWrite once to stdout and quit.\n.El\n.Sh CUSTOMIZATION\n.Nm\ncan be customized by creating a custom config.h and (re)compiling the source\ncode. This keeps it fast, secure and simple.\n.Sh SIGNALS\n.Nm\nresponds to the following signals:\n.Pp\n.Bl -tag -width TERM -compact\n.It USR1\nTriggers an instant redraw.\n.El\n.Sh AUTHORS\nSee the LICENSE file for the authors.\n.Sh SEE ALSO\n.Xr dwm 1\n"
  },
  {
    "path": "slstatus.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <errno.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <X11/Xlib.h>\n\n#include \"arg.h\"\n#include \"slstatus.h\"\n#include \"util.h\"\n\nstruct arg {\n\tconst char *(*func)(const char *);\n\tconst char *fmt;\n\tconst char *args;\n};\n\nchar buf[1024];\nstatic volatile sig_atomic_t done;\nstatic Display *dpy;\n\n#include \"config.h\"\n\nstatic void\nterminate(const int signo)\n{\n\tif (signo != SIGUSR1)\n\t\tdone = 1;\n}\n\nstatic void\ndifftimespec(struct timespec *res, struct timespec *a, struct timespec *b)\n{\n\tres->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec);\n\tres->tv_nsec = a->tv_nsec - b->tv_nsec +\n\t               (a->tv_nsec < b->tv_nsec) * 1E9;\n}\n\nstatic void\nusage(void)\n{\n\tdie(\"usage: %s [-v] [-s] [-1]\", argv0);\n}\n\nint\nmain(int argc, char *argv[])\n{\n\tstruct sigaction act;\n\tstruct timespec start, current, diff, intspec, wait;\n\tsize_t i, len;\n\tint sflag, ret;\n\tchar status[MAXLEN];\n\tconst char *res;\n\n\tsflag = 0;\n\tARGBEGIN {\n\tcase 'v':\n\t\tdie(\"slstatus-\"VERSION);\n\t\tbreak;\n\tcase '1':\n\t\tdone = 1;\n\t\t/* FALLTHROUGH */\n\tcase 's':\n\t\tsflag = 1;\n\t\tbreak;\n\tdefault:\n\t\tusage();\n\t} ARGEND\n\n\tif (argc)\n\t\tusage();\n\n\tmemset(&act, 0, sizeof(act));\n\tact.sa_handler = terminate;\n\tsigaction(SIGINT,  &act, NULL);\n\tsigaction(SIGTERM, &act, NULL);\n\tact.sa_flags |= SA_RESTART;\n\tsigaction(SIGUSR1, &act, NULL);\n\n\tif (!sflag && !(dpy = XOpenDisplay(NULL)))\n\t\tdie(\"XOpenDisplay: Failed to open display\");\n\n\tdo {\n\t\tif (clock_gettime(CLOCK_MONOTONIC, &start) < 0)\n\t\t\tdie(\"clock_gettime:\");\n\n\t\tstatus[0] = '\\0';\n\t\tfor (i = len = 0; i < LEN(args); i++) {\n\t\t\tif (!(res = args[i].func(args[i].args)))\n\t\t\t\tres = unknown_str;\n\n\t\t\tif ((ret = esnprintf(status + len, sizeof(status) - len,\n\t\t\t                     args[i].fmt, res)) < 0)\n\t\t\t\tbreak;\n\n\t\t\tlen += ret;\n\t\t}\n\n\t\tif (sflag) {\n\t\t\tputs(status);\n\t\t\tfflush(stdout);\n\t\t\tif (ferror(stdout))\n\t\t\t\tdie(\"puts:\");\n\t\t} else {\n\t\t\tif (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0)\n\t\t\t\tdie(\"XStoreName: Allocation failed\");\n\t\t\tXFlush(dpy);\n\t\t}\n\n\t\tif (!done) {\n\t\t\tif (clock_gettime(CLOCK_MONOTONIC, &current) < 0)\n\t\t\t\tdie(\"clock_gettime:\");\n\t\t\tdifftimespec(&diff, &current, &start);\n\n\t\t\tintspec.tv_sec = interval / 1000;\n\t\t\tintspec.tv_nsec = (interval % 1000) * 1E6;\n\t\t\tdifftimespec(&wait, &intspec, &diff);\n\n\t\t\tif (wait.tv_sec >= 0 &&\n\t\t\t    nanosleep(&wait, NULL) < 0 &&\n\t\t\t    errno != EINTR)\n\t\t\t\t\tdie(\"nanosleep:\");\n\t\t}\n\t} while (!done);\n\n\tif (!sflag) {\n\t\tXStoreName(dpy, DefaultRootWindow(dpy), NULL);\n\t\tif (XCloseDisplay(dpy) < 0)\n\t\t\tdie(\"XCloseDisplay: Failed to close display\");\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "slstatus.h",
    "content": "/* See LICENSE file for copyright and license details. */\n\n/* battery */\nconst char *battery_perc(const char *);\nconst char *battery_remaining(const char *);\nconst char *battery_state(const char *);\n\n/* cat */\nconst char *cat(const char *path);\n\n/* cpu */\nconst char *cpu_freq(const char *unused);\nconst char *cpu_perc(const char *unused);\n\n/* datetime */\nconst char *datetime(const char *fmt);\n\n/* disk */\nconst char *disk_free(const char *path);\nconst char *disk_perc(const char *path);\nconst char *disk_total(const char *path);\nconst char *disk_used(const char *path);\n\n/* entropy */\nconst char *entropy(const char *unused);\n\n/* hostname */\nconst char *hostname(const char *unused);\n\n/* ip */\nconst char *ipv4(const char *interface);\nconst char *ipv6(const char *interface);\nconst char *up(const char *interface);\n\n/* kernel_release */\nconst char *kernel_release(const char *unused);\n\n/* keyboard_indicators */\nconst char *keyboard_indicators(const char *fmt);\n\n/* keymap */\nconst char *keymap(const char *unused);\n\n/* load_avg */\nconst char *load_avg(const char *unused);\n\n/* netspeeds */\nconst char *netspeed_rx(const char *interface);\nconst char *netspeed_tx(const char *interface);\n\n/* num_files */\nconst char *num_files(const char *path);\n\n/* ram */\nconst char *ram_free(const char *unused);\nconst char *ram_perc(const char *unused);\nconst char *ram_total(const char *unused);\nconst char *ram_used(const char *unused);\n\n/* run_command */\nconst char *run_command(const char *cmd);\n\n/* swap */\nconst char *swap_free(const char *unused);\nconst char *swap_perc(const char *unused);\nconst char *swap_total(const char *unused);\nconst char *swap_used(const char *unused);\n\n/* temperature */\nconst char *temp(const char *);\n\n/* uptime */\nconst char *uptime(const char *unused);\n\n/* user */\nconst char *gid(const char *unused);\nconst char *uid(const char *unused);\nconst char *username(const char *unused);\n\n/* volume */\nconst char *vol_perc(const char *card);\n\n/* wifi */\nconst char *wifi_essid(const char *interface);\nconst char *wifi_perc(const char *interface);\n"
  },
  {
    "path": "util.c",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <errno.h>\n#include <stdarg.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"util.h\"\n\nchar *argv0;\n\nstatic void\nverr(const char *fmt, va_list ap)\n{\n\tvfprintf(stderr, fmt, ap);\n\n\tif (fmt[0] && fmt[strlen(fmt) - 1] == ':') {\n\t\tfputc(' ', stderr);\n\t\tperror(NULL);\n\t} else {\n\t\tfputc('\\n', stderr);\n\t}\n}\n\nvoid\nwarn(const char *fmt, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tverr(fmt, ap);\n\tva_end(ap);\n}\n\nvoid\ndie(const char *fmt, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tverr(fmt, ap);\n\tva_end(ap);\n\n\texit(1);\n}\n\nstatic int\nevsnprintf(char *str, size_t size, const char *fmt, va_list ap)\n{\n\tint ret;\n\n\tret = vsnprintf(str, size, fmt, ap);\n\n\tif (ret < 0) {\n\t\twarn(\"vsnprintf:\");\n\t\treturn -1;\n\t} else if ((size_t)ret >= size) {\n\t\twarn(\"vsnprintf: Output truncated\");\n\t\treturn -1;\n\t}\n\n\treturn ret;\n}\n\nint\nesnprintf(char *str, size_t size, const char *fmt, ...)\n{\n\tva_list ap;\n\tint ret;\n\n\tva_start(ap, fmt);\n\tret = evsnprintf(str, size, fmt, ap);\n\tva_end(ap);\n\n\treturn ret;\n}\n\nconst char *\nbprintf(const char *fmt, ...)\n{\n\tva_list ap;\n\tint ret;\n\n\tva_start(ap, fmt);\n\tret = evsnprintf(buf, sizeof(buf), fmt, ap);\n\tva_end(ap);\n\n\treturn (ret < 0) ? NULL : buf;\n}\n\nconst char *\nfmt_human(uintmax_t num, int base)\n{\n\tdouble scaled;\n\tsize_t i, prefixlen;\n\tconst char **prefix;\n\tconst char *prefix_1000[] = { \"\", \"k\", \"M\", \"G\", \"T\", \"P\", \"E\", \"Z\",\n\t                              \"Y\" };\n\tconst char *prefix_1024[] = { \"\", \"Ki\", \"Mi\", \"Gi\", \"Ti\", \"Pi\", \"Ei\",\n\t                              \"Zi\", \"Yi\" };\n\n\tswitch (base) {\n\tcase 1000:\n\t\tprefix = prefix_1000;\n\t\tprefixlen = LEN(prefix_1000);\n\t\tbreak;\n\tcase 1024:\n\t\tprefix = prefix_1024;\n\t\tprefixlen = LEN(prefix_1024);\n\t\tbreak;\n\tdefault:\n\t\twarn(\"fmt_human: Invalid base\");\n\t\treturn NULL;\n\t}\n\n\tscaled = num;\n\tfor (i = 0; i < prefixlen && scaled >= base; i++)\n\t\tscaled /= base;\n\n\treturn bprintf(\"%.1f %s\", scaled, prefix[i]);\n}\n\nint\npscanf(const char *path, const char *fmt, ...)\n{\n\tFILE *fp;\n\tva_list ap;\n\tint n;\n\n\tif (!(fp = fopen(path, \"r\"))) {\n\t\twarn(\"fopen '%s':\", path);\n\t\treturn -1;\n\t}\n\tva_start(ap, fmt);\n\tn = vfscanf(fp, fmt, ap);\n\tva_end(ap);\n\tfclose(fp);\n\n\treturn (n == EOF) ? -1 : n;\n}\n\nint\nlscanf(FILE *fp, const char *key, const char *fmt, void *res)\n{\n\t\tint n;\n\t\tchar line[256];\n\n\t\tn = -1;\n\t\twhile (fgets(line, sizeof(line), fp))\n\t\t\tif (strncmp(line, key, strlen(key)) == 0) {\n\t\t\t\tn = sscanf(line + strlen(key), fmt, res);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\trewind(fp);\n\t\treturn (n == 1) ? 1 : -1;\n}\n"
  },
  {
    "path": "util.h",
    "content": "/* See LICENSE file for copyright and license details. */\n#include <stdint.h>\n#include <stdio.h>\n\nextern char buf[1024];\n\n#define LEN(x) (sizeof(x) / sizeof((x)[0]))\n\nextern char *argv0;\n\nvoid warn(const char *, ...);\nvoid die(const char *, ...);\n\nint esnprintf(char *str, size_t size, const char *fmt, ...);\nconst char *bprintf(const char *fmt, ...);\nconst char *fmt_human(uintmax_t num, int base);\nint pscanf(const char *path, const char *fmt, ...);\nint lscanf(FILE *fp, const char *key, const char *fmt, void *res);\n"
  }
]