diff --git a/.bashrc b/.bashrc index 13d8d90..8609176 100644 --- a/.bashrc +++ b/.bashrc @@ -10,7 +10,8 @@ export PATH="$JAVA_HOME/bin:$PATH" [[ $- != *i* ]] && return alias ls='ls --color=auto' -alias cclear="printf '\e[3J\e[H\e[2J'" +alias nohup='nohup > "${TMPDIR:-/tmp}/nohup.$USER.$$.out" 2>&1' +alias cclear="printf '\e[3J\e[H\e[2J'" # Doesn't work in st? Should clear the terminal completely alias v="nvim" alias sagentsource="source ~/.local/bin/sagent" alias rms="shred -uzn8" @@ -24,7 +25,7 @@ if command -v dnf &> /dev/null; then fi PS1='[\u@\h \W]\$ ' -# . "$HOME/.cargo/env" +. "$HOME/.cargo/env" p="$HOME/projects" ls="ls -Utp --color=auto" diff --git a/.xinitrc b/.xinitrc new file mode 100644 index 0000000..d6f5d77 --- /dev/null +++ b/.xinitrc @@ -0,0 +1,11 @@ +#!/bin/sh + +# Dark theme +export GTK_THEME=Adwaita:dark +export GDK_BACKEND=x11 +export QT_STYLE_OVERRIDE=Fusion +export XDG_CURRENT_DESKTOP=dwm +export XDG_SESSION_DESKTOP=dwm +export XDG_SESSION_TYPE=x11 + +exec dbus-run-session -- /usr/local/bin/dwm diff --git a/__once_setup.sh b/__once_setup.sh index 0ddb8d1..880610b 100755 --- a/__once_setup.sh +++ b/__once_setup.sh @@ -118,6 +118,8 @@ flatpak mask com.spotify.Client # spotify fix bash <(curl -sSL https://spotx-official.github.io/run.sh) -fh +chmod +x spotify +ln -s ~/.config/spotify ~/.local/bin # packer (nvim) git clone --depth 1 https://github.com/wbthomason/packer.nvim\ diff --git a/dconf/user b/dconf/user index 218f43f..96fab40 100644 Binary files a/dconf/user and b/dconf/user differ diff --git a/dwm-6.6/config.h b/dwm-6.6/config.h index 80694f7..fead8b3 100644 --- a/dwm-6.6/config.h +++ b/dwm-6.6/config.h @@ -1,11 +1,11 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static const unsigned int borderpx = 2; /* border pixel of windows */ +static const unsigned int borderpx = 3; /* border pixel of windows */ static const unsigned int snap = 32; /* snap pixel */ static const int showbar = 10; /* 0 means no bar */ -static const int topbar = 0; /* 0 means bottom bar */ -static const char *fonts[] = { "CommitMono:size=17" }; +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "CommitMono:size=15" }; static const char dmenufont[] = "CommitMono:size=17"; // static const char col_foreground[] = "#BCC4C9"; @@ -16,10 +16,10 @@ static const char dmenufont[] = "CommitMono:size=17"; // static const char col_norm_border[] = "#182221"; static const char col_foreground[] = "#788799"; -static const char col_foreground2[] = "#9AA3B2"; -static const char col_background[] = "#e5e6e8"; -static const char col_background2[] = "#CFCFD1"; -static const char col_sel_border[] = "#e5e6e8"; +static const char col_foreground2[] = "#8792A4"; +static const char col_background[] = "#e5e6e8"; +static const char col_background2[] = "#CFCFD1"; +static const char col_sel_border[] = "#f78ade"; static const char col_norm_border[] = "#5a6a7c"; static const char *colors[][3] = { @@ -58,7 +58,8 @@ static const char *const autostart[] = { // "nitrogen", "--set-zoom-fill", "/home/plky/.config/wallpaper/kirino.png", "--head=0", NULL, // "nitrogen", "--set-zoom-fill", "/home/plky/.config/wallpaper/kirino_win7.png", "--head=1", NULL, "nitrogen", "--restore", NULL, - "/home/plky/.config/dwmstat.sh", NULL, + // "/home/plky/.config/dwmstat.sh", NULL, + "slstatus", NULL, "redshift", "-l", "40.7:-74.0", "-t", "6500:3600", NULL, "xcompmgr", NULL, @@ -115,13 +116,15 @@ static const char *volmute[] = { "pactl", "set-sink-mute", "@DEFAULT_SINK@", " static const char *mplaypause[] = { "playerctl", "play-pause", NULL }; static const char *mnext[] = { "playerctl", "next", NULL }; static const char *mprev[] = { "playerctl", "previous", NULL }; -static const char *slock[] = {"slock", NULL}; +static const char *brightup[] = { "brightnessctl", "set", "+5%", NULL }; +static const char *brightdown[] = { "brightnessctl", "set", "5%-", NULL }; +// static const char *slock[] = { "slock", NULL }; static const Key keys[] = { /* modifier key function argument */ { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY|ShiftMask, XK_l, spawn, {.v = slock } }, + { MODKEY|ShiftMask, XK_l, spawn, SHCMD("cinnamon-screensaver-command --lock || slock") }, { MODKEY, XK_b, togglebar, {0} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, @@ -155,6 +158,9 @@ static const Key keys[] = { { MODKEY|ShiftMask, XK_q, quit, {0} }, { MODKEY, XK_f, togglefullscr, {0} }, + { 0, XF86XK_MonBrightnessDown, spawn, { .v = brightdown } }, + { 0, XF86XK_MonBrightnessUp, spawn, { .v = brightup } }, + { 0, XF86XK_AudioRaiseVolume, spawn, { .v = volup } }, { 0, XF86XK_AudioLowerVolume, spawn, { .v = voldown } }, { 0, XF86XK_AudioMute, spawn, { .v = volmute } }, diff --git a/dwm-6.6/drw.o b/dwm-6.6/drw.o new file mode 100644 index 0000000..23dd8c3 Binary files /dev/null and b/dwm-6.6/drw.o differ diff --git a/dwm-6.6/dwm b/dwm-6.6/dwm new file mode 100755 index 0000000..a7c3a29 Binary files /dev/null and b/dwm-6.6/dwm differ diff --git a/dwm-6.6/dwm.o b/dwm-6.6/dwm.o new file mode 100644 index 0000000..b7dd27f Binary files /dev/null and b/dwm-6.6/dwm.o differ diff --git a/dwm-6.6/util.o b/dwm-6.6/util.o new file mode 100644 index 0000000..670b10e Binary files /dev/null and b/dwm-6.6/util.o differ diff --git a/gtk-2.0/gtkfilechooser.ini b/gtk-2.0/gtkfilechooser.ini new file mode 100644 index 0000000..3869492 --- /dev/null +++ b/gtk-2.0/gtkfilechooser.ini @@ -0,0 +1,11 @@ +[Filechooser Settings] +LocationMode=path-bar +ShowHidden=false +ShowSizeColumn=true +GeometryX=570 +GeometryY=231 +GeometryWidth=780 +GeometryHeight=585 +SortColumn=name +SortOrder=ascending +StartupMode=recent diff --git a/nemo/desktop-metadata b/nemo/desktop-metadata index 653d88d..c8ba2a8 100644 --- a/nemo/desktop-metadata +++ b/nemo/desktop-metadata @@ -1,22 +1,22 @@ [desktop-monitor-0] nemo-icon-view-keep-aligned=true nemo-icon-view-auto-layout=true -nemo-icon-view-layout-timestamp=1769280641 +nemo-icon-view-layout-timestamp=1769287850 [trash] -nemo-icon-position-timestamp=1769281021 +nemo-icon-position-timestamp=1769287851 nemo-icon-position=91,229 monitor=0 icon-scale=1 [home] -nemo-icon-position-timestamp=1769281021 +nemo-icon-position-timestamp=1769287851 nemo-icon-position=91,129 monitor=0 icon-scale=1 [computer] -nemo-icon-position-timestamp=1769281021 +nemo-icon-position-timestamp=1769287851 nemo-icon-position=91,29 monitor=0 icon-scale=1 diff --git a/nitrogen/bg-saved.cfg b/nitrogen/bg-saved.cfg index 95dfe2c..17b9c57 100644 --- a/nitrogen/bg-saved.cfg +++ b/nitrogen/bg-saved.cfg @@ -1,9 +1,4 @@ -[xin_0] -file=/home/plky/.config/wallpaper/b*rs.png -mode=0 -bgcolor=#000000 - -[xin_1] -file=/home/plky/.config/wallpaper/white_sankarea.png +[xin_-1] +file=/home/c2ny/.config/wallpaper/columbina_sandrone.jpg mode=0 bgcolor=#000000 diff --git a/nitrogen/nitrogen.cfg b/nitrogen/nitrogen.cfg index 87ca8d7..16638db 100644 --- a/nitrogen/nitrogen.cfg +++ b/nitrogen/nitrogen.cfg @@ -1,12 +1,12 @@ [geometry] -posx=34 -posy=0 +posx=15 +posy=15 sizex=1886 -sizey=1016 +sizey=1012 [nitrogen] view=icon recurse=true sort=alpha icon_caps=false -dirs=/home/plky/.config/wallpaper; +dirs=/home/c2ny/.config/wallpaper; diff --git a/slstatus-1.1/LICENSE b/slstatus-1.1/LICENSE new file mode 100644 index 0000000..9fae663 --- /dev/null +++ b/slstatus-1.1/LICENSE @@ -0,0 +1,46 @@ +ISC License + +Copyright 2016-2025 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 Ivan J. +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-2012 Michael Buch +Copyright 2018 Ian Remmler +Copyright 2016-2019 Joerg Jung +Copyright 2019 Ryan Kes +Copyright 2019 Cem Keylan +Copyright 2019 Dimitris Papastamos +Copyright 2019-2022 Ingo Feinerer +Copyright 2020 Alexandre Ratchov +Copyright 2020 Mart Lubbers +Copyright 2020 Daniel Moch +Copyright 2022 Nickolas Raymond Kaczynski +Copyright 2022 Patrick Iacob +Copyright 2021-2022 Steven Ward +Copyright 2025 Joakim Sindholt +Copyright 2025 Al +Copyright 2025 sewn + +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/slstatus-1.1/Makefile b/slstatus-1.1/Makefile new file mode 100644 index 0000000..7a18274 --- /dev/null +++ b/slstatus-1.1/Makefile @@ -0,0 +1,69 @@ +# See LICENSE file for copyright and license details +# slstatus - suckless status monitor +.POSIX: + +include config.mk + +REQ = util +COM =\ + components/battery\ + components/cat\ + components/cpu\ + components/datetime\ + components/disk\ + components/entropy\ + components/hostname\ + components/ip\ + components/kernel_release\ + components/keyboard_indicators\ + components/keymap\ + components/load_avg\ + components/netspeeds\ + components/num_files\ + components/ram\ + components/run_command\ + components/swap\ + components/temperature\ + components/uptime\ + components/user\ + components/volume\ + components/wifi + +all: slstatus + +$(COM:=.o): config.mk $(REQ:=.h) slstatus.h +slstatus.o: slstatus.c slstatus.h arg.h config.h config.mk $(REQ:=.h) + +.c.o: + $(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $< + +config.h: + cp config.def.h $@ + +slstatus: slstatus.o $(COM:=.o) $(REQ:=.o) + $(CC) -o $@ $(LDFLAGS) $(COM:=.o) $(REQ:=.o) slstatus.o $(LDLIBS) + +clean: + rm -f slstatus slstatus.o $(COM:=.o) $(REQ:=.o) slstatus-${VERSION}.tar.gz + +dist: + rm -rf "slstatus-$(VERSION)" + mkdir -p "slstatus-$(VERSION)/components" + cp -R LICENSE Makefile README config.mk config.def.h \ + arg.h slstatus.h slstatus.c $(REQ:=.c) $(REQ:=.h) \ + slstatus.1 "slstatus-$(VERSION)" + cp -R $(COM:=.c) "slstatus-$(VERSION)/components" + tar -cf - "slstatus-$(VERSION)" | gzip -c > "slstatus-$(VERSION).tar.gz" + rm -rf "slstatus-$(VERSION)" + +install: all + mkdir -p "$(DESTDIR)$(PREFIX)/bin" + cp -f slstatus "$(DESTDIR)$(PREFIX)/bin" + chmod 755 "$(DESTDIR)$(PREFIX)/bin/slstatus" + mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" + cp -f slstatus.1 "$(DESTDIR)$(MANPREFIX)/man1" + chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" + +uninstall: + rm -f "$(DESTDIR)$(PREFIX)/bin/slstatus" + rm -f "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" diff --git a/slstatus-1.1/README b/slstatus-1.1/README new file mode 100644 index 0000000..4d592bb --- /dev/null +++ b/slstatus-1.1/README @@ -0,0 +1,65 @@ +slstatus - suckless status +========================== +slstatus is a small tool for providing system status information to other +programs over the EWMH property of the root window (used by dwm(1)) or +standard input/output. It is designed to be as efficient as possible by +only issuing the minimum of system calls required. + + +Features +-------- +- Battery percentage/state/time left +- Cat (read file) +- CPU usage +- CPU frequency +- Custom shell commands +- Date and time +- Disk status (free storage, percentage, total storage and used storage) +- Available entropy +- Username/GID/UID +- Hostname +- IP address (IPv4 and IPv6), interface status +- Kernel version +- Keyboard indicators +- Keymap +- Load average +- Network speeds (RX and TX) +- Number of files in a directory (hint: Maildir) +- Memory status (free memory, percentage, total memory and used memory) +- Swap status (free swap, percentage, total swap and used swap) +- Temperature +- Uptime +- Volume percentage +- WiFi signal percentage and ESSID + + +Requirements +------------ +Currently slstatus works on FreeBSD, Linux and OpenBSD. +In order to build slstatus you need the Xlib header files. + +- For volume percentage on Linux the kernel module `snd-mixer-oss` must be + loaded. +- For volume percentage on FreeBSD, `sndio` must be installed. + + +Installation +------------ +Edit config.mk to match your local setup (slstatus is installed into the +/usr/local namespace by default). + +Afterwards enter the following command to build and install slstatus (if +necessary as root): + + make clean install + + +Running slstatus +---------------- +See the man page for details. + + +Configuration +------------- +slstatus can be customized by creating a custom config.h and (re)compiling the +source code. This keeps it fast, secure and simple. diff --git a/slstatus-1.1/arg.h b/slstatus-1.1/arg.h new file mode 100644 index 0000000..5f1f408 --- /dev/null +++ b/slstatus-1.1/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/slstatus-1.1/components/battery.c b/slstatus-1.1/components/battery.c new file mode 100644 index 0000000..1c753f9 --- /dev/null +++ b/slstatus-1.1/components/battery.c @@ -0,0 +1,247 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +#if defined(__linux__) +/* + * https://www.kernel.org/doc/html/latest/power/power_supply_class.html + */ + #include + #include + #include + + #define POWER_SUPPLY_CAPACITY "/sys/class/power_supply/%s/capacity" + #define POWER_SUPPLY_STATUS "/sys/class/power_supply/%s/status" + #define POWER_SUPPLY_CHARGE "/sys/class/power_supply/%s/charge_now" + #define POWER_SUPPLY_ENERGY "/sys/class/power_supply/%s/energy_now" + #define POWER_SUPPLY_CURRENT "/sys/class/power_supply/%s/current_now" + #define POWER_SUPPLY_POWER "/sys/class/power_supply/%s/power_now" + + static const char * + pick(const char *bat, const char *f1, const char *f2, char *path, + size_t length) + { + if (esnprintf(path, length, f1, bat) > 0 && + access(path, R_OK) == 0) + return f1; + + if (esnprintf(path, length, f2, bat) > 0 && + access(path, R_OK) == 0) + return f2; + + return NULL; + } + + const char * + battery_perc(const char *bat) + { + int cap_perc; + char path[PATH_MAX]; + + if (esnprintf(path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0) + return NULL; + if (pscanf(path, "%d", &cap_perc) != 1) + return NULL; + + return bprintf("%d", cap_perc); + } + + const char * + battery_state(const char *bat) + { + static struct { + char *state; + char *symbol; + } map[] = { + { "Charging", "+" }, + { "Discharging", "-" }, + { "Full", "o" }, + { "Not charging", "o" }, + }; + size_t i; + char path[PATH_MAX], state[12]; + + if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) + return NULL; + if (pscanf(path, "%12[a-zA-Z ]", state) != 1) + return NULL; + + for (i = 0; i < LEN(map); i++) + if (!strcmp(map[i].state, state)) + break; + + return (i == LEN(map)) ? "?" : map[i].symbol; + } + + const char * + battery_remaining(const char *bat) + { + uintmax_t charge_now, current_now, m, h; + double timeleft; + char path[PATH_MAX], state[12]; + + if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) + return NULL; + if (pscanf(path, "%12[a-zA-Z ]", state) != 1) + return NULL; + + if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path, + sizeof(path)) || + pscanf(path, "%ju", &charge_now) < 0) + return NULL; + + if (!strcmp(state, "Discharging")) { + if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path, + sizeof(path)) || + pscanf(path, "%ju", ¤t_now) < 0) + return NULL; + + if (current_now == 0) + return NULL; + + timeleft = (double)charge_now / (double)current_now; + h = timeleft; + m = (timeleft - (double)h) * 60; + + return bprintf("%juh %jum", h, m); + } + + return ""; + } +#elif defined(__OpenBSD__) + #include + #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; + unsigned int h, m; + + if (load_apm_power_info(&apm_info)) { + if (apm_info.ac_state != APM_AC_ON) { + h = apm_info.minutes_left / 60; + m = apm_info.minutes_left % 60; + return bprintf("%uh %02um", h, m); + } else { + return ""; + } + } + + return NULL; + } +#elif defined(__FreeBSD__) + #include + + #define BATTERY_LIFE "hw.acpi.battery.life" + #define BATTERY_STATE "hw.acpi.battery.state" + #define BATTERY_TIME "hw.acpi.battery.time" + + const char * + battery_perc(const char *unused) + { + int cap_perc; + size_t len; + + len = sizeof(cap_perc); + if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len) + return NULL; + + return bprintf("%d", cap_perc); + } + + const char * + battery_state(const char *unused) + { + int state; + size_t len; + + len = sizeof(state); + if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len) + return NULL; + + switch (state) { + case 0: /* FALLTHROUGH */ + case 2: + return "+"; + case 1: + return "-"; + default: + return "?"; + } + } + + const char * + battery_remaining(const char *unused) + { + int rem; + size_t len; + + len = sizeof(rem); + if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len + || rem < 0) + return NULL; + + return bprintf("%uh %02um", rem / 60, rem % 60); + } +#endif diff --git a/slstatus-1.1/components/cat.c b/slstatus-1.1/components/cat.c new file mode 100644 index 0000000..07944cc --- /dev/null +++ b/slstatus-1.1/components/cat.c @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +cat(const char *path) +{ + char *f; + FILE *fp; + + if (!(fp = fopen(path, "r"))) { + warn("fopen '%s':", path); + return NULL; + } + + f = fgets(buf, sizeof(buf) - 1, fp); + if (fclose(fp) < 0) { + warn("fclose '%s':", path); + return NULL; + } + if (!f) + return NULL; + + if ((f = strrchr(buf, '\n'))) + f[0] = '\0'; + + return buf[0] ? buf : NULL; +} + diff --git a/slstatus-1.1/components/cpu.c b/slstatus-1.1/components/cpu.c new file mode 100644 index 0000000..d0d03c7 --- /dev/null +++ b/slstatus-1.1/components/cpu.c @@ -0,0 +1,157 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +#if defined(__linux__) + #define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" + + const char * + cpu_freq(const char *unused) + { + uintmax_t freq; + + /* in kHz */ + if (pscanf(CPU_FREQ, "%ju", &freq) != 1) + return NULL; + + return fmt_human(freq * 1000, 1000); + } + + const char * + cpu_perc(const char *unused) + { + static long double a[7]; + long double b[7], sum; + + memcpy(b, a, sizeof(b)); + /* cpu user nice system idle iowait irq softirq */ + if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf", + &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) + != 7) + return NULL; + + if (b[0] == 0) + return NULL; + + sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) - + (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]); + + if (sum == 0) + return NULL; + + return bprintf("%d", (int)(100 * + ((b[0] + b[1] + b[2] + b[5] + b[6]) - + (a[0] + a[1] + a[2] + a[5] + a[6])) / sum)); + } +#elif defined(__OpenBSD__) + #include + #include + #include + + const char * + cpu_freq(const char *unused) + { + int freq, mib[2]; + size_t size; + + mib[0] = CTL_HW; + mib[1] = HW_CPUSPEED; + + size = sizeof(freq); + + /* in MHz */ + if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { + warn("sysctl 'HW_CPUSPEED':"); + return NULL; + } + + return fmt_human(freq * 1E6, 1000); + } + + const char * + cpu_perc(const char *unused) + { + int mib[2]; + static uintmax_t a[CPUSTATES]; + uintmax_t b[CPUSTATES], sum; + size_t size; + + mib[0] = CTL_KERN; + mib[1] = KERN_CPTIME; + + size = sizeof(a); + + memcpy(b, a, sizeof(b)); + if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) { + warn("sysctl 'KERN_CPTIME':"); + return NULL; + } + if (b[0] == 0) + return NULL; + + sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - + (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); + + if (sum == 0) + return NULL; + + return bprintf("%d", 100 * + ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + + a[CP_INTR]) - + (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + + b[CP_INTR])) / sum); + } +#elif defined(__FreeBSD__) + #include + #include + #include + + const char * + cpu_freq(const char *unused) + { + int freq; + size_t size; + + size = sizeof(freq); + /* in MHz */ + if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) { + warn("sysctlbyname 'hw.clockrate':"); + return NULL; + } + + return fmt_human(freq * 1E6, 1000); + } + + const char * + cpu_perc(const char *unused) + { + size_t size; + static long a[CPUSTATES]; + long b[CPUSTATES], sum; + + size = sizeof(a); + memcpy(b, a, sizeof(b)); + if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) { + warn("sysctlbyname 'kern.cp_time':"); + return NULL; + } + if (b[0] == 0) + return NULL; + + sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - + (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); + + if (sum == 0) + return NULL; + + return bprintf("%d", 100 * + ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + + a[CP_INTR]) - + (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + + b[CP_INTR])) / sum); + } +#endif diff --git a/slstatus-1.1/components/datetime.c b/slstatus-1.1/components/datetime.c new file mode 100644 index 0000000..5b10daf --- /dev/null +++ b/slstatus-1.1/components/datetime.c @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +datetime(const char *fmt) +{ + time_t t; + + t = time(NULL); + if (!strftime(buf, sizeof(buf), fmt, localtime(&t))) { + warn("strftime: Result string exceeds buffer size"); + return NULL; + } + + return buf; +} diff --git a/slstatus-1.1/components/disk.c b/slstatus-1.1/components/disk.c new file mode 100644 index 0000000..e19a693 --- /dev/null +++ b/slstatus-1.1/components/disk.c @@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +disk_free(const char *path) +{ + struct statvfs fs; + + if (statvfs(path, &fs) < 0) { + warn("statvfs '%s':", path); + return NULL; + } + + return fmt_human(fs.f_frsize * fs.f_bavail, 1024); +} + +const char * +disk_perc(const char *path) +{ + struct statvfs fs; + + if (statvfs(path, &fs) < 0) { + warn("statvfs '%s':", path); + return NULL; + } + + return bprintf("%d", (int)(100 * + (1 - ((double)fs.f_bavail / (double)fs.f_blocks)))); +} + +const char * +disk_total(const char *path) +{ + struct statvfs fs; + + if (statvfs(path, &fs) < 0) { + warn("statvfs '%s':", path); + return NULL; + } + + return fmt_human(fs.f_frsize * fs.f_blocks, 1024); +} + +const char * +disk_used(const char *path) +{ + struct statvfs fs; + + if (statvfs(path, &fs) < 0) { + warn("statvfs '%s':", path); + return NULL; + } + + return fmt_human(fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024); +} diff --git a/slstatus-1.1/components/entropy.c b/slstatus-1.1/components/entropy.c new file mode 100644 index 0000000..65010b0 --- /dev/null +++ b/slstatus-1.1/components/entropy.c @@ -0,0 +1,29 @@ +/* See LICENSE file for copyright and license details. */ +#include "../slstatus.h" +#if defined(__linux__) + #include + #include + + #include "../util.h" + + #define ENTROPY_AVAIL "/proc/sys/kernel/random/entropy_avail" + + const char * + entropy(const char *unused) + { + uintmax_t num; + + if (pscanf(ENTROPY_AVAIL, "%ju", &num) != 1) + return NULL; + + return bprintf("%ju", num); + } +#elif defined(__OpenBSD__) | defined(__FreeBSD__) + const char * + entropy(const char *unused) + { + // https://www.unicode.org/charts/PDF/U2200.pdf + /* Unicode Character 'INFINITY' (U+221E) */ + return "\u221E"; + } +#endif diff --git a/slstatus-1.1/components/hostname.c b/slstatus-1.1/components/hostname.c new file mode 100644 index 0000000..dab8b63 --- /dev/null +++ b/slstatus-1.1/components/hostname.c @@ -0,0 +1,17 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +hostname(const char *unused) +{ + if (gethostname(buf, sizeof(buf)) < 0) { + warn("gethostbyname:"); + return NULL; + } + + return buf; +} diff --git a/slstatus-1.1/components/ip.c b/slstatus-1.1/components/ip.c new file mode 100644 index 0000000..2cdad46 --- /dev/null +++ b/slstatus-1.1/components/ip.c @@ -0,0 +1,87 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#if defined(__OpenBSD__) + #include + #include +#elif defined(__FreeBSD__) + #include + #include +#endif + +#include "../slstatus.h" +#include "../util.h" + +static const char * +ip(const char *interface, unsigned short sa_family) +{ + struct ifaddrs *ifaddr, *ifa; + int s; + char host[NI_MAXHOST]; + + if (getifaddrs(&ifaddr) < 0) { + warn("getifaddrs:"); + return NULL; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) + continue; + + s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), + host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (!strcmp(ifa->ifa_name, interface) && + (ifa->ifa_addr->sa_family == sa_family)) { + freeifaddrs(ifaddr); + if (s != 0) { + warn("getnameinfo: %s", gai_strerror(s)); + return NULL; + } + return bprintf("%s", host); + } + } + + freeifaddrs(ifaddr); + + return NULL; +} + +const char * +ipv4(const char *interface) +{ + return ip(interface, AF_INET); +} + +const char * +ipv6(const char *interface) +{ + return ip(interface, AF_INET6); +} + +const char * +up(const char *interface) +{ + struct ifaddrs *ifaddr, *ifa; + + if (getifaddrs(&ifaddr) < 0) { + warn("getifaddrs:"); + return NULL; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) + continue; + + if (!strcmp(ifa->ifa_name, interface)) { + freeifaddrs(ifaddr); + return ifa->ifa_flags & IFF_UP ? "up" : "down"; + } + } + + freeifaddrs(ifaddr); + + return NULL; +} diff --git a/slstatus-1.1/components/kernel_release.c b/slstatus-1.1/components/kernel_release.c new file mode 100644 index 0000000..36a6a44 --- /dev/null +++ b/slstatus-1.1/components/kernel_release.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +kernel_release(const char *unused) +{ + struct utsname udata; + + if (uname(&udata) < 0) { + warn("uname:"); + return NULL; + } + + return bprintf("%s", udata.release); +} diff --git a/slstatus-1.1/components/keyboard_indicators.c b/slstatus-1.1/components/keyboard_indicators.c new file mode 100644 index 0000000..5f62bb7 --- /dev/null +++ b/slstatus-1.1/components/keyboard_indicators.c @@ -0,0 +1,50 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +/* + * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num + * lock, each optionally followed by '?', in the order of indicators desired. + * If followed by '?', the letter with case preserved is included in the output + * if the corresponding indicator is on. Otherwise, the letter is always + * included, lowercase when off and uppercase when on. + */ +const char * +keyboard_indicators(const char *fmt) +{ + Display *dpy; + XKeyboardState state; + size_t fmtlen, i, n; + int togglecase, isset; + char key; + + if (!(dpy = XOpenDisplay(NULL))) { + warn("XOpenDisplay: Failed to open display"); + return NULL; + } + XGetKeyboardControl(dpy, &state); + XCloseDisplay(dpy); + + fmtlen = strnlen(fmt, 4); + for (i = n = 0; i < fmtlen; i++) { + key = tolower(fmt[i]); + if (key != 'c' && key != 'n') + continue; + + togglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?'); + isset = (state.led_mask & (1 << (key == 'n'))); + + if (togglecase) + buf[n++] = isset ? toupper(key) : key; + else if (isset) + buf[n++] = fmt[i]; + } + + buf[n] = 0; + return buf; +} diff --git a/slstatus-1.1/components/keymap.c b/slstatus-1.1/components/keymap.c new file mode 100644 index 0000000..22224f3 --- /dev/null +++ b/slstatus-1.1/components/keymap.c @@ -0,0 +1,86 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +static int +valid_layout_or_variant(char *sym) +{ + size_t i; + /* invalid symbols from xkb rules config */ + static const char *invalid[] = { "evdev", "inet", "pc", "base" }; + + for (i = 0; i < LEN(invalid); i++) + if (!strncmp(sym, invalid[i], strlen(invalid[i]))) + return 0; + + return 1; +} + +static char * +get_layout(char *syms, int grp_num) +{ + char *tok, *layout; + int grp; + + layout = NULL; + tok = strtok(syms, "+:_"); + for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:_")) { + if (!valid_layout_or_variant(tok)) { + continue; + } else if (strlen(tok) == 1 && isdigit(tok[0])) { + /* ignore :2, :3, :4 (additional layout groups) */ + continue; + } + layout = tok; + grp++; + } + + return layout; +} + +const char * +keymap(const char *unused) +{ + Display *dpy; + XkbDescRec *desc; + XkbStateRec state; + char *symbols; + const char *layout; + + layout = NULL; + + if (!(dpy = XOpenDisplay(NULL))) { + warn("XOpenDisplay: Failed to open display"); + return NULL; + } + if (!(desc = XkbAllocKeyboard())) { + warn("XkbAllocKeyboard: Failed to allocate keyboard"); + goto end; + } + if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) { + warn("XkbGetNames: Failed to retrieve key symbols"); + goto end; + } + if (XkbGetState(dpy, XkbUseCoreKbd, &state)) { + warn("XkbGetState: Failed to retrieve keyboard state"); + goto end; + } + if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) { + warn("XGetAtomName: Failed to get atom name"); + goto end; + } + layout = bprintf("%s", get_layout(symbols, state.group)); + XFree(symbols); +end: + XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); + if (XCloseDisplay(dpy)) + warn("XCloseDisplay: Failed to close display"); + + return layout; +} diff --git a/slstatus-1.1/components/load_avg.c b/slstatus-1.1/components/load_avg.c new file mode 100644 index 0000000..f278a40 --- /dev/null +++ b/slstatus-1.1/components/load_avg.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +load_avg(const char *unused) +{ + double avgs[3]; + + if (getloadavg(avgs, 3) < 0) { + warn("getloadavg: Failed to obtain load average"); + return NULL; + } + + return bprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]); +} diff --git a/slstatus-1.1/components/netspeeds.c b/slstatus-1.1/components/netspeeds.c new file mode 100644 index 0000000..cde6fa9 --- /dev/null +++ b/slstatus-1.1/components/netspeeds.c @@ -0,0 +1,129 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +#if defined(__linux__) + #include + + #define NET_RX_BYTES "/sys/class/net/%s/statistics/rx_bytes" + #define NET_TX_BYTES "/sys/class/net/%s/statistics/tx_bytes" + + const char * + netspeed_rx(const char *interface) + { + uintmax_t oldrxbytes; + static uintmax_t rxbytes; + extern const unsigned int interval; + char path[PATH_MAX]; + + oldrxbytes = rxbytes; + + if (esnprintf(path, sizeof(path), NET_RX_BYTES, interface) < 0) + return NULL; + if (pscanf(path, "%ju", &rxbytes) != 1) + return NULL; + if (oldrxbytes == 0) + return NULL; + + return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, + 1024); + } + + const char * + netspeed_tx(const char *interface) + { + uintmax_t oldtxbytes; + static uintmax_t txbytes; + extern const unsigned int interval; + char path[PATH_MAX]; + + oldtxbytes = txbytes; + + if (esnprintf(path, sizeof(path), NET_TX_BYTES, interface) < 0) + return NULL; + if (pscanf(path, "%ju", &txbytes) != 1) + return NULL; + if (oldtxbytes == 0) + return NULL; + + return fmt_human((txbytes - oldtxbytes) * 1000 / interval, + 1024); + } +#elif defined(__OpenBSD__) | defined(__FreeBSD__) + #include + #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) < 0) { + warn("getifaddrs failed"); + return NULL; + } + rxbytes = 0; + for (ifa = ifal; ifa; ifa = ifa->ifa_next) + if (!strcmp(ifa->ifa_name, interface) && + (ifd = (struct if_data *)ifa->ifa_data)) + rxbytes += ifd->ifi_ibytes, if_ok = 1; + + freeifaddrs(ifal); + if (!if_ok) { + warn("reading 'if_data' failed"); + return NULL; + } + if (oldrxbytes == 0) + return NULL; + + return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, + 1024); + } + + const char * + netspeed_tx(const char *interface) + { + struct ifaddrs *ifal, *ifa; + struct if_data *ifd; + uintmax_t oldtxbytes; + static uintmax_t txbytes; + extern const unsigned int interval; + int if_ok = 0; + + oldtxbytes = txbytes; + + if (getifaddrs(&ifal) < 0) { + warn("getifaddrs failed"); + return NULL; + } + txbytes = 0; + for (ifa = ifal; ifa; ifa = ifa->ifa_next) + if (!strcmp(ifa->ifa_name, interface) && + (ifd = (struct if_data *)ifa->ifa_data)) + txbytes += ifd->ifi_obytes, if_ok = 1; + + freeifaddrs(ifal); + if (!if_ok) { + warn("reading 'if_data' failed"); + return NULL; + } + if (oldtxbytes == 0) + return NULL; + + return fmt_human((txbytes - oldtxbytes) * 1000 / interval, + 1024); + } +#endif diff --git a/slstatus-1.1/components/num_files.c b/slstatus-1.1/components/num_files.c new file mode 100644 index 0000000..df0acd1 --- /dev/null +++ b/slstatus-1.1/components/num_files.c @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +num_files(const char *path) +{ + struct dirent *dp; + DIR *dir; + int num; + + if (!(dir = opendir(path))) { + warn("opendir '%s':", path); + return NULL; + } + + num = 0; + while ((dp = readdir(dir))) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; /* skip self and parent */ + + num++; + } + + closedir(dir); + + return bprintf("%d", num); +} diff --git a/slstatus-1.1/components/ram.c b/slstatus-1.1/components/ram.c new file mode 100644 index 0000000..15c4b74 --- /dev/null +++ b/slstatus-1.1/components/ram.c @@ -0,0 +1,212 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include "../slstatus.h" +#include "../util.h" + +#if defined(__linux__) + #include + + const char * + ram_free(const char *unused) + { + uintmax_t free; + + if (pscanf("/proc/meminfo", + "MemTotal: %ju kB\n" + "MemFree: %ju kB\n" + "MemAvailable: %ju kB\n", + &free, &free, &free) != 3) + return NULL; + + return fmt_human(free * 1024, 1024); + } + + const char * + ram_perc(const char *unused) + { + uintmax_t total, free, buffers, cached; + int percent; + + if (pscanf("/proc/meminfo", + "MemTotal: %ju kB\n" + "MemFree: %ju kB\n" + "MemAvailable: %ju kB\n" + "Buffers: %ju kB\n" + "Cached: %ju kB\n", + &total, &free, &buffers, &buffers, &cached) != 5) + return NULL; + + if (total == 0) + return NULL; + + percent = 100 * ((total - free) - (buffers + cached)) / total; + return bprintf("%d", percent); + } + + const char * + ram_total(const char *unused) + { + uintmax_t total; + + if (pscanf("/proc/meminfo", "MemTotal: %ju kB\n", &total) + != 1) + return NULL; + + return fmt_human(total * 1024, 1024); + } + + const char * + ram_used(const char *unused) + { + uintmax_t total, free, buffers, cached, used; + + if (pscanf("/proc/meminfo", + "MemTotal: %ju kB\n" + "MemFree: %ju kB\n" + "MemAvailable: %ju kB\n" + "Buffers: %ju kB\n" + "Cached: %ju kB\n", + &total, &free, &buffers, &buffers, &cached) != 5) + return NULL; + + used = (total - free - buffers - cached); + return fmt_human(used * 1024, 1024); + } +#elif defined(__OpenBSD__) + #include + #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(const char *unused) + { + struct uvmexp uvmexp; + int free_pages; + + if (!load_uvmexp(&uvmexp)) + return NULL; + + free_pages = uvmexp.npages - uvmexp.active; + return fmt_human(pagetok(free_pages, uvmexp.pageshift) * + 1024, 1024); + } + + const char * + ram_perc(const char *unused) + { + struct uvmexp uvmexp; + int percent; + + if (!load_uvmexp(&uvmexp)) + return NULL; + + percent = uvmexp.active * 100 / uvmexp.npages; + return bprintf("%d", percent); + } + + const char * + ram_total(const char *unused) + { + struct uvmexp uvmexp; + + if (!load_uvmexp(&uvmexp)) + return NULL; + + return fmt_human(pagetok(uvmexp.npages, + uvmexp.pageshift) * 1024, 1024); + } + + const char * + ram_used(const char *unused) + { + struct uvmexp uvmexp; + + if (!load_uvmexp(&uvmexp)) + return NULL; + + return fmt_human(pagetok(uvmexp.active, + uvmexp.pageshift) * 1024, 1024); + } +#elif defined(__FreeBSD__) + #include + #include + #include + #include + + const char * + ram_free(const char *unused) { + struct vmtotal vm_stats; + int mib[] = {CTL_VM, VM_TOTAL}; + size_t len; + + len = sizeof(struct vmtotal); + if (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0 + || !len) + return NULL; + + return fmt_human(vm_stats.t_free * getpagesize(), 1024); + } + + const char * + ram_total(const char *unused) { + unsigned int npages; + size_t len; + + len = sizeof(npages); + if (sysctlbyname("vm.stats.vm.v_page_count", + &npages, &len, NULL, 0) < 0 || !len) + return NULL; + + return fmt_human(npages * getpagesize(), 1024); + } + + const char * + ram_perc(const char *unused) { + unsigned int npages; + unsigned int active; + size_t len; + + len = sizeof(npages); + if (sysctlbyname("vm.stats.vm.v_page_count", + &npages, &len, NULL, 0) < 0 || !len) + return NULL; + + if (sysctlbyname("vm.stats.vm.v_active_count", + &active, &len, NULL, 0) < 0 || !len) + return NULL; + + return bprintf("%d", active * 100 / npages); + } + + const char * + ram_used(const char *unused) { + unsigned int active; + size_t len; + + len = sizeof(active); + if (sysctlbyname("vm.stats.vm.v_active_count", + &active, &len, NULL, 0) < 0 || !len) + return NULL; + + return fmt_human(active * getpagesize(), 1024); + } +#endif diff --git a/slstatus-1.1/components/run_command.c b/slstatus-1.1/components/run_command.c new file mode 100644 index 0000000..93bf6da --- /dev/null +++ b/slstatus-1.1/components/run_command.c @@ -0,0 +1,31 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +run_command(const char *cmd) +{ + char *p; + FILE *fp; + + if (!(fp = popen(cmd, "r"))) { + warn("popen '%s':", cmd); + return NULL; + } + + p = fgets(buf, sizeof(buf) - 1, fp); + if (pclose(fp) < 0) { + warn("pclose '%s':", cmd); + return NULL; + } + if (!p) + return NULL; + + if ((p = strrchr(buf, '\n'))) + p[0] = '\0'; + + return buf[0] ? buf : NULL; +} diff --git a/slstatus-1.1/components/swap.c b/slstatus-1.1/components/swap.c new file mode 100644 index 0000000..f270d93 --- /dev/null +++ b/slstatus-1.1/components/swap.c @@ -0,0 +1,274 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +#if defined(__linux__) + static int + get_swap_info(long *s_total, long *s_free, long *s_cached) + { + FILE *fp; + struct { + const char *name; + const size_t len; + long *var; + } ent[] = { + { "SwapTotal", sizeof("SwapTotal") - 1, s_total }, + { "SwapFree", sizeof("SwapFree") - 1, s_free }, + { "SwapCached", sizeof("SwapCached") - 1, s_cached }, + }; + size_t line_len = 0, i, left; + char *line = NULL; + + /* get number of fields we want to extract */ + for (i = 0, left = 0; i < LEN(ent); i++) + if (ent[i].var) + left++; + + if (!(fp = fopen("/proc/meminfo", "r"))) { + warn("fopen '/proc/meminfo':"); + return 1; + } + + /* read file line by line and extract field information */ + while (left > 0 && getline(&line, &line_len, fp) >= 0) { + for (i = 0; i < LEN(ent); i++) { + if (ent[i].var && + !strncmp(line, ent[i].name, ent[i].len)) { + sscanf(line + ent[i].len + 1, + "%ld kB\n", ent[i].var); + left--; + break; + } + } + } + free(line); + if (ferror(fp)) { + warn("getline '/proc/meminfo':"); + return 1; + } + + fclose(fp); + return 0; + } + + const char * + swap_free(const char *unused) + { + long free; + + if (get_swap_info(NULL, &free, NULL)) + return NULL; + + return fmt_human(free * 1024, 1024); + } + + const char * + swap_perc(const char *unused) + { + long total, free, cached; + + if (get_swap_info(&total, &free, &cached) || total == 0) + return NULL; + + return bprintf("%d", 100 * (total - free - cached) / total); + } + + const char * + swap_total(const char *unused) + { + long total; + + if (get_swap_info(&total, NULL, NULL)) + return NULL; + + return fmt_human(total * 1024, 1024); + } + + const char * + swap_used(const char *unused) + { + long total, free, cached; + + if (get_swap_info(&total, &free, &cached)) + return NULL; + + return fmt_human((total - free - cached) * 1024, 1024); + } +#elif defined(__OpenBSD__) + #include + #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(const char *unused) + { + int total, used; + + if (getstats(&total, &used)) + return NULL; + + return fmt_human((total - used) * 1024, 1024); + } + + const char * + swap_perc(const char *unused) + { + int total, used; + + if (getstats(&total, &used)) + return NULL; + + if (total == 0) + return NULL; + + return bprintf("%d", 100 * used / total); + } + + const char * + swap_total(const char *unused) + { + int total, used; + + if (getstats(&total, &used)) + return NULL; + + return fmt_human(total * 1024, 1024); + } + + const char * + swap_used(const char *unused) + { + int total, used; + + if (getstats(&total, &used)) + return NULL; + + return fmt_human(used * 1024, 1024); + } +#elif defined(__FreeBSD__) + #include + #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 */) < 0) { + warn("kvm_getswapinfo:"); + kvm_close(kd); + return 0; + } + + kvm_close(kd); + return 1; + } + + const char * + swap_free(const char *unused) + { + struct kvm_swap swap_info[1]; + long used, total; + + if (!getswapinfo(swap_info, 1)) + return NULL; + + total = swap_info[0].ksw_total; + used = swap_info[0].ksw_used; + + return fmt_human((total - used) * getpagesize(), 1024); + } + + const char * + swap_perc(const char *unused) + { + struct kvm_swap swap_info[1]; + long used, total; + + if (!getswapinfo(swap_info, 1)) + return NULL; + + total = swap_info[0].ksw_total; + used = swap_info[0].ksw_used; + + return bprintf("%d", used * 100 / total); + } + + const char * + swap_total(const char *unused) + { + struct kvm_swap swap_info[1]; + long total; + + if (!getswapinfo(swap_info, 1)) + return NULL; + + total = swap_info[0].ksw_total; + + return fmt_human(total * getpagesize(), 1024); + } + + const char * + swap_used(const char *unused) + { + struct kvm_swap swap_info[1]; + long used; + + if (!getswapinfo(swap_info, 1)) + return NULL; + + used = swap_info[0].ksw_used; + + return fmt_human(used * getpagesize(), 1024); + } +#endif diff --git a/slstatus-1.1/components/temperature.c b/slstatus-1.1/components/temperature.c new file mode 100644 index 0000000..7cf1394 --- /dev/null +++ b/slstatus-1.1/components/temperature.c @@ -0,0 +1,73 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include "../slstatus.h" +#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 + + #define ACPI_TEMP "hw.acpi.thermal.%s.temperature" + + const char * + temp(const char *zone) + { + char buf[256]; + int temp; + size_t len; + + len = sizeof(temp); + snprintf(buf, sizeof(buf), ACPI_TEMP, zone); + if (sysctlbyname(buf, &temp, &len, NULL, 0) < 0 + || !len) + return NULL; + + /* kelvin to decimal celcius */ + return bprintf("%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10)); + } +#endif diff --git a/slstatus-1.1/components/uptime.c b/slstatus-1.1/components/uptime.c new file mode 100644 index 0000000..6227f73 --- /dev/null +++ b/slstatus-1.1/components/uptime.c @@ -0,0 +1,34 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +#if defined(CLOCK_BOOTTIME) + #define UPTIME_FLAG CLOCK_BOOTTIME +#elif defined(CLOCK_UPTIME) + #define UPTIME_FLAG CLOCK_UPTIME +#else + #define UPTIME_FLAG CLOCK_MONOTONIC +#endif + +const char * +uptime(const char *unused) +{ + char warn_buf[256]; + uintmax_t h, m; + struct timespec uptime; + + if (clock_gettime(UPTIME_FLAG, &uptime) < 0) { + snprintf(warn_buf, sizeof(warn_buf), "clock_gettime %d", UPTIME_FLAG); + warn(warn_buf); + return NULL; + } + + h = uptime.tv_sec / 3600; + m = uptime.tv_sec % 3600 / 60; + + return bprintf("%juh %jum", h, m); +} diff --git a/slstatus-1.1/components/user.c b/slstatus-1.1/components/user.c new file mode 100644 index 0000000..3517495 --- /dev/null +++ b/slstatus-1.1/components/user.c @@ -0,0 +1,33 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +const char * +gid(const char *unused) +{ + return bprintf("%d", getgid()); +} + +const char * +username(const char *unused) +{ + struct passwd *pw; + + if (!(pw = getpwuid(geteuid()))) { + warn("getpwuid '%d':", geteuid()); + return NULL; + } + + return bprintf("%s", pw->pw_name); +} + +const char * +uid(const char *unused) +{ + return bprintf("%d", geteuid()); +} diff --git a/slstatus-1.1/components/volume.c b/slstatus-1.1/components/volume.c new file mode 100644 index 0000000..6cec556 --- /dev/null +++ b/slstatus-1.1/components/volume.c @@ -0,0 +1,219 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +#if defined(__OpenBSD__) | defined(__FreeBSD__) + #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(); + initialized = 0; + return NULL; + } + } + } + + value = 100; + LIST_FOREACH(c, &controls, next) { + if (c->type == CTRL_MUTE && c->val == 1) + value = 0; + else if (c->type == CTRL_LEVEL) { + v = (c->val * 100 + c->maxval / 2) / c->maxval; + /* For multiple channels return the minimum. */ + if (v < value) + value = v; + } + } + + return bprintf("%d", value); + } +#else + #include + + 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/slstatus-1.1/components/wifi.c b/slstatus-1.1/components/wifi.c new file mode 100644 index 0000000..23af201 --- /dev/null +++ b/slstatus-1.1/components/wifi.c @@ -0,0 +1,413 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include + +#include "../slstatus.h" +#include "../util.h" + +#define RSSI_TO_PERC(rssi) \ + rssi >= -50 ? 100 : \ + (rssi <= -100 ? 0 : \ + (2 * (rssi + 100))) + +#if defined(__linux__) + #include + #include + #include + #include + #include + + static int nlsock = -1; + static uint32_t seq = 1; + static char resp[4096]; + + static char * + findattr(int attr, const char *p, const char *e, size_t *len) + { + while (p < e) { + struct nlattr nla; + memcpy(&nla, p, sizeof(nla)); + if (nla.nla_type == attr) { + *len = nla.nla_len - NLA_HDRLEN; + return (char *)(p + NLA_HDRLEN); + } + p += NLA_ALIGN(nla.nla_len); + } + return NULL; + } + + static uint16_t + nl80211fam(void) + { + static const char family[] = "nl80211"; + static uint16_t id; + ssize_t r; + size_t len; + char ctrl[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(sizeof(family))] = {0}, *p = ctrl; + + if (id) + return id; + + memcpy(p, &(struct nlmsghdr){ + .nlmsg_len = sizeof(ctrl), + .nlmsg_type = GENL_ID_CTRL, + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_seq = seq++, + .nlmsg_pid = 0, + }, sizeof(struct nlmsghdr)); + p += NLMSG_HDRLEN; + memcpy(p, &(struct genlmsghdr){ + .cmd = CTRL_CMD_GETFAMILY, + .version = 1, + }, sizeof(struct genlmsghdr)); + p += GENL_HDRLEN; + memcpy(p, &(struct nlattr){ + .nla_len = NLA_HDRLEN+sizeof(family), + .nla_type = CTRL_ATTR_FAMILY_NAME, + }, sizeof(struct nlattr)); + p += NLA_HDRLEN; + memcpy(p, family, sizeof(family)); + + if (nlsock < 0) + nlsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); + if (nlsock < 0) { + warn("socket 'AF_NETLINK':"); + return 0; + } + if (send(nlsock, ctrl, sizeof(ctrl), 0) != sizeof(ctrl)) { + warn("send 'AF_NETLINK':"); + return 0; + } + r = recv(nlsock, resp, sizeof(resp), 0); + if (r < 0) { + warn("recv 'AF_NETLINK':"); + return 0; + } + if ((size_t)r <= sizeof(ctrl)) + return 0; + p = findattr(CTRL_ATTR_FAMILY_ID, resp + sizeof(ctrl), resp + r, &len); + if (p && len == 2) + memcpy(&id, p, 2); + + return id; + } + + static int + ifindex(const char *interface) + { + static struct ifreq ifr; + static int ifsock = -1; + + if (ifsock < 0) + ifsock = socket(AF_UNIX, SOCK_DGRAM, 0); + if (ifsock < 0) { + warn("socket 'AF_UNIX':"); + return -1; + } + if (strcmp(ifr.ifr_name, interface) != 0) { + strcpy(ifr.ifr_name, interface); + if (ioctl(ifsock, SIOCGIFINDEX, &ifr) != 0) { + warn("ioctl 'SIOCGIFINDEX':"); + return -1; + } + } + return ifr.ifr_ifindex; + } + + const char * + wifi_essid(const char *interface) + { + uint16_t fam = nl80211fam(); + ssize_t r; + size_t len; + char req[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(4)] = {0}, *p = req; + int idx = ifindex(interface); + if (!fam) { + fprintf(stderr, "nl80211 family not found\n"); + return NULL; + } + if (idx < 0) { + fprintf(stderr, "interface %s not found\n", interface); + return NULL; + } + + memcpy(p, &(struct nlmsghdr){ + .nlmsg_len = sizeof(req), + .nlmsg_type = fam, + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_seq = seq++, + .nlmsg_pid = 0, + }, sizeof(struct nlmsghdr)); + p += NLMSG_HDRLEN; + memcpy(p, &(struct genlmsghdr){ + .cmd = NL80211_CMD_GET_INTERFACE, + .version = 1, + }, sizeof(struct genlmsghdr)); + p += GENL_HDRLEN; + memcpy(p, &(struct nlattr){ + .nla_len = NLA_HDRLEN+4, + .nla_type = NL80211_ATTR_IFINDEX, + }, sizeof(struct nlattr)); + p += NLA_HDRLEN; + memcpy(p, &(uint32_t){idx}, 4); + + if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) { + warn("send 'AF_NETLINK':"); + return NULL; + } + r = recv(nlsock, resp, sizeof(resp), 0); + if (r < 0) { + warn("recv 'AF_NETLINK':"); + return NULL; + } + + if ((size_t)r <= NLMSG_HDRLEN + GENL_HDRLEN) + return NULL; + p = findattr(NL80211_ATTR_SSID, resp + NLMSG_HDRLEN + GENL_HDRLEN, resp + r, &len); + if (p) + p[len] = 0; + + return p; + } + + const char * + wifi_perc(const char *interface) + { + static char strength[4]; + struct nlmsghdr hdr; + uint16_t fam = nl80211fam(); + ssize_t r; + size_t len; + char req[NLMSG_HDRLEN + GENL_HDRLEN + NLA_HDRLEN + NLA_ALIGN(4)] = {0}, *p = req, *e; + int idx = ifindex(interface); + + if (idx < 0) { + fprintf(stderr, "interface %s not found\n", interface); + return NULL; + } + + memcpy(p, &(struct nlmsghdr){ + .nlmsg_len = sizeof(req), + .nlmsg_type = fam, + .nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP, + .nlmsg_seq = seq++, + .nlmsg_pid = 0, + }, sizeof(struct nlmsghdr)); + p += NLMSG_HDRLEN; + memcpy(p, &(struct genlmsghdr){ + .cmd = NL80211_CMD_GET_STATION, + .version = 1, + }, sizeof(struct genlmsghdr)); + p += GENL_HDRLEN; + memcpy(p, &(struct nlattr){ + .nla_len = NLA_HDRLEN + 4, + .nla_type = NL80211_ATTR_IFINDEX, + }, sizeof(struct nlattr)); + p += NLA_HDRLEN; + memcpy(p, &idx, 4); + + if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) { + warn("send 'AF_NETLINK':"); + return NULL; + } + + *strength = 0; + while (1) { + r = recv(nlsock, resp, sizeof(resp), 0); + if (r < 0) { + warn("recv 'AF_NETLINK':"); + return NULL; + } + if ((size_t)r < sizeof(hdr)) + return NULL; + + for (p = resp; p != resp + r && (size_t)(resp + r-p) >= sizeof(hdr); p = e) { + memcpy(&hdr, p, sizeof(hdr)); + e = resp + r - p < hdr.nlmsg_len ? resp + r : p + hdr.nlmsg_len; + + if (!*strength && hdr.nlmsg_len > NLMSG_HDRLEN+GENL_HDRLEN) { + p += NLMSG_HDRLEN+GENL_HDRLEN; + p = findattr(NL80211_ATTR_STA_INFO, p, e, &len); + if (p) + p = findattr(NL80211_STA_INFO_SIGNAL_AVG, p, e, &len); + if (p && len == 1) + snprintf(strength, sizeof(strength), "%d", RSSI_TO_PERC(*p)); + } + if (hdr.nlmsg_type == NLMSG_DONE) + return *strength ? strength : NULL; + } + } + } +#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/slstatus-1.1/config.def.h b/slstatus-1.1/config.def.h new file mode 100644 index 0000000..100093e --- /dev/null +++ b/slstatus-1.1/config.def.h @@ -0,0 +1,70 @@ +/* See LICENSE file for copyright and license details. */ + +/* interval between updates (in ms) */ +const unsigned int interval = 1000; + +/* text to show if no value can be retrieved */ +static const char unknown_str[] = "n/a"; + +/* maximum output string length */ +#define MAXLEN 2048 + +/* + * function description argument (example) + * + * battery_perc battery percentage battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * battery_remaining battery remaining HH:MM battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * battery_state battery charging state battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * cat read arbitrary file path + * cpu_freq cpu frequency in MHz NULL + * cpu_perc cpu usage in percent NULL + * datetime date and time format string (%F %T) + * disk_free free disk space in GB mountpoint path (/) + * disk_perc disk usage in percent mountpoint path (/) + * disk_total total disk space in GB mountpoint path (/) + * disk_used used disk space in GB mountpoint path (/) + * entropy available entropy NULL + * gid GID of current user NULL + * hostname hostname NULL + * ipv4 IPv4 address interface name (eth0) + * ipv6 IPv6 address interface name (eth0) + * kernel_release `uname -r` NULL + * keyboard_indicators caps/num lock indicators format string (c?n?) + * see keyboard_indicators.c + * keymap layout (variant) of current NULL + * keymap + * load_avg load average NULL + * netspeed_rx receive network speed interface name (wlan0) + * netspeed_tx transfer network speed interface name (wlan0) + * num_files number of files in a directory path + * (/home/foo/Inbox/cur) + * ram_free free memory in GB NULL + * ram_perc memory usage in percent NULL + * ram_total total memory size in GB NULL + * ram_used used memory in GB NULL + * run_command custom shell command command (echo foo) + * swap_free free swap in GB NULL + * swap_perc swap usage in percent NULL + * swap_total total swap size in GB NULL + * swap_used used swap in GB NULL + * temp temperature in degree celsius sensor file + * (/sys/class/thermal/...) + * NULL on OpenBSD + * thermal zone on FreeBSD + * (tz0, tz1, etc.) + * uid UID of current user NULL + * up interface is running interface name (eth0) + * uptime system uptime NULL + * username username of current user NULL + * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) + * NULL on OpenBSD/FreeBSD + * wifi_essid WiFi ESSID interface name (wlan0) + * wifi_perc WiFi signal in percent interface name (wlan0) + */ +static const struct arg args[] = { + /* function format argument */ + { datetime, "%s", "%F %T" }, +}; diff --git a/slstatus-1.1/config.h b/slstatus-1.1/config.h new file mode 100644 index 0000000..7921491 --- /dev/null +++ b/slstatus-1.1/config.h @@ -0,0 +1,121 @@ +/* See LICENSE file for copyright and license details. */ + +/* interval between updates (in ms) */ +const unsigned int interval = 1000; + +/* text to show if no value can be retrieved */ +static const char unknown_str[] = "n/a"; + +/* maximum output string length */ +#define MAXLEN 2048 + +/* + * function description argument (example) + * + * battery_perc battery percentage battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * battery_remaining battery remaining HH:MM battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * battery_state battery charging state battery name (BAT0) + * NULL on OpenBSD/FreeBSD + * cat read arbitrary file path + * cpu_freq cpu frequency in MHz NULL + * cpu_perc cpu usage in percent NULL + * datetime date and time format string (%F %T) + * disk_free free disk space in GB mountpoint path (/) + * disk_perc disk usage in percent mountpoint path (/) + * disk_total total disk space in GB mountpoint path (/) + * disk_used used disk space in GB mountpoint path (/) + * entropy available entropy NULL + * gid GID of current user NULL + * hostname hostname NULL + * ipv4 IPv4 address interface name (eth0) + * ipv6 IPv6 address interface name (eth0) + * kernel_release `uname -r` NULL + * keyboard_indicators caps/num lock indicators format string (c?n?) + * see keyboard_indicators.c + * keymap layout (variant) of current NULL + * keymap + * load_avg load average NULL + * netspeed_rx receive network speed interface name (wlan0) + * netspeed_tx transfer network speed interface name (wlan0) + * num_files number of files in a directory path + * (/home/foo/Inbox/cur) + * ram_free free memory in GB NULL + * ram_perc memory usage in percent NULL + * ram_total total memory size in GB NULL + * ram_used used memory in GB NULL + * run_command custom shell command command (echo foo) + * swap_free free swap in GB NULL + * swap_perc swap usage in percent NULL + * swap_total total swap size in GB NULL + * swap_used used swap in GB NULL + * temp temperature in degree celsius sensor file + * (/sys/class/thermal/...) + * NULL on OpenBSD + * thermal zone on FreeBSD + * (tz0, tz1, etc.) + * uid UID of current user NULL + * up interface is running interface name (eth0) + * uptime system uptime NULL + * username username of current user NULL + * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) + * NULL on OpenBSD/FreeBSD + * wifi_essid WiFi ESSID interface name (wlan0) + * wifi_perc WiFi signal in percent interface name (wlan0) + */ +static const char vol[] = + "out=`wpctl get-volume @DEFAULT_SINK@`; " + "muted=`printf \"%s\" \"$out\" | awk '{print $3}'`; " + "v=`printf \"%s\" \"$out\" | awk '{print $2}'`; " + "pct=`awk -v v=\"$v\" 'BEGIN{printf \"%d\", (v*100)+0.5}'`; " + "if [ \"$muted\" = \"[MUTED]\" ] || [ \"$pct\" -le 0 ]; then " + "printf \"󰝟 MUT\"; " + "elif [ \"$pct\" -lt 34 ]; then " + "printf \"󰕿 %s%%\" \"$pct\"; " + "elif [ \"$pct\" -lt 67 ]; then " + "printf \"󰖀 %s%%\" \"$pct\"; " + "else " + "printf \"󰕾 %s%%\" \"$pct\"; " + "fi"; + +static const char bright[] = + "b=`brightnessctl -m get 2>/dev/null`; " + "max=`brightnessctl -m max 2>/dev/null`; " + "pct=`awk -v b=\"$b\" -v m=\"$max\" 'BEGIN{ if(m>0) printf \"%d\", (b/m*100)+0.5; else print 0 }'`; " + "if [ \"$pct\" -le 0 ]; then " + "printf \"󰃞 %s%%\" \"$pct\"; " + "elif [ \"$pct\" -lt 34 ]; then " + "printf \"󰃟 %s%%\" \"$pct\"; " + "else " + "printf \"󰃠 %s%%\" \"$pct\"; " + "fi"; + +static const char bt[] = + "if ! command -v bluetoothctl >/dev/null 2>&1; then " + "printf \"󰂯 N/A\"; exit; " + "fi; " + "powered=`bluetoothctl show 2>/dev/null | awk -F': ' '/Powered:/ {print $2}'`; " + "if [ \"$powered\" != \"yes\" ]; then " + "printf \"󰂯 OFF\"; exit; " + "fi; " + "dev=`bluetoothctl devices Connected 2>/dev/null | head -n1`; " + "if [ -n \"$dev\" ]; then " + "name=`printf \"%s\" \"$dev\" | cut -d' ' -f3-`; " + "printf \"󰂱 %s\" \"$name\"; " + "else " + "printf \"󰂲 ON\"; " + "fi"; + +static const struct arg args[] = { + /* function format argument */ + { wifi_essid, "%s ", "wlp3s0" }, + { wifi_perc, "%s%%", "wlp3s0" }, + { run_command, "| %s", bright }, + { run_command, "| %s", vol }, + { run_command, "| %s", bt }, + { battery_perc, "|  %s%%", "BAT0" }, + { battery_state, "(%s) ", "BAT0" }, + { cpu_freq, "|  %sHz", NULL }, + { datetime, "| %s", "%A %I:%M %p - %m/%d" }, +}; diff --git a/slstatus-1.1/config.mk b/slstatus-1.1/config.mk new file mode 100644 index 0000000..5655183 --- /dev/null +++ b/slstatus-1.1/config.mk @@ -0,0 +1,22 @@ +# slstatus version +VERSION = 1.1 + +# customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# flags +CPPFLAGS = -I$(X11INC) -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" +CFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -Os -march=native +LDFLAGS = -L$(X11LIB) -s +# OpenBSD: add -lsndio +# FreeBSD: add -lkvm -lsndio +LDLIBS = -lX11 + +# compiler and linker +CC = cc diff --git a/slstatus-1.1/slstatus.1 b/slstatus-1.1/slstatus.1 new file mode 100644 index 0000000..73e7a60 --- /dev/null +++ b/slstatus-1.1/slstatus.1 @@ -0,0 +1,47 @@ +.Dd 2023-04-23 +.Dt SLSTATUS 1 +.Os +.Sh NAME +.Nm slstatus +.Nd suckless status +.Sh SYNOPSIS +.Nm +.Op Fl s +.Op Fl 1 +.Sh DESCRIPTION +.Nm +is a small tool for providing system status information to other programs +over the EWMH +.Em WM_NAME +property of the root window (used by +.Xr dwm 1 ) or standard input/output. It is designed to be as efficient as possible by +only issuing the minimum of system calls required. +.P +By default, +.Nm +outputs to WM_NAME. +.Sh OPTIONS +.Bl -tag -width Ds +.It Fl v +Print version information to stderr, then exit. +.It Fl s +Write to stdout instead of WM_NAME. +.It Fl 1 +Write once to stdout and quit. +.El +.Sh CUSTOMIZATION +.Nm +can be customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.Sh SIGNALS +.Nm +responds to the following signals: +.Pp +.Bl -tag -width TERM -compact +.It USR1 +Triggers an instant redraw. +.El +.Sh AUTHORS +See the LICENSE file for the authors. +.Sh SEE ALSO +.Xr dwm 1 diff --git a/slstatus-1.1/slstatus.c b/slstatus-1.1/slstatus.c new file mode 100644 index 0000000..16d88fe --- /dev/null +++ b/slstatus-1.1/slstatus.c @@ -0,0 +1,135 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include + +#include "arg.h" +#include "slstatus.h" +#include "util.h" + +struct arg { + const char *(*func)(const char *); + const char *fmt; + const char *args; +}; + +char buf[1024]; +static volatile sig_atomic_t done; +static Display *dpy; + +#include "config.h" + +static void +terminate(const int signo) +{ + if (signo != SIGUSR1) + done = 1; +} + +static void +difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) +{ + res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec); + res->tv_nsec = a->tv_nsec - b->tv_nsec + + (a->tv_nsec < b->tv_nsec) * 1E9; +} + +static void +usage(void) +{ + die("usage: %s [-v] [-s] [-1]", argv0); +} + +int +main(int argc, char *argv[]) +{ + struct sigaction act; + struct timespec start, current, diff, intspec, wait; + size_t i, len; + int sflag, ret; + char status[MAXLEN]; + const char *res; + + sflag = 0; + ARGBEGIN { + case 'v': + die("slstatus-"VERSION); + break; + case '1': + done = 1; + /* FALLTHROUGH */ + case 's': + sflag = 1; + break; + default: + usage(); + } ARGEND + + if (argc) + usage(); + + memset(&act, 0, sizeof(act)); + act.sa_handler = terminate; + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); + act.sa_flags |= SA_RESTART; + sigaction(SIGUSR1, &act, NULL); + + if (!sflag && !(dpy = XOpenDisplay(NULL))) + die("XOpenDisplay: Failed to open display"); + + do { + if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) + die("clock_gettime:"); + + status[0] = '\0'; + for (i = len = 0; i < LEN(args); i++) { + if (!(res = args[i].func(args[i].args))) + res = unknown_str; + + if ((ret = esnprintf(status + len, sizeof(status) - len, + args[i].fmt, res)) < 0) + break; + + len += ret; + } + + if (sflag) { + puts(status); + fflush(stdout); + if (ferror(stdout)) + die("puts:"); + } else { + if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) + die("XStoreName: Allocation failed"); + XFlush(dpy); + } + + if (!done) { + if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) + die("clock_gettime:"); + difftimespec(&diff, ¤t, &start); + + intspec.tv_sec = interval / 1000; + intspec.tv_nsec = (interval % 1000) * 1E6; + difftimespec(&wait, &intspec, &diff); + + if (wait.tv_sec >= 0 && + nanosleep(&wait, NULL) < 0 && + errno != EINTR) + die("nanosleep:"); + } + } while (!done); + + if (!sflag) { + XStoreName(dpy, DefaultRootWindow(dpy), NULL); + if (XCloseDisplay(dpy) < 0) + die("XCloseDisplay: Failed to close display"); + } + + return 0; +} diff --git a/slstatus-1.1/slstatus.h b/slstatus-1.1/slstatus.h new file mode 100644 index 0000000..394281c --- /dev/null +++ b/slstatus-1.1/slstatus.h @@ -0,0 +1,85 @@ +/* See LICENSE file for copyright and license details. */ + +/* battery */ +const char *battery_perc(const char *); +const char *battery_remaining(const char *); +const char *battery_state(const char *); + +/* cat */ +const char *cat(const char *path); + +/* cpu */ +const char *cpu_freq(const char *unused); +const char *cpu_perc(const char *unused); + +/* datetime */ +const char *datetime(const char *fmt); + +/* disk */ +const char *disk_free(const char *path); +const char *disk_perc(const char *path); +const char *disk_total(const char *path); +const char *disk_used(const char *path); + +/* entropy */ +const char *entropy(const char *unused); + +/* hostname */ +const char *hostname(const char *unused); + +/* ip */ +const char *ipv4(const char *interface); +const char *ipv6(const char *interface); +const char *up(const char *interface); + +/* kernel_release */ +const char *kernel_release(const char *unused); + +/* keyboard_indicators */ +const char *keyboard_indicators(const char *fmt); + +/* keymap */ +const char *keymap(const char *unused); + +/* load_avg */ +const char *load_avg(const char *unused); + +/* netspeeds */ +const char *netspeed_rx(const char *interface); +const char *netspeed_tx(const char *interface); + +/* num_files */ +const char *num_files(const char *path); + +/* ram */ +const char *ram_free(const char *unused); +const char *ram_perc(const char *unused); +const char *ram_total(const char *unused); +const char *ram_used(const char *unused); + +/* run_command */ +const char *run_command(const char *cmd); + +/* swap */ +const char *swap_free(const char *unused); +const char *swap_perc(const char *unused); +const char *swap_total(const char *unused); +const char *swap_used(const char *unused); + +/* temperature */ +const char *temp(const char *); + +/* uptime */ +const char *uptime(const char *unused); + +/* user */ +const char *gid(const char *unused); +const char *uid(const char *unused); +const char *username(const char *unused); + +/* volume */ +const char *vol_perc(const char *card); + +/* wifi */ +const char *wifi_essid(const char *interface); +const char *wifi_perc(const char *interface); diff --git a/slstatus-1.1/util.c b/slstatus-1.1/util.c new file mode 100644 index 0000000..bca9b2e --- /dev/null +++ b/slstatus-1.1/util.c @@ -0,0 +1,141 @@ +/* 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) +{ + 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/slstatus-1.1/util.h b/slstatus-1.1/util.h new file mode 100644 index 0000000..cf4b027 --- /dev/null +++ b/slstatus-1.1/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)[0])) + +extern char *argv0; + +void warn(const char *, ...); +void die(const char *, ...); + +int esnprintf(char *str, size_t size, const char *fmt, ...); +const char *bprintf(const char *fmt, ...); +const char *fmt_human(uintmax_t num, int base); +int pscanf(const char *path, const char *fmt, ...); diff --git a/spotify b/spotify new file mode 100755 index 0000000..89de98e --- /dev/null +++ b/spotify @@ -0,0 +1,3 @@ +#!/bin/sh + +flatpak run com.spotify.Client diff --git a/wallpaper/nohup.out b/wallpaper/nohup.out deleted file mode 100644 index 20d057d..0000000 --- a/wallpaper/nohup.out +++ /dev/null @@ -1,20 +0,0 @@ - -(nemo:39725): Gtk-WARNING **: 13:30:55.465: Failed to register client: GDBus.Error:org.gnome.SessionManager.AlreadyRegistered: Unable to register client -Initializing nemo-image-converter extension -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox. -WARNING: Glycin running without sandbox.