aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-29 10:42:29 +0200
committerDanilo M. <danix@danix.xyz>2026-09-29 10:42:29 +0200
commit4645998b64815d15aef6efe00dcbdfc4a045359e (patch)
tree89665a54e8afcfc63c6ec4749c041d440432eaa6
parentdab41433688ff2247020d7a6fe12ac2140a75fb5 (diff)
downloadunified-desktop-theme-4645998b64815d15aef6efe00dcbdfc4a045359e.tar.gz
unified-desktop-theme-4645998b64815d15aef6efe00dcbdfc4a045359e.zip
feat(bin): udt-machine-name writes PRETTY_HOSTNAME to /etc/machine-info
The GRUB theme titles its panel with the machine's pretty name, and on Slackware nothing writes /etc/machine-info: hostnamectl is systemd's. This sets the one key, keeping any others, and with no argument prints it. The value is double-quoted with only \ and " escaped, the escapes systemd's reader and the GRUB build's shlex agree on; control characters are refused. It needs root and is never run by install.sh, which only suggests it in the GRUB output while no name is set. tests/machine-name.sh checks the quoting round-trip against shlex. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--AGENTS.md3
-rwxr-xr-xbin/udt-machine-name40
-rwxr-xr-xinstall.sh5
-rwxr-xr-xtests/machine-name.sh28
4 files changed, 75 insertions, 1 deletions
diff --git a/AGENTS.md b/AGENTS.md
index df16d3d..e6b0960 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -27,6 +27,9 @@ one symlink. A real `~/.config/hypr` directory is left alone with a warning.
`install.sh` runs its `build` as the user, then prints the root copy. A copy,
not a link, because GRUB reads `/boot` before `/home` is mounted; it needs
rerunning after a scheme or wallpaper change.
+Its panel title is `PRETTY_HOSTNAME` from `/etc/machine-info`, which
+`bin/udt-machine-name` writes (root, run by the user; there is no
+hostnamectl without systemd). It rewrites that one key and keeps the rest.
Live files that mix theme keys with anything else are merged, never replaced:
`install.sh`'s `ini_merge` writes every key in `templates/qt-gtk/qt5ct.conf`,
diff --git a/bin/udt-machine-name b/bin/udt-machine-name
new file mode 100755
index 0000000..1a677eb
--- /dev/null
+++ b/bin/udt-machine-name
@@ -0,0 +1,40 @@
+#!/bin/bash
+# Set or show this machine's pretty hostname, PRETTY_HOSTNAME in
+# /etc/machine-info. hostnamectl is systemd's writer; Slackware has neither,
+# and the GRUB theme reads the name for its panel title.
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+# Licensed under the GNU General Public License v2 only.
+#
+# udt-machine-name print the current name
+# sudo udt-machine-name "My Box" set it
+set -euo pipefail
+
+file="${UDT_MACHINE_INFO:-/etc/machine-info}"
+
+if [ $# -eq 0 ]; then
+ [ -f "$file" ] && sed -n 's/^PRETTY_HOSTNAME=//p' "$file"
+ exit 0
+fi
+if [ $# -ne 1 ] || [ -z "$1" ]; then
+ echo "usage: $(basename "$0") [NAME]" >&2
+ exit 2
+fi
+case "$1" in
+ *[[:cntrl:]]*) echo "name must not contain control characters" >&2; exit 2 ;;
+esac
+
+# Double-quoted, with only \ and " escaped: the escapes both systemd's reader
+# and the GRUB build's shlex understand the same way.
+value="$1"
+value="${value//\\/\\\\}"
+value="${value//\"/\\\"}"
+line="PRETTY_HOSTNAME=\"$value\""
+
+# Every other key in the file (ICON_NAME, CHASSIS, ...) is kept as it was.
+tmp="$(mktemp "$file.XXXXXX")"
+trap 'rm -f "$tmp"' EXIT
+{ [ -f "$file" ] && grep -v '^PRETTY_HOSTNAME=' "$file" || true; echo "$line"; } > "$tmp"
+chmod 644 "$tmp"
+mv "$tmp" "$file"
+trap - EXIT
+echo "$line"
diff --git a/install.sh b/install.sh
index 8052f71..f8ae97b 100755
--- a/install.sh
+++ b/install.sh
@@ -104,7 +104,7 @@ ln -sfn "$HOME/.cache/udt/colors.json" "$HOME/.cache/wal/colors.json"
# The rofi menus are bound by name in hypr-theme's keybindings, so they keep
# the names they had when they lived loose in ~/bin.
-for f in udt-accent udt-palette udt-powermenu.sh udt-launcher.sh qar-scrotmenu.sh; do
+for f in udt-accent udt-palette udt-machine-name udt-powermenu.sh udt-launcher.sh qar-scrotmenu.sh; do
ln -sfn "$repo/bin/$f" "$HOME/bin/$f"
done
@@ -352,6 +352,9 @@ if [ -x "$grub_repo/build" ]; then
echo " rm -rf /boot/grub/themes/udt && cp -r \"$grub_repo/dist/udt\" /boot/grub/themes/"
echo " # once: GRUB_THEME=\"/boot/grub/themes/udt/theme.txt\" in /etc/default/grub, then"
echo " grub-mkconfig -o /boot/grub/grub.cfg"
+ # The panel title falls back to the OS name until one is set.
+ [ -n "$("$repo/bin/udt-machine-name")" ] || \
+ echo " # optional, the panel title: sudo \"$repo/bin/udt-machine-name\" \"My Machine\""
else
echo "grub: its build failed, theme not refreshed" >&2
fi
diff --git a/tests/machine-name.sh b/tests/machine-name.sh
new file mode 100755
index 0000000..f8d9f6d
--- /dev/null
+++ b/tests/machine-name.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Check bin/udt-machine-name: quoting round-trips through shlex, other keys
+# survive, a second set replaces rather than appends.
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+# Licensed under the GNU General Public License v2 only.
+set -euo pipefail
+
+repo="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+tmp="$(mktemp -d)"
+trap 'rm -rf "$tmp"' EXIT
+export UDT_MACHINE_INFO="$tmp/machine-info"
+
+printf 'ICON_NAME=computer\nPRETTY_HOSTNAME="old"\n' > "$UDT_MACHINE_INFO"
+"$repo/bin/udt-machine-name" 'first' >/dev/null
+"$repo/bin/udt-machine-name" 'Anne'"'"'s "Box" \ $HOME' >/dev/null
+
+[ "$(grep -c '^PRETTY_HOSTNAME=' "$UDT_MACHINE_INFO")" = 1 ]
+grep -qx 'ICON_NAME=computer' "$UDT_MACHINE_INFO"
+python3 - "$UDT_MACHINE_INFO" <<'PY'
+import shlex, sys
+line = next(l for l in open(sys.argv[1]) if l.startswith("PRETTY_HOSTNAME="))
+got = " ".join(shlex.split(line[len("PRETTY_HOSTNAME="):]))
+assert got == 'Anne\'s "Box" \\ $HOME', got
+PY
+! "$repo/bin/udt-machine-name" $'a\nb' 2>/dev/null
+! "$repo/bin/udt-machine-name" '' 2>/dev/null
+
+echo "machine-name OK"