Knowledge Base

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

Use "Remote Printer" driver for cups-shared printer in cups client

I use a cups print server to share a USB-connected printer. One of my new network clients needed the printer set up, and of course my client runs cups too. An existing cups client uses the printer with a "remote printer" driver that works well, and the closest model number in the built-in list after installing the generic, distro-provided package for this brand printed the page incredibly wrong.

So, I spent time learning how to set up the cups client to use "Remote Printer (grayscale, 2-sided printing)" driver, which presumably then lets the cups server use the correct driver I would have set up at least once on the real print server.

On the cups client, visit the cups web interface, normally http://localhost:631, and navigate to Administration -> add printer.

Select ipp printer type, and add your network printer: Mine was ipp://192.168.1.150:631/printers/printername. Add name, etc. Now, on the cups page where you select make and model or PPD file, select "Raw" -> IPP Everywhere. Then select button "Add Printer."

References

  1. CUPS: Share printer with generic driver - Unix & Linux Stack Exchange

Fluxbox show "(on $HOSTNAME)" if X11 forwarded program

I solved my problem from last time! I wrote a patch for Fluxbox to add the "(on $CLIENT)" message to titlebars of X11-forwarded client windows. See the source, and the debian/ for building a dpkg on my cgit instance (master branch).

Just in case that ever goes away (and somehow this blog doesn't), here's the source:

Author: bgstack15
Date: 2022-11-09
Version: fluxbox 1.4.0
Source: original
Summary: Add "(on $CLIENT)" to titlebar for forwarded windows
Message: 
Inspired by xfwm4's ability to display the remote host running an X11 window. This fails on xfe which somehow lacks the WM_CLIENT_MACHINE property.
--- a/src/Xutil.cc
+++ b/src/Xutil.cc
@@ -43,6 +43,51 @@ using std::endl;

 namespace Xutil {

+FbTk::FbString getWMClientMachine(Window window) {
+
+    if (window == None)
+        return FbTk::FbString("");
+
+    Display *display = FbTk::App::instance()->display();
+
+    XTextProperty text_prop;
+    text_prop.value = 0;
+    char **list = 0;
+    int num = 0;
+    _FB_USES_NLS;
+    FbTk::FbString name;
+
+    if (XGetWMClientMachine(display, window, &text_prop)) {
+        if (text_prop.value && text_prop.nitems > 0) {
+            if (text_prop.encoding != XA_STRING) {
+
+                text_prop.nitems = strlen((char *) text_prop.value);
+                XmbTextPropertyToTextList(display, &text_prop, &list, &num);
+
+                if (num > 0 && list != 0)
+                    name = FbTk::FbStringUtil::LocaleStrToFb(static_cast<char *>(*list));
+                else
+                    name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";
+
+                if (list)
+                    XFreeStringList(list);
+
+            } else
+                name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";
+
+            XFree(text_prop.value);
+
+        } else { // default name
+            name = _FB_XTEXT(Window, Unnamed, "Unnamed", "Default name for a window without a WM_NAME");
+        }
+    } else {
+        // default name
+        name = _FB_XTEXT(Window, Unnamed, "Unnamed", "Default name for a window without a WM_NAME");
+    }
+
+    return name;
+}
+
 FbTk::FbString getWMName(Window window) {

     if (window == None)
--- a/src/Xutil.hh
+++ b/src/Xutil.hh
@@ -28,6 +28,7 @@

 namespace Xutil {

+FbTk::FbString getWMClientMachine(Window window);
 FbTk::FbString getWMName(Window window);

 FbTk::FbString getWMClassName(Window win);
--- a/src/WinClient.cc
+++ b/src/WinClient.cc
@@ -49,6 +49,7 @@
 #else
   #include <string.h>
 #endif
+#include<unistd.h>

 using std::string;
 using std::list;
@@ -217,6 +218,10 @@ bool WinClient::getAttrib(XWindowAttribu
     return XGetWindowAttributes(display(), window(), &attr);
 }

+bool WinClient::getWMClientMachine(XTextProperty &textprop) const {
+    return XGetWMClientMachine(display(), window(), &textprop);
+}
+
 bool WinClient::getWMName(XTextProperty &textprop) const {
     return XGetWMName(display(), window(), &textprop);
 }
@@ -319,7 +324,14 @@ void WinClient::updateTitle() {
     if (m_title_override)
         return;

-    m_title.setLogical(FbTk::FbString(Xutil::getWMName(window()), 0, 512));
+    FbTk::FbString fullname = FbTk::FbString(Xutil::getWMName(window()), 0, 512);
+    FbTk::FbString clientmachine = FbTk::FbString(Xutil::getWMClientMachine(window()), 0, 512);
+    char *host = new char[512]; gethostname(host, 512);
+    FbTk::FbString hostname = FbTk::FbString(host);
+    if (clientmachine != "Unnamed" && clientmachine != "" && clientmachine != hostname) {
+        fullname += " (on " + clientmachine + ")";
+    }
+    m_title.setLogical(fullname);
     m_title_update_timer.start();
 }

@@ -328,7 +340,14 @@ void WinClient::emitTitleSig() {
 }

 void WinClient::setTitle(const FbTk::FbString &title) {
-    m_title.setLogical(title);
+    FbTk::FbString fullname = title;
+    FbTk::FbString clientmachine = FbTk::FbString(Xutil::getWMClientMachine(window()), 0, 512);
+    char *host = new char[512]; gethostname(host, 512);
+    FbTk::FbString hostname = FbTk::FbString(host);
+    if (clientmachine != "Unnamed" && clientmachine != "" && clientmachine != hostname) {
+        fullname += " (on " + clientmachine + ")";
+    }
+    m_title.setLogical(fullname);
     m_title_override = true;
     m_title_update_timer.start();
 }
--- a/src/WinClient.hh
+++ b/src/WinClient.hh
@@ -91,6 +91,7 @@ public:
     //

     bool getAttrib(XWindowAttributes &attr) const;
+    bool getWMClientMachine(XTextProperty &textprop) const;
     bool getWMName(XTextProperty &textprop) const;
     bool getWMIconName(XTextProperty &textprop) const;
     std::string getWMRole() const;

And here's the readme:

Readme for fluxbox

Overview

This is for my customized dpkg of Fluxbox which exists quite happily in vanilla form in Debian Sid.

fluxbox upstream

I modified the debian/ from snapshot.debian.org/package/fluxbox/

This set of overlay patches probably will not be maintained, so user beware! That being said, upstream is frozen so you won't get behind here either.

Reason for being in stackrpms

I wrote exactly one patch: debian/patches/add-clientmachine-if-forwarded.patch Also by using the custom package here I can incorporate all the useful patches added in what appears to be a neo-upstream on github which has neat patches like toolbar: allow labeled general action buttons and document iconified title deco which are not present in the Debian Fluxbox 1.3.5 release.

I chose Fluxbox as my daily driver desktop environment/window manager because it is stable. And it is stable, with a few minor flaws!

So this one patch I wrote adds to the titlebar of a forwarded window "(on $CLIENT)" which was inspired by Xfwm4.

Improvements

  • Add a configurable option for "Show (on $CLIENT)" so users can decide if they like it.
  • Some programs do not properly maintain WM_CLIENT_MACHINE X property, like xfe(1) so that could be misleading.
  • Maybe store local hostname on the Display, like Xfwm4 so we do not need to keep calling gethostname()
  • Find way to rearrange the iconbar window entries (issue #94 in original repo) which was also requested in one of the github forks (luebking/fluxbox#1 with comments:

If you however mean to drag around the icon, that's probably not too hard to do in src/Icon{Button,barTool}*

Alternatives

Just use the native package fluxbox for the given distro.

Github indicates a large number of forks exist of the source. Almost all of them do not provide substantive improvements.

Dependencies

Exact same as native package fluxbox.

References

Every link in this document. Official upstream link?: http://git.fluxbox.org/fluxbox.git/

Differences from upstream

Only one d/p/series and d/p/add-clientmachine-if-forwarded.patch

Call for help: Fluxbox display "(on $HOSTNAME)" for X11 forwarding

I recently discovered that my X11-forwarded client windows do not display the appended string "(on $CLIENT)" like I recall seeing in the past.

Upon some research, including a Unix Stack Exchange question, I learned that it depends on the window manager! It's not a built-in of Xorg.

Xfwm4 file client.c#215 adds this bit inside function clientCreateTitleName().

Fluxbox file WinClient.cc#322 in function WinClient::updateTitle() would be where you add the logic for adding "(on $CLIENT)" string.

If anybody likes C++ development and wants to write me a custom patch and earn my dying thanks, I would greatly appreciate it! Maybe someday I'll learn how to do this part. If a patch for this ever gets written, I would have to build fluxbox myself with the patch, which I am willing to do.

References

https://salsa.debian.org/xfce-team/desktop/xfwm4 https://gitlab.xfce.org/xfce/xfwm4

http://fluxbox.org/download/

krb5-auth-dialog and the news

With the most recent month's OS updates for Devuan GNU+Linux, I discovered that krb5-auth-dialog has now been updated for the first time in 4+ years!

The GNOME people have now removed the tray icon, which is the entire reason I wanted the software! So I downgraded to krb5-auth-plugin=3.26.1-4 and that now behaves like I want it to.

I was perusing /r/linux (that's a subreddit, if the syntax is unfamiliar to you) and came across Kerberos authentication on the Librem 5 which links to a Purism blog post by Guido Günter, one of the maintainers of krb5-auth-dialog. The screenshots in his article about kerberos on a Purism phone show krb5-auth-dialog, updated for a GTK4 and mobile world! I'm sure his changes fit nicely with that paradigm, and it's good that the software is still maintained.

That being said, its modern incarnation is useless on a real workstation so I reverted it. I had to download it and store it in a local apt repository.

Maybe someday I will fork krb5-auth-dialog into krb5-auth-trayicon and merge any changes (such as build with meson instead of GNU Make) that do not relate to deleting the tray icon. There are 122 commits and 119029 lines in the git diff between branches.

Devuan updates for November 2022 and sssd error

After running OS updates on Devuan unstable, I got this failure.

(2022-10-31 10:09:50): [be[ipa.internal.com]] [dp_load_module] (0x0400): About to load module [ipa].
(2022-10-31 10:09:50): [be[ipa.internal.com]] [dp_module_open_lib] (0x1000): Loading module [ipa] with path [/usr/lib/x86_64-linux-gnu/sssd/libsss_ipa.so]
(2022-10-31 10:09:50): [be[ipa.internal.com]] [dp_module_open_lib] (0x0010): Unable to load module [ipa] with path [/usr/lib/x86_64-linux-gnu/sssd/libsss_ipa.so]: libndr.so.2: cannot open shared object file: No such file or directory
(2022-10-31 10:09:50): [be[ipa.internal.com]] [dp_load_module] (0x0020): Unable to create DP module.
(2022-10-31 10:09:50): [be[ipa.internal.com]] [dp_target_init] (0x0010): Unable to load module ipa
(2022-10-31 10:09:50): [be[ipa.internal.com]] [dp_load_targets] (0x0020): Unable to load target [id] [80]: Accessing a corrupted shared library.
(2022-10-31 10:09:50): [be[ipa.internal.com]] [dp_init_done] (0x0020): Unable to initialize DP targets [1432158209]: Internal Error

Needed to add file /etc/apt/sources.list.d/temp.list with contents.

deb [check-valid-until=no] http://snapshot.debian.org/archive/debian/20221001T092433Z/ unstable main contrib

And then downgrade samba-libs, either with aptitude which can dynamically identify other dependencies to also downgrade, or just with apt-get.

sudo apt-get install libsmbclient=2:4.16.5+dfsg-1 samba-libs=2:4.16.5+dfsg-1

Downgrading sssd to 2.7.4-1 from 2.7.4-1+b1 is not necessary.

I could have avoided this this time by running this first:

sudo apt-mark hold samba-libs

Send https request with openssl s_client

Inspired by https://news.ycombinator.com/item?id=32903694.

To send a simple http get with openssl s_client, use this template.

sed -r -e 's/$/\r/;' <<EOF | openssl s_client -connect www.example.com:443 -ign_eof
GET /internal/directory.html HTTP/1.1
Host: www.example.com
Connection: close

EOF

Or with printf.

printf 'GET /internal/directory.html HTTP/1.1\r\nHost: www.example.com\r\nConnection: close\r\n\r\n' | openssl s_client -connect www.example.com:443 -ign_eof

Here is a sample post:

sed -r -e 's/$/\r/;' <<EOF | openssl s_client -connect server3.ipa.internal.com:443 -ign_eof
POST /coupons/search/ HTTP/1.0
Host: server3.ipa.internal.com
Connection: close
Content-Type: text/plain;charset=UTF-8
Accept: text/plain

cheese
EOF

X11 switching keyboard layouts

tl;dr

For myself:

sudo apt-get install fbxkb
setxkbmap -option grp:switch,grp:shifts_toggle 'us,us(dvorak)'

Add to ~/.fluxbox/startup:

fbxkb &

The story

I learned that Xorg (if not all X11 implementations) provide input method switching built-in! You can change keyboard layouts with:

setxkbmap -layout us -variant basic

To switch to dvorak:

setxkbmap -layout us -variant dvorak

While researching in preparation for writing a tray icon utility to show/switch input methods, I learned that you can simply specify multiple input methods, and complex options such as switching between the two:

setxkbmap -option grp:switch,grp:shifts_toggle,grp_led:scroll 'us(basic),us(dvorak)'

See xkeyboard-config(7) for a list of options.

And in my research, I also learned that I don't need to write my own mktrayicon-powered one: Multiple already exist!

Fbxkb was the closest to what I wanted visually, functionally, and source code-wise. Multiple sources of fbxkb source code exist, such as a few github places, the sourceforge (abandoned) upstream in svn which I don't use, and the Debian source tarball.

I did fork it to add some small steps I wanted:

  • Display menu on left click, and increment input method on middle click
  • Enable rotating input methods on scrollwheel scrolling action
  • Add variant support, e.g., dvorak
  • Add tooltip

Research links

  1. https://fbxkb.sourceforge.net/faq.html
  2. https://unix.stackexchange.com/questions/22903/how-to-re-enable-the-caps-lock-key
  3. https://superuser.com/questions/1194468/invert-colors-with-imagemagick/1376630#1376630

Save videos: 2022 edition

My current process for running yt-dlp involves detoxing the filenames.

File save-videos.sh.

#!/bin/sh
# Startdate: 2022-09-20
# Purpose: single utility that downloads and safely renames provided files
# Dependencies:
#    yt-dlp
#    detox
#    rename
#    files: config/detoxrc config/safe.tbl
cd "/path/${SUBDIR:+${SUBDIR}}"
mkdir -p temp && { cd temp && USED_TEMP=1 ; }
LANG=latin-1 PYTHONIOENCODING=latin-1 yt-dlp "${@}"
if test "${USED_TEMP}" = "1" ;
then
   # remove weird characters
   detox -f "config/detoxrc" -v *
   # strip the dash that precedes the youtube VID
   rename 's/ -([a-zA-Z0-9_]{11}\.)/ $1/' *
   mv -i * ..
fi

File config/detoxrc:

sequence default {
  uncgi;
  iso8859_1 {
    filename "/usr/share/detox/iso8859_1.tbl";
  };
  safe {
    filename "config/safe.tbl";
  };
  wipeup {
    remove_trailing;
  };
};

And my only differences for config/safe.tbl are:

--- /usr/share/detox/safe.tbl   2022-09-20 15:02:16.000000000 -0400
+++ config/safe.tbl 2022-09-20 10:08:23.326100599 -0400
@@ -99,11 +99,11 @@
 0x09       _   # tab
 0x0A       _   # new line
 0x0D       _   # carriage return
-0x20       _   # space
-0x21       _   # !
+#0x20      _   # space
+0x21       ''  # !
 0x22       _   # "
 0x24       _   # $
-0x27       _   # '
+0x27       ''  # '
 0x2a       _   # *
 0x2f       _   # /
 0x3a       _   # :

I entirely discard exclamation mark ! and single quote ', and do not replace spaces at all.

Keyboard LEDs trayicons in C

I previously wrote a small tool for myself named keyboard-leds-trayicons, which wraps around mktrayicon to provide system tray icons that indicate the current status of Capslock and Numlock.

Well, I decided to learn some C programming and rewrite my cruddy shell scripts with their silly extra sleep 0.75 invocations. I incorporated the entirety of mktrayicon.c, and wrote new logic.

I started piecemeal: at first just adding basic fifo controls to the child processes. Then I got fancy and added Unix domain sockets. This has been a labor of love, and now it is ready to be shared. You can see the almost-product-worthy keyboard-leds-trayicons.c now. I enjoyed adding getopt and libinih support. C is such a good way to write small programs like this. I even learned how to use libxdo (which powers xdotool) so you can click the tray icons to toggle Capslock and Numlock!

ddccontrol for monitors

The story

I use an Nvidia graphics card on my Devuan Ceres desktop. I also use two monitors, and a kvm switch for one of the monitors. On the other monitor I have a 3-input HDMI input switcher. Some article I read on the Internet suggested that one can use software to interact with the monitors, using the ddc protocol. I think DDC is how my old computers could recognize what was plugged in to my VGA port (and nowadays, VGA, displayport, and unfortunately some HDMI) by name.

On GNU/Linux, that software is ddccontrol. To enable Nvidia to pass through ddc protocol, I had to enable a module parameter. I set value in new file /etc/modprobe.d/nvidia-registry.conf which turns on the i2c capabilities of my 01:00.0 VGA compatible controller: NVIDIA Corporation GP107 [GeForce GTX 1050 Ti] (rev a1).

options nvidia NVreg_RegistryDwords="RMUseSwI2c=1"

I re-ran update-initramfs to ensure even the initram has this new setting.

sudo update-initramfs -u -k $( uname -r )

After a reboot (just to be sure), in userspace, I can now query the monitor. To learn the input field:

$ ddccontrol dev:/dev/i2c-4 -d | grep -i input
 Control 0x60: +/5/3 C [Input Source Select (Main)]

My two identical Samsung monitors ended up needing slightly different ddccontrol commands. I suspect this is due to one is connected via HDMI and one via DP.

My monitor-left-hdmi.sh command:

ddccontrol dev:/dev/i2c-4 -r 0x60 -w '5'

monitor-left-dp.sh:

ddccontrol dev:/dev/i2c-4 -r 0x60 -w '3'

monitor-right-vga.sh:

ddccontrol dev:/dev/i2c-2 -r 0x60 -w '1'
ddccontrol dev:/dev/i2c-2 -r 0xdb -w '4'
ddccontrol dev:/dev/i2c-2 -r 0xdc -w '6'
ddccontrol dev:/dev/i2c-2 -r 0xeb -w '253'

monitor-right-hdmi.sh:

ddccontrol dev:/dev/i2c-2 -r 0xdb -w '253'
ddccontrol dev:/dev/i2c-2 -r 0xdc -w '260'
ddccontrol dev:/dev/i2c-2 -r 0xeb -w '9'
ddccontrol dev:/dev/i2c-2 -r 0x60 -w '5'

I learned all those by evaluating the output of ddccontrol dev:/dev/i2c-4 -d after manually choosing the inputs I cared about.

These monitors didn't have prebuilt profiles in the ddccontrol-db.