Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Gxkb is replacing fbxkb in my workflows, and GTK2 status in Devuan

The story

I use a patched Fluxbox as my window manager. I use fbxkb as a system tray icon to show me quickly which keyboard layout is active in X11.

I was reading on Ludditus about how Debian is working even harder to remove gtk2 more. I remember when some of the gtk2 dev packages were first removed from Debian, because I had to switch to using gtk3 to build Palemoon web browser and FreeFileSync. But this recent conversation from Ludditus was the first I'd heard of this recent change, which was a week after the original announcement by a guy to the debian-devel mailing list who is not even subscribed to the mailing list. I seem to recall that most mailing lists are set up so you must subscribe in order to send to it. I wonder if this user who started the conversation was abusing permissions or taking advantage of a bad configuration. There's a whole thread you could read for more info on the thunderous applause leading to the death of liberty.

Anyway, trying to get back to the topic at hand, I discovered that my workflows still dependent on the "offensive" package include the following.

$ sudo apt-get remove libgtk2.0-0t64 libgtk2.0-0
The following packages will be REMOVED:
asunder fbxkb gtk-chtheme libgail-common libgail18t64 libgtk2.0-0t64 libgtk2.0-bin libgtkspell0 palemoon pidgin
0 upgraded, 0 newly installed, 10 to remove and 265 not upgraded.

I have yet to address pidgin, which I actively use. I have found GTK3 forks for asunder: GrimRipper and asunder-gtk3. I have yet to address Palemoon, but I think that one already was using gtk3 also, so I hope it was just an optional dependency on gtk2. I haven't used it in a while; I'll have to grab Steven Pusser's latest palemoon work.

Gxkb and Fbxkb

Gxkb is already very similar to fbxkb, but it already uses gtk3. I started testing it, and had to poke around for quite a while before I realized the solution for my needs is very simple! All I need to do is set up my {country_code}_{variant}.png in the correct directory.

mkdir -p ~/.local/share/gxkb/flags
cp -pi /mnt/public/Support/Programs/gxkb/us_dvorak.png ~/.local/share/gxkb/flags/

That's it. I used ImageMagick (or whatever has supplanted it, et al) convert to invert the colors so Dvorak shows up as an inverted-color US flag. That is all.

I had forked fbxkb to add some features, but I need zero customization of gxkb! This simplifies my maintenance efforts, not that I had to rebuild fbxkb ever once I built it the way I liked. Here are the customizations I had added to fbxkb, and the current resolution for gxkb:

  • Display menu on left click, and increment input method on middle click: Can live without the menu; I have only 2 variants for now. If that changes, I might have to implement a menu.
  • Enable rotating input methods on scrollwheel scrolling action: Already have this feature.
  • Add variant support, e.g., dvorak: Already have this feature.
  • Add tooltip: Already have this feature!

References and additional reading

Weblinks

There might be additional or repeated entries in-line in the post.

  1. Debian -- Details of package gxkb in sid
  2. Debian -- Details of package fbxkb in bullseye
  3. Show home:bgstack15 / fbxkb - openSUSE Build Service
  4. #967337 - fbxkb: depends on deprecated GTK 2 - Debian Bug report logs
  5. Debian has its retards too: they plan to kill GTK2! – Homo Ludditus

Files

  1. file:///mnt/public/Support/Programs/gxkb/gxkb-keyboard-layout-indicator.md

Debuild package misc recommends

I wanted to add a recommended package to one of the packages I build for myself. I wanted to use my existing logic in Makefiles for DEPLIST, deptype, etc., which is demonstrated in gmm's debian/rules file.

override_dh_gencontrol:
  printf "misc:Depends=" > debian/${APPNAME}.substvars
  make -C src deplist DISTRO=devuan DEPTYPE=dep SEPARATOR=',' | grep -vE 'make\[[0-9]' >> debian/${APPNAME}.substvars
  dh_gencontrol

I had to update d/control and d/rules. It was very easy.

diff --git a/debian/control b/debian/control
index 5dd9849..a6638af 100644
--- a/debian/control
+++ b/debian/control
@@ -11,6 +11,7 @@ Package: stackrpms-acer-chromebook
 Architecture: all
 Multi-Arch: foreign
 Depends: ${misc:Depends}, ${shlibs:Depends}
+Recommends: ${misc:Recommends}
 Description: Common files for Acer Chromebook platform
  Useful configs and scripts for Stackrpms Acer Chromebook
  systems
diff --git a/debian/rules b/debian/rules
index 45b851e..d07d83a 100755
--- a/debian/rules
+++ b/debian/rules
@@ -15,6 +15,8 @@ override_dh_auto_install:
 override_dh_gencontrol:
        printf "misc:Depends=" > debian/${APPNAME}.substvars
        make -C src deplist DISTRO=devuan DEPTYPE=dep SEPARATOR=',' | grep -vE 'make\[[0-9]' >> debian/${APPNAME}.substvars
+       printf "misc:Recommends=" >> debian/${APPNAME}.substvars
+       make -C src deplist DISTRO=devuan DEPTYPE=rec SEPARATOR=',' | grep -vE 'make\[[0-9]' >> debian/${APPNAME}.substvars
        dh_gencontrol

 execute_after_dh_auto_clean:

I also just had to add the relevant rec-devuan: firmware-atheros in one of the source files.

Reference 1 was all I needed, to make it so my additional contents in the substvars file got added in the correct spot in my package.

Because I'd already written the Makefile logic to parse depends, recommends, and suggests, for a given target type, this small dpkg addition can hook into that logic without a lot of extra work!

References

  1. https://codesearch.debian.net/search?q=misc%3ARecommends&literal=1

git_1:2.51.0-1/debian/control

 perl, libcgi-pm-perl
Pre-Depends: ${misc:Pre-Depends}
Recommends: ${misc:Recommends}, libhttp-date-perl | libtime-parsedate-perl
Breaks: apache2.2-common (<< 2.3~)
Suggests: httpd-cgi | libcgi-fast-perl, git-doc

Initialize a dpkg for building

I talk about debuild a lot. Sometimes I build a new package that has no dpkg recipe yet, but I have to start somewhere.

To build a suitable tarball without git archive stuff (no scm in today's case), you can run this.

debmake -p paint -u 0.0.1 -r '1+stackrpms' -z=tar.gz -t

Customize the build recipe. For quite a while now, I've been putting the install process in file src/Makefile, and my debian/rules points to that source directory. It's nice and simple, with minimal effort needed on the dpkg instructions level. I want to be flexible in case I get around to building rpms again, or change package formats. I don't see that happening, but you never know. Make is probably the lowest common denominator: Pretty much any package manager will be able to use one.

And then a nice short debuild to build the package.

Devuan preseed, Jan 2026 edition

It's been almost 2 years since the last time I talked about a Devuan preseed virtual machine installation. I think it's been mostly my environmental changes this time, and thankfully not the underlying tech.

I pulled sha256:67b94eca462979374c668edd3339ec5f460867f18385b4bfc35126a727dbf5f4 devuan_excalibur_6.1.0_amd64_netinstall.iso

vm=d2-05a ; time sudo virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=debiantesting -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/Linux/devuan_excalibur_6.1.0_amd64_netinstall.iso --initrd-inject=/mnt/public/Support/Platforms/devuan/preseed/preseed.cfg --extra-args "NOTIFYEMAIL=bgstack15@gmail.com interface=auto netcfg/get_hostname=${vm}" --debug --network type=bridge,source=br0 --noautoconsole

I still haven't increased the disk size. I nowadays just add a 100GB disk separately, and tend to mount to /usr/src.

Read more…

Fedora 43: Lessons learned

Here's a partially-reheated post from the last time that I didn't read.

Operations for each new OS level release

I need to create a few new files.

  1. /mnt/public/www/domainname/repo/mirror/bgstack15-stackrpms-fedora-43.repo
  2. /mnt/public/www/domainname/repo/mirror/example-bundle-fedora43.repo

Lessons learned

  1. Rpm 6.0 has dropped old signature algorithms, which means some packages in my signed repositories are suddenly not good enough anymore. This stymied the package installation when the offending packages are in section %packages.

    So for now, I've had to connect to the new vm, and attempt to install the offending packages, and then visit the cache and rpm -i them manually, after installing the dependencies, of course.

    sudo dnf install moreutils # my dependencies
    sudo dnf install bgconf bgscripts-core bgscripts # this fails
    cd /var/cache/libdnf5/internalrpm-32eaedcb537c4bfd/packages
    sudo rpm -ivh --nodigest ./*.rpm
    

    Like it's 2001 or something.

  2. X11 and Xfce are still available.

    Some of the news about Fedora suggests they're going to get rid of these trusty technologies. If and when that happens, I guess I'll stop blogging about it because it won't be usable anymore. I already have to run on a special EL9 host with spice support re-enabled in qemu. Apparently good tech is dying, and is being replaced with garbage and incomplete tooling. I think I'm old now.

Read more…

Writing init script for explorer.lu

Great artists steal, so I just copied the certmonger init script for Devuan and adapted it for running the explorer-lu instance.

files/2026/listings/explorer-lu (Source)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/bin/sh
### BEGIN INIT INFO
# Provides:          explorer-lu
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Run explorer.lu instance
# Description:       Explorer.lu is a featureful web app for examining Lego
#                    Universe data from whichever dataset is configured.
### END INIT INFO

PATH=/home/bgstack15/.cargo/bin:/sbin:/usr/sbin:/bin:/usr/bin
DESC="explorer-lu"
NAME=paradox-server
DAEMON=/home/bgstack15/.cargo/bin/$NAME
DAEMON_ARGS=
export RUST_LOG=info
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/explorer-lu
DESTDIR=/usr/src/lu-explorer

. /lib/init/vars.sh
. /lib/lsb/init-functions

# Exit if the package is not installed
[ -x $DAEMON ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started
	start-stop-daemon --start --background --quiet --pidfile $PIDFILE --chdir $DESTDIR --exec $DAEMON --test > /dev/null \
		|| return 1
	start-stop-daemon --start --background --quiet --pidfile $PIDFILE --chdir $DESTDIR --exec $DAEMON -- \
		$DAEMON_ARGS \
		|| return 2
	# Add code here, if necessary, that waits for the process to be ready
	# to handle requests from services started subsequently which depend
	# on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   2 if daemon could not be stopped
	#   other if a failure occurred
	start-stop-daemon --stop --quiet --retry=TERM/3/KILL/5 --chdir $DESTDIR --pidfile $PIDFILE --name $NAME
	RETVAL="$?"
	[ "$RETVAL" = 2 ] && return 2
	# Wait for children to finish too if this is a daemon that forks
	# and if the daemon is only ever run from this initscript.
	# If the above conditions are not satisfied then add some other code
	# that waits for the process to drop all resources that could be
	# needed by services started subsequently.  A last resort is to
	# sleep for some time.
	start-stop-daemon --stop --quiet --oknodo --chdir $DESTDIR --retry=0/3/KILL/5 --exec $DAEMON
	[ "$?" = 2 ] && return 2
	# Many daemons don't delete their pidfiles when they exit.
	rm -f $PIDFILE
	return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
	#
	# If the daemon can reload its configuration without
	# restarting (for example, when it is sent a SIGHUP),
	# then implement that here.
	#
	start-stop-daemon --stop --signal 1 --quiet --chdir $DESTDIR --pidfile $PIDFILE --name $NAME
	return 0
}

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
    do_start
    case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
  ;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  #reload|force-reload)
	#
	# If do_reload() is not implemented then leave this commented out
	# and leave 'force-reload' as an alias for 'restart'.
	#
	#log_daemon_msg "Reloading $DESC" "$NAME"
	#do_reload
	#log_end_msg $?
	#;;
  restart|force-reload)
	#
	# If the "reload" option is implemented then remove the
	# 'force-reload' alias
	#
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;; # Old process is still running
			*) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
	  	# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
  *)
	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
	exit 3
	;;
esac

:

I had to add the --chdir and --background parameters myself. I also greatly shortened the timeout for killing the app. It appears it doesn't listen to the first signal. But it's a very simple webapp that doesn't matter if it gets hard-killed.

Prevent constant WinG display test in Windows 3.1

Some games that I run in my DOSBox Windows 3.1 environment always show a "Optimal display performance test" screen.

Screenshot of Windows 3.1 with a fuzzy graphic with the text Your program is testing for optimal display performance so that it will look its best on your system

I learned it was the WinG application after searching the Internet for that exact expression.

Due to how I install my dosbox environment, it is owned by root at path /usr/share/win31games. But I run dosbox as my own user, and even though all the directories are mode o+w, this utility keeps displaying every time I want to run the affected game.

I learned how to fix it. I copied it to ~/win31games and ran it there, and then diffed the WIN.INI file.

diff -aur /usr/share/win31games/WINDOWS/WIN.INI /home/bgstack15/win31games/WINDOWS/WIN.INI
--- /usr/share/win31games/WINDOWS/WIN.INI         2026-01-02 15:54:14.162281332 -0500
+++ /home/bgstack15/win31games/WINDOWS/WIN.INI    2026-01-02 11:50:49.716741502 -0500
@@ -178,5 +178,7 @@
 [WinG]^M
 s3trio.drv640x480x8(0,12)v1.70.4.0-504A-1.0.0.37=ECHGEGHGDDHGHCHGDDHGDDFFDDFFDDFFZZZZZZZZZZZZZZZZDDFGDGFGDDFGDDFG1F^M
+s3trio.drv640x480x8(0,12)v1.70.4.0-565C-1.0.0.37=ECHGECHGECHGECHGDDFFDDFFDDFFDDFFZZZZZZZZZZZZZZZZDDFGDDFGDDFFDDFG1F^M
+s3trio.drv640x480x8(0,12)v1.70.4.0-5B93-1.0.0.37=ECHGECHGECHGECHGDDFGDDFGDDFFDDFFZZZZZZZZZZZZZZZZDDFGDGFFDDFFFFFF1F^M
 ^M
 [drawdib]^M
 s3trio.drv 640x480x8(5)=1,0,0,0^M

So apparently WIN.INI was not writeable. Once I updated it with this new one with the latest dosbox emulated video card serial number, it then would run my game instantly.

Rotating stored credentials for services, etc.

I vibecoded for the first time recently, and came up with a few really useful functions for my team. When our service accounts get their password updated, we have to update on the pet servers where they get used.

Upstream

This project's upstream is at https://bgstack15.ddns.net/cgit/credlib

Alternatives

Do password changes manually with ClickOps.

Reason for existence

Concatenating my various Powershell credential-related libraries.

Using

Read the headers of the files, but here is a useful example for updating a cached password for these item types in Windows.

. Rotate-Creds-Lib.ps1
$creds = Get-Credential # provide domain as well, e.g. ts201@prod.example.corp
Rotate-ScheduledTasksCredential -Credential $creds
Rotate-IISAppPoolsCredential    -Credential $creds
Rotate-ServicesCredential       -Credential $creds

Dependencies

Powershell 5.1 in Windows 2019.

libcups problem after December updates

tl;dr

Until the newer, fixed version is available, downgrade with this command.

sudo apt install --allow-downgrades libcups2t64=2.4.10-3 libcups2t64:i386=2.4.10-3 cups=2.4.10-3 cups-client=2.4.10-3 cups-core-drivers=2.4.10-3 cups-bsd=2.4.10-3 cups-daemon=2.4.10-3 cups-ipp-utils=2.4.10-3

Narrative

After the December OS updates, one of my systems could not print from graphical programs. It took me a little while to learn how to print from the command line. That satisfies me, for basic things, but not for my users!

lp -d 'Zebra-Technologies-ZTC-ZP-450-200dpi' '/home/user5/Desktop/eBay-label-10-13909-52935.pdf'

Atril would just hang when trying to print. The Xfce4 system printer control dialog works!

I had to search the Internet and I came accross a bunch of research that was live at the time.

from dbus-monitor: at the time it malfunctions:

method call time=1764616543.199457 sender=:1.143 -> destination=org.freedesktop.DBus serial=30 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch string "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',arg0='org.freedesktop.secrets'" method return time=1764616543.199479 sender=org.freedesktop.DBus -> destination=:1.143 serial=24 reply_serial=30 method call time=1764616543.199482 sender=:1.143 -> destination=org.freedesktop.DBus serial=31 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=StartServiceByName string "org.freedesktop.secrets" uint32 0 error time=1764616543.199488 sender=org.freedesktop.DBus -> destination=:1.143 error_name=org.freedesktop.DBus.Error.ServiceUnknown reply_serial=31 string "The name org.freedesktop.secrets was not provided by any .service files"

The problem was merely because of an update to libcups, that broke how GTK was expecting. Apparently GTK is at fault (surprise, surprise). I use gtk3, and I hope I avoid gtk4.

Anyway, so the solution until gtk or libcups blinks was to downgrade, as seen in the tl;dr above.

The broken version is 2.4.14-3 and was the most recent one in debian per https://snapshot.debian.org/binary/libcups2t64/ at the time.

By the time this is published, the problem will probably be resolved already.

References

  1. Why is GNOME's print dialog crashing when cups.service is running? : r/linuxquestions
  2. Printing impossible from any application / Applications & Desktop Environments / Arch Linux Forums
  3. GTK System dialog freeze - English / Applications - openSUSE Forums
  4. CUPS 2.4.15 freezes apps requesting the GTK print dialog · Issue #1429 · OpenPrinting/cups