Background
I’ve been a huge fan of Linux ever since Microsoft started expanding the telemetry in Windows, starting with Windows 8. Linux has more versatility as a platform to develop on, and the ability to tweeak and alter the most minute details of components like the WM, DM, and system dameon tasks (on applicable systems). This kind of power quickly converted me through a rapid succession of distributions, starting with Ubuntu and ending with Arch1. Like many people with this kind of interest in deeply customizing the user experience, I ended up using Screenfetch and then Neofetch as the first command in every user-facing new terminal.
In some terminal emulators2 using the Bash or MirBSD Korn shells, I’ve had Screenfetch (and especially Neofetch) lag as the the sytem gets queried for information and said system info is regex’d, grepped, or split. When you run this application automatically when the user opens a terminal, this gets pretty annoying.
Enter C, everyone’s favorite3 high performance language4. I figured it would be fun to re-implement Screenfetch in C to try and get as much performance as possible; with slash, I think I’ve made good progress. Because Screenfetch would be cooler if it was written in C.
Collecting Information When Everybody Structures Their Distro Differently (in C)
Slash is broken up into three parts: a system detection library, a collection of ASCII art for popular Linux distros, and the execuable which combines the two with some configuration file handling. The final two parts are pretty much run-of-the-mill code, but there were some interesting problems getting the first part set up.
From easiest to hardest, the major tasks are listed below.
Get an Identifier for the Shell
If $SHELL
isn’t declared by your shell, you don’t really have any options.
Get the CPU’s model and properties
Chances are, if the system in Linux-based, CPU info is in /proc/cpuinfo
. 90% of the time, it works every time. Similarly, system uptime is expected to be in /proc/uptime
, system RAM is expected in /proc/meminfo
Get the Screen Resolution
As long as the user has xandr
, you can grep ot scan through its output to determine the number of monitors and their respective resolutions.
Get the Name of the Window Manager
Ideally, $GDMSESSION
is declared in the shell. We have the viable fallback of reading the output of the command ps aux
, though.
Get the GPU model
We straight-up need lspci
to get any level of information about the GPU; afterwards, we can examine the output and deal with the assorted name formatting schemes used by diferent manufacturers and vendors.
Get the model of the computer
Depending on the system, there are files we can scan under /sys/
or /tmp/sysinfo
. In all cases if present, these files only contain a designation for the device. If the files aren’t there, we’ve pretty much run out of options.
Getting the WM theme
Ends up being a bunch of highly specific one-line commands; either calls to settings libraries, like for Gnome, or awk
commands as a fallback.
Getting the GTK Theme
This one is kind of a pain. For GTK3, the location of this information can either be found in ${HOME}/.config/gtk-3.0/settings.ini
, through Gnome with gsettings get org.gnome.desktop.interface
, in grep \"^[^#]*%s\" \"${XDG_CONFIG_HOME}/gtk-3.0/settings.ini
if the ./config/gtk-3.0/...
file doesn’t exist and the WM adheres to the freedesktop standard, or in /etc/gtk-3.0/settings.ini
. There are equivalents for GTK2 themes; ultimately, there’s a fair amount of unique cases.
Configuring Slash
1 I’ll get around to Gentoo at some point. For now, I love Pacman and the AUR too much to switch.
2 Terminator, Gnome-Terminal, URXVT, ST (of all terminals; the name is literally “Suckless Terminal.” Where did we go wrong?)
3 Except for that half of CS people that get hung up on how much of a development style problem or security threat everything about C is, and the other half who don’t get pointers.
4 Valid alternatives are Rust or Go. C++ doesn’t count.