https://factoids.jfrech.com/

[2024-04-05] CSP in Go

Thinking of closing a channel as sending a sentinel value is an approximate thought model: the sentinel value has access to a hidden one-sized extra buffer.

ch := make(chan struct{})
close(ch) // does not block

ch = make(chan struct{}, 3)
ch <- struct{}{}
ch <- struct{}{}
ch <- struct{}{}
close(ch) // does not block

[2024-04-05] PulseAudio CLI

$ pactl set-sink-mute @DEFAULT_SINK@ false && pactl set-sink-volume @DEFAULT_SINK@ 30%

[2024-04-04] Filepath sanitisation

filepath.Join(base, untrusted)                                       // not sanitised
filepath.Join(base, "/", untrusted)                                  // not sanitised
filepath.Join(base, filepath.Join("/", untrusted))                   // sanitised
filepath.Join(base, filepath.FromSlashes(path.Join("/", untrusted))) // sanitised, platform-cognisant

[2024-04-02] Finding a Git commit

$ find ~/git/ -mindepth 1 -maxdepth 1 -type d | while IFS= read -r repo; do git -C "$repo" log; done | grep -A3 -B3 "$PATTERN"

[2024-03-29] DWM keybindings

I seem to always forget how one un-floats a window: Mod+MiddleMouseClick.

[2024-03-29] DWM adventures

I today bound Mod+w to open my web browser. In testing key chord feel, I pressed Mod+i thinking it would be a no-op. However, in vanilla DWM, Mod+i increments and Mod+d decrements the number of windows put vertically ontop in the master area. The effect is, when Mod+i is pressed once and only two windows are opened, they look like they stacked vertically.
Cf. https://unix.stackexchange.com/a/65900 [accessed 2024-03-29]

[2024-03-29] Pre-visualising pkg.go.dev's module rendering

$ go install golang.org/x/tools/cmd/godoc@latest && godoc -http=:8080

[2024-03-29] Interfacing with the evil kraken.

$ export GIT_SSH_COMMAND='ssh -o IdentitiesOnly=yes -i ~/.ssh/github'

[2024-03-29] Dual Git commit histories

$ git checkout --orphan $PREVIOUSLY_UNUSED_BRANCH_NAME

[2024-03-25] Printing on Debian 12

$ doas apt install --assume-yes lprng hplip
...
$ lp -d "$(lpstat -p -d | grep '^printer' | cut -d\  -f2)" paper.pdf

[2024-03-25] sxiv

I always want "a" and "b" pressed to use pixel-repeating scaling and no bottom cursor line. However, only the latter is supported by a flag: "$ sxiv -b a.png".

[2024-03-23] Sound without a desktop environment (on Debian 12)

$ doas apt install --assume-yes pavucontrol
$ pacmd list-sinks
$ pavucontrol ...
$ pactl info

[2024-03-23] Not forgetting local changes

$ ls "$HOME/git/" | while read repo; do echo "$repo"; git -C "$repo" status; echo; echo; done

[2024-03-23] Pushing a single tag

$ git tag devel
$ git push origin devel

[2024-03-17] The meaning of a trailing slash

$ cd "$(mktemp -d)"
$ mkdir a
$ ln -s a b
$ rm b/
rm: cannot remove 'b/': Is a directory
$ rm b

[2024-03-13] CSS

svw -- smallest viewport height
Cf. https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units [accessed 2024-03-13]

[2024-03-13] [2020-08-06] Early UNIX experiences

# useradd -m -G mail -s /bin/bash $USERNAME
# passwd $USERNAME
...
=== T H U N D E R B I R D ===
IMAP mail.domain.tld :993 SSL/TLS Autodetect
SMTP mail.domain.tld :587 STARTTLS Normal passw.

[2024-02-29] Incomplete Go documentation

As of Go 1.22, "bufio".(*Reader).WriteTo may emit w.(io.ReaderFrom).ReadFrom calls (cf. https://cs.opensource.google/go/go/+/refs/tags/go1.22.0:src/bufio/bufio.go;l=530) without mentioning it in its documentation.

[2024-02-29] Finding a domain's owner

Checking general domain availability: https://www.netcup.de/bestellen/domaincheck.php?domain=domain&tld=1

Checking mail availability: $ dig -t mx "$DOMAIN" and possibly writing to info@DOMAIN or postmaster@DOMAIN.

Checking the WayBack Machine (https://web.archive.org/) for an old imprint.

[2024-01-29] OpenSSH key management

$ echo "fingerprints" && ssh-keygen -lf ~/.ssh/known_hosts
$ echo "public host keys" && ssh-keygen -H -F domain
$ echo "rewrite known_hosts" && ssh-keygen -H

[2024-01-27] Computing is pain.

Fed up with Fedora 38's unbearable bugginess and disappointed by FreeBSD's Rust advances, I will now run Debian on my ThinkPad T470s.

$ curl -fsSL https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS
64d727dd5785ae5fcfd3ae8ffbede5f40cca96f1580aaa2820e8b99dae989d94  debian-12.4.0-amd64-netinst.iso
155eb74ffe7344c895708a12672183c87a4dfc2e9faf4fa401a64cad212e6b7e  debian-edu-12.4.0-amd64-netinst.iso
7f3eea6bf674584d9f162827a35d4bfd9e814513e88861315ce7526d1dded90f  debian-mac-12.4.0-amd64-netinst.iso

[2024-01-27] There are M.2 "M", "B" and "M+B" keys.

And if you bought a "M"-keyed SSD, your ThinkPad T470s' "B"-keyed slot won't receive it.
Cf. https://superuser.com/a/1530488 [accessed 2024-01-27]

[2024-01-24] CSS

Most fascinatingly, setting "z-index: 0;" has an effect as its meddles with the stacking contexts and thus messes up situations in which children want to "position: fixed; left: 0; right: 0; top: 0; bottom: 0; z-index: 1024;" but contend with siblings which are "position: sticky;".

[2024-01-21] What are you trying to tell me?

$ go doc std.byte
doc: no symbol byte in package archive/tar
exit status 1

[2024-01-17] Go "io/fs" error "readdir *: not implemented

Most likely, a "io/fs".FS.Open'd directory does not implement "io/fs".ReadDirFile.
Cf. https://cs.opensource.google/go/go/+/master:src/io/fs/readdir.go;l=41;drc=a5943e9de13b050c20aa2490082206232af4615c [accessed 2024-01-17]

[2024-01-11] Vim is a hot mess.

I think I've written about this before, but Vim's inability to not ignore backslash semantics for % are infuriating. I just wanted to delete the <br/> tag with $d%!

                        (prime?&nbsp;.p)&nbsp;|&gt;&nbsp;(not&nbsp;(any&nbsp;\<br/>

[2024-01-08] Go's example tests may require "go test -count=1"

It appears that Go caches tests modulo comments which makes "// Output:" directives changing not invalidate the test cache ... :/

[2024-01-07] Go's make does not imply a memory allocation

make([]string,0)!=nil holds. But apparently, make([]struct{},0x7fffffffffffffff) seldom panics.

[2024-01-06] An example why error codes are not sufficient and human-only error messages not a waste of time.

```sh $ cd "$(mktemp -d)" && ln -s bin sym && ls -ld sym && ./sym lrwxrwxrwx. 1 j j 3 Jan 6 00:17 sym -> bin bash: ./sym: No such file or directory ```

[2023-12-29] Gitting

When performing one singular change over a few commits (hard-resetting back down, making the change and cherry-picking back up), git tree-diff -p is of great use:

$ git diff-tree c35d924 20af12a -p
$ git diff-tree -p b202033 79f6768
$ git diff-tree -p 5565350 58db4e2

$ git reset --hard HEAD~1 && git push --force && git reset --hard 58db4e2a07b2c7388d1f213ce3debc8a05231039

[2024-01-03] Keep getting bitten by Go

Why does net/url ignore URL.RawPath if I explicitly set it?

$ cd "$(mktemp -d)" && cat >hrmpf.go <<'EOF'
package main

import (
    "fmt"
    "net/url"
)

func main() {
    fmt.Println((&url.URL{Scheme: "https", Host: "example.com", RawPath: "/i-ll-show-you-a-magic-trick-and-vanish"}).String())
}
EOF
$ go run hrmpf.go
https://example.com

Funny, huh? One should only ever use "net/url".Parse. I never get URL construction by hand to work.

[2024-01-01] Go's "compress/zlib".(*Reader).Close is not idempotent

Bit me just now; an hour later I am convinced "compress/zlib" is a very old package and thus a tad inelegant. "compress/zlib".NewReader at least mentions in a comment how it may void data if r.(io.ByteReader) does not unearase. But "compress/zlib".(*Reader).Close writes something on second close (I get double closes since I employ a cautious, uncancelled "defer zwc.Close()").

[2023-12-29] Go's soft panic

master* $ go doc testing.t.fatal
package testing // import "testing"

func (c *T) Fatal(args ...any)
    Fatal is equivalent to Log followed by FailNow.

master* $ go doc testing.t.failnow
package testing // import "testing"

func (c *T) FailNow()
    FailNow marks the function as having failed and stops its execution by
    calling runtime.Goexit (which then runs all deferred calls in the current
    goroutine). Execution will continue at the next test or benchmark. FailNow
    must be called from the goroutine running the test or benchmark function,
    not from other goroutines created during the test. Calling FailNow does not
    stop those other goroutines.

master* $ go doc runtime.goexit
package runtime // import "runtime"

func Goexit()
    Goexit terminates the goroutine that calls it. No other goroutine is
    affected. Goexit runs all deferred calls before terminating the goroutine.
    Because Goexit is not a panic, any recover calls in those deferred functions
    will return nil.

    Calling Goexit from the main goroutine terminates that goroutine without
    func main returning. Since func main has not returned, the program continues
    execution of other goroutines. If all other goroutines exit, the program
    crashes.

[2023-12-29] Hamming weight, popcount, population count or ones count in Go

Before rolling your own, use "math/bits".OnesCount64. There is also "math/bits".Len64.

[2023-12-28] printf in Haskell

Probably because of its dubious typing, I never before have used printf in Haskell. But writing a lot of Go has taught me its beauty.

ghci> import Text.Printf
ghci> printf "%x\n" (2^63-1)
7fffffffffffffff

[2023-12-26] Go stdlib

I just found out about strings.Field. Since I often use strings.TrimSpace, using something along the lines of strings.Split(s, " ") just seems off (some people do use tabs). And regexp feels overkill.

[2023-12-19] Quick Go memory profiling

$ go test -memprofile=/tmp/mem.out ./...
...
$ go tool pprof -http=:8081 /tmp/mem.out

[2023-12-19] Too much newth (... ings)

Democratisation is a good thing. It dismantles awe people expressed for monumental tasks. But one should not forget that design is hard. The fallacy of inventing a new thing is ubiquitous. Why is it a fallacy? Because when you give up trying to fix a weak point in an existing system you most likely only shift this intrinsically difficult problem to another part of your new-fangled system. Which most likely is incompatible with the world and which is, quite frankly, why it is worth absolutely nothing.

[2023-12-19] Go test results caching

I just had an unexplainable test results cache corruption---funnily enough, adding a " + 0" invalidates the cache, but e.g. adding " " inside a bracket map index does not.

$ go clean -testcache

[2023-12-16] Go documentation

In the past few weeks, "^Zgo doc ...\nfg\n" really has become a staple of my workflow. Reading https://pkg.go.dev/regexp@go1.21.5 [accessed 2023-12-16], I noticed that "go doc regexp/syntax" exists.

[2023-12-09] Go channels

The following prints "closed" not once, but ad infinitum:

// Jonathan Frech, 2023-12-09
package main

import "fmt"

func main() {
    a := make(chan int)
    b := make(chan int)

    close(a)

    for {
        select {
        case _, ok := <-a:
            if !ok {
                fmt.Println("closed")
            }
        case <-b:
        }
    }
}

[2023-12-15] Zlib -d

master* $ openssl zlib -d <.git/objects/bf/074c0f6e7e72c82c98d466e008fa771cdf9915 | xxd | head
00000000: 626c 6f62 2031 3338 3731 3230 3634 0048  blob 138712064.H
00000010: 4541 4400 0000 0000 0000 0000 0000 0000  EAD.............
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000070: 0000 0030 3030 3036 3434 0030 3030 3030  ...0000644.00000
00000080: 3030 0030 3030 3030 3030 0030 3030 3030  00.0000000.00000
00000090: 3030 3030 3237 0030 3030 3030 3030 3030  000027.000000000
error writing output file

[2023-12-11] Cppref

curl -fsSL https://en.cppreference.com/w/cpp/symbol_index | grep '<tt>' | grep vector

[2023-12-05] Fuzz something, anything.

$ set -x; cd "$(mktemp -d)" && git clone https://git.jfrech.com/~jfrech/brief.git repo && cd repo && packagetarget="$(grep -rI '^func Fuzz[A-Za-z0-9_]\+(f \*testing.F) {$' | sort -R | head -n1 | sed 's!^\([^:]*\)/[^:/]*:func \([A-Za-z0-9_]*\)(.*$!\1,\2!')"; GOPRIVATE=pkg.jfrech.com go test ./"${packagetarget%%,*}" -fuzz "${packagetarget##*,}"

[2023-12-03] I probably use path/filepath too often.

Quoting https://pkg.go.dev/path@go1.21.4 [accessed 2023-12-03],

Package path implements utility routines for manipulating slash-separated paths.

The path package should only be used for paths separated by forward slashes, such as the paths in URLs. This package does not deal with Windows paths with drive letters or backslashes; to manipulate operating system paths, use the path/filepath package.

Since I never respect Windows, I should probably not rely on path/filepath to yield slash-delimited strings.

[2023-11-20] Deleting /Icon files

Most likely a remnant of Mac OS 9's data/resource fork distinction.

# find . | grep '/Icon$' | while IFS= read -r icon; do rm "$icon"; done

[2023-11-09] I am shocked.

Maybe I'll switch from Brave to Firefox ...
Cf. https://community.brave.com/t/turn-off-leo-completely-e-g-remove-all-visuals/514899 [accessed 2023-11-09]

[2023-11-05] Unlock Brave

Today I had a truly baffling bug in which brave-browser simply would not start:

$ brave-browser
[3290:3290:1105/015048.729334:ERROR:process_singleton_posix.cc(353)] The profile appears to be in use by another Brave process (6831) on another computer (p200300c2a70c1776cf4ec56b2b334f02.dip0.t-ipconnect.de). Brave has locked the profile so that it doesn't get corrupted. If you are sure no other processes are using this profile, you can unlock the profile and relaunch Brave.
[3290:3290:1105/015048.729496:ERROR:message_box_dialog.cc(146)] Unable to show a dialog outside the UI thread message loop: Brave - The profile appears to be in use by another Brave process (6831) on another computer (p200300c2a70c1776cf4ec56b2b334f02.dip0.t-ipconnect.de). Brave has locked the profile so that it doesn't get corrupted. If you are sure no other processes are using this profile, you can unlock the profile and relaunch Brave.

It got so bad that I honestly installed Firefox ...

My fix was the following one-liner (especially the SingletonLock seemed an issue):

find ~/.config/BraveSoftware/ | grep LOCK | while IFS= read -r LOCK; do rm "$LOCK"; done && rm ~/.config/BraveSoftware/Brave-Browser/SingletonLock

[2023-11-04] Filesystem checksum

$ OUT=/tmp/x270 && rm -f ~/go/bin/fscs && GOPRIVATE=pkg.jfrech.com go install pkg.jfrech.com/glu/cmd/fscs@v0.0.0-20231104154721-209c09db5cb4 && ~/go/bin/fscs . >"$OUT" && find . | wc -l && wc -l "$OUT"

[2023-10-31] Thoughts on design and Go.

In analogy to the half-proverb "Accept interfaces, return structs." [citation needed], I think "Never accept an io.ReadCloser without returning one." should also be a proverb: initiating a second-layer network abstraction, as an example, potentially needs to read/write and close, closing on error. But else, the caller should be left as the closing entity.
I also realised how only returning structs idiomatically hints at not using a FailingReader, a concept I have now abandoned (one can hide two semantically different readers in the one io.Reader interface):

// preferred
func Decode(encoding string, r io.Reader) (*DecodedReader, error) {
    if encoding != "base32" {
        return nil, fmt.Errorf("unknown encoding: %q", encoding)
    }
    return &DecodedReader{r: r}, nil
}

// to be avoided
func Decode(encoding string, r io.Reader) io.Reader {
    if encoding != "base32" {
        return &FailingReader{fmt.Errorf("unknown encoding: %q", encoding)}
    }
    return &DecodedReader{r: r}
}

type FailingReader struct {
    Err error
}

func (fr *FailingReader) Read(p []byte) (int, error) {
    return 0, fr.Err
}

[2023-10-25] Go's net/mail.(*Address).String does both encode and transport-encode

Bit me the other day. To be fair, [the documentation](https://pkg.go.dev/net/mail@go1.21.3#Address.String) says "(...) will be rendered according to RFC 2047." RFC 2047 being atom encoding (or transport-encoding or Q/B-encoding).

[2023-10-24] A Go documentation slip-up

Go 1.21.3 [says](https://pkg.go.dev/runtime/debug@go1.21.3#BuildSetting):

(...)
CGO_ENABLED: the effective CGO_ENABLED environment variable
CGO_CFLAGS: the effective CGO_CFLAGS environment variable
CGO_CPPFLAGS: the effective CGO_CPPFLAGS environment variable
CGO_CXXFLAGS: the effective CGO_CPPFLAGS environment variable
CGO_LDFLAGS: the effective CGO_CPPFLAGS environment variable
GOARCH: the architecture target
(...)

I was scratching my head why CGO_CXXFLAGS and CGO_LDFLAGS were aliases. After all, [Russ Cox had written it](https://cs.opensource.google/go/go/+/dadd80ae204bda1c3a48245d8a938f55f71259ea). How can you get more authoritative? But alas, it [was a bug](https://cs.opensource.google/go/go/+/43559aa9a5a550ba7dac224a174130e42f93de99).

Anyways, the key vcs.time was what I truly searched for. Now I can programmatically encode the latest commit's date in [Brief](https://brief.software.jfrech.com/)'s manpage.

[2023-10-20] Check DNS MX records for propagation

I know, I know: DNS does not propagate, what happens is that caches expire.

$ dig +short -t mx jfrech.com

[2023-10-17] Odd Go compiler diagnostic

$ go version && filename="$(mktemp)" && echo 'package main; import "strings"; func main() { strings.HasSuffix(strings, "") }' >"$filename.go" && go run "$filename.go"
go version go1.20.8 freebsd/amd64
# command-line-arguments
/tmp/tmp.ObFT1xQm.go:1:65: use of package strings not in selector

[2023-10-16] Skim through all dangling blob data

When regularily git adding or even git commiting followed by intrepid branch resetting and commit amending, it sometimes happens that one loses code one knows one wrote. When the last git gc --prune=now is a while back, the following might aid in recovering these lines of code:

git fsck --dangling | grep '^dangling blob [0-9a-f]\{40\}$' | sed 's/dangling blob/git cat-file -p/' | xargs -I{} sh -c {} | vim -

[2023-10-09] .zfs/

I just now learnt of /zroot/.zfs/, a pseudo directory in which all snapshots are pseudo-mounted. Very handy if you want to free up space by destroying a snapshot but maybe one directory which got deleted you really want to keep and re-examine later.

[2023-10-07] FreeBSD: configure hostname

For the standard wired device em0:

 # grep em0 /etc/rc.conf
ifconfig_em0="DHCP"
ifconfig_em0_ipv6="inet6 accept_rtadv"
# ed /etc/rc.conf
...
# grep em0 /etc/rc.conf
#ifconfig_em0="DHCP"
ifconfig_em0="inet 192.168.2.98 netmask 255.255.255.0"
ifconfig_em0_ipv6="inet6 accept_rtadv"

Cf. https://forums.freebsd.org/threads/setting-up-static-ip-address.46025/#post-257506 [accessed 2023-10-07]

[2023-10-07] macOS: configure hostname

Apparently, # scutil --set HostName host.name. Cf. https://apple.stackexchange.com/a/287775 [accessed 2023-10-07]

[2023-10-07] Git housekeeping (one-liner)

# pwd && git show-ref && du -hs . && echo '=== FSCK' && git fsck --dangling | sort && echo '===' && git gc --no-prune --aggressive && du -hs . && echo '=== FSCK' && git fsck --dangling | sort && echo '==='

[2023-10-07] Git housekeeping

$ git fsck --dangling | sort | sha512sum
$ git gc --no-prune --aggressive
$ git fsck --dangling | sort | sha512sum

[2023-10-06] Delete tags on the remote

$ git push --delete origin v0.1.0

[2023-10-06] Commit a stale change in Git

$ stat CHANGED_FILE
...
$ git add CHANGED_FILE
$ GIT_AUTHOR_DATE='2023-09-14 03:30:51 +0200' git commit -m '((actual commit message, authored from when the stale change was made, committer date is now))'

[2023-10-05] Fix FreeBSD system time

For some reason, my system time just offset itself by ~7h. To fix it, I had to manually ping a time server:

# ntpdate 0.pool.ntp.org
 5 Oct 23:31:57 ntpdate[39118]: step time server 172.104.134.72 offset +60351.279198 sec

What did not work was a) restarting the NTP daemon via # service ntpd restart; neither did b) restarting nor c) adjusting the timezone and disabling CMOS via # tzsetup.

Cf. https://forums.freebsd.org/threads/time-is-always-wrong.83166/ [accessed 2023-10-05]

[2023-10-05] Removing Windows 10's recovery partition

I bought a refurbished ThinkPad T470s (I manually removed camera, microphone and speakers). It had an OEM-installed Windows 10 on it (which I require for external reasons) and I wanted to dual-boot with Fedora 38. Inside Windows 10 running, I could shrink the boot partition and delete the recovery partition, but this lead to the computer no longer booting. Sticking in a Windows 10 installer thumb drive and powering the system on seems to have repaired the system.

[2023-09-22] Update macOS Developer Tools after an OS upgrade

% xcode-select --install

[2023-09-15] Fabric.png

It must have been years ago, but this clothy, woolly background for me is the epitome of what a wallpaper is.

$ cd "$(mktemp -d)" && curl -fsSL https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/gnome-backgrounds/3.28.0-1/gnome-backgrounds_3.28.0.orig.tar.xz | tar -xz gnome-backgrounds-3.28.0/backgrounds/Fabric.jpg && mv */*/Fabric.jpg /tmp/fabric.jpg ; cd - >/dev/null

[2023-09-15] Uninstall OSXFUSE

OSXFUSE or macFUSE [1] only implements deprecated FUSE 2, ships a slow SSHFS and is duly unreliable. To get rid of of this horrid macOS kernel extension, one has to both instruct it through the Control Panel to uninstall itself and [2] instruct Control Panel to remove the extension (third-party items have a context menu). Finally, % rm -rf Library/Caches/io.macfuse.preferencepanes.macfuse.

REFERENCES.
[1] https://osxfuse.github.io/ [accessed 2023-09-15]
[2] https://www.imymac.com/powermymac/unistall-mac-fuse.html#part2 [accessed 2023-09-15]

[2023-09-14] Installing fonts

# target=/usr/local/share/fonts/TTF/JetBrainsMono && [ ! -d "$target" ] && mkdir -p "$target" && usrtmpdir="$(mktemp -d)" && echo >&2 "$tmpdir" && cd "$tmpdir" && curl -fsSL https://download.jetbrains.com/fonts/JetBrainsMono-2.304.zip | unzip - && mv fonts/ttf/*.ttf "$target"/ && cd - >/dev/null && rm -rf "$tmpdir" && fc-cache -f && fc-list | grep -i jetbrains

[2023-09-12] Gentoo wiki's odd bot prevention

Since I have of late managed to get a WiFi-enabled, FreeBSD-running, camera-and-microphone-removed ThinkPadX270 running, I began oncemore dabbling in dwm [1]. Surfing along, I came across the sh line " weather=$(curl wttr.in?format=1)" [2] whose blatant disregard for a POSIX shell's whitespace handling I could not leave untouched. Alas, creating a Gentoo wiki account seems to require running Gentoo, as the last step asks ''**To protect the wiki against automated account creation, we kindly ask you to answer the question that appears below ([more info](https://wiki.gentoo.org/wiki/Special:Captcha/help)):** | On a recent Gentoo system, what does `sed -n "6p" /etc/os-release | sha256sum | cut -d " " -f 1` print?'' [3]. Now, I do not have a machine running Gentoo and hashing the empty string or the string only containing a newline did not work. This is why only after three days I write these lines: I downloaded a three gigabyte gentoo-livegui-amd64-20230903T170202Z.iso, put it on a thumb drive, tripped into KDE (ugh ... cf. [4]) and looked at the file in question:

gentoo@livecd ~ $ cat /etc/os-release
NAME=Gentoo
ID=gentoo
PRETTY_NAME="Gentoo Linux"
ANSI_COLOR="1;32"
HOME_URL="https://www.gentoo.org/"
SUPPORT_URL="https://www.gentoo.org/support/"
BUG_REPORT_URL="https://bugs.gentoo.org/"
VERSION_ID="2.14"

From the above, the correct 64 hex digits can be computed; I now have a Gentoo wiki account. Of course, I quickly logged out of my Gentoo live cd running that questionable desktop environment!

In a way, by search engines indexing my page, Gentoo wiki's security is hampered. I hope they will not now be robbed of their server resources.
I, however, do think that such forms of bot prevention are far more ethical than e. g. deploying tech giants' solutions and forcing your users to surrender their soul. The price Gentoo wiki pays is most likely a fairly low user count. But I am sure they are fine with that.

REFERENCES.
[1] https://dwm.suckless.org/ [accessed 2023-09-12]
[2] https://wiki.gentoo.org/wiki/Dwm#Custom_script [accessed 2023-09-12]
[3] https://wiki.gentoo.org/index.php?title=Special:CreateAccount [accessed 2023-09-12]
[4] https://blog.jfrech.com/271/ [accessed 2023-09-12]

[2023-08-31] ZFS adventures

I just noticed that when destroying a snapshot of a dataset which clings on to a lot of data, zfs list tank called in quick succession reveals how the ZFS daemon takes its time to release captive blocks (which previously made me question which snapshot was to blame for the tank not releasing blocks I was sure not to be needed anymore -- the impatient do not see the full picture). But as [McK15, 41:19] said, ZFS' snapshotting efficiency is a function of churn. And a lot of data (even in the form of a singular, large file) means a lot of blocks which is churn.

REFERENCES
[McK15] Marshall K. McKusick: "An Introduction of the Implementation of ZFS", 2015. In: OpenZFS Conference 2015, San Francisco, California. Online: https://youtu.be/IQp_FglfzUQ?t=2479 [accessed 2023-08-28]

[2023-08-24] My preferred rsync invocation

$ rsync -vzP -caXN SRC/ DST/
$ rsync -vzP -caXN --delete SRC/ DST/

[2023-08-20] OpenSSH can be finnicky

# chown -R root /root/.ssh && chmod 0700 /root/.ssh && chmod 0600 /root/.ssh/*
# grep -v '^ssh-ed25519 [A-Za-z0-9+/=_-]\{68\}' /root/.ssh/authorized_keys
# cat /etc/ssh/sshd_config
PermitRootLogin prohibit-password
PubkeyAcceptedKeyTypes=ssh-ed25519
PubkeyAuthentication yes

UsePAM no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PasswordAuthentication no
PermitEmptyPasswords no

X11Forwarding no
PrintMotd yes
#PrintLastLog yes ### not supported by FreeBSD 13.2-RELEASE

[2023-08-18] netcatting data

I am on a system where ssh throws no hostkey alg and have insufficient privileges to install host keys. So, to exfiltrate data, trusty nc saves the day:

$ echo source system >/dev/null
$ nc 192.168.2.119 6666 <DATA

$ echo drain system >/dev/null
$ nc -lp6666 >DATA

Of course, this is unencrypted and thus not cryptographically checksummed, so a final sha512sum (or shasum -a512 on the Mac OS X 10.7.5 system I am currently on to read an old HFS (plus?) drive) must not be skipped.

[2023-08-08] Reducing systemd's logging footprint on disk

On my space-constrained git VPS,

# du -hs /var/*
...
2.0G    /var/log
...

was unacceptable. So I ran:

# journalctl --vacuum-time=1month
...

This got /var/log down to 524760B. However, /usr/lib/modules's 951488B I left untouched.

[2023-08-06] My preferred rsync invocation

$ rsync -calvzP

[2023-06-29] Fetch git/*

$ cd ~/git && ls | xargs -I{} git -C {} fetch

[2023-06-28] My preferred rsync invocation

$ rsync -calvz j@192.168.2.xxx:A /tmp/B

[2023-06-28] A quick-and-dirty directory checksum

$ find "$DIR/" -type f | LC_ALL=C sort | xargs -L1 sha512sum | sha512sum

[2023-06-20] Mass-fetch Git repositories

E. g. when fearing a prolonged Internet drought. (Which can happen if your University out of nowhere decides to scrap their root certificate which would expire ~2033 ($ openssl x509 -in wurzel.crt -inform DER -enddate -nocert).)

$ for repo in ~/git/*; do git -C "$repo" fetch --all; done

[2023-05-28] Deleting empty files

$ wc -l "$TARGET_DIRECTORY"/* | grep '\<0\>' | awk '{ print $2 }' | xargs rm

[2023-05-23] Go as a package manager

I have to admit to using v1.3.0 instead of the more appropriate v2.0.0 solely to not get a varying import path.

$ GOPRIVATE=pkg.jfrech.com go install pkg.jfrech.com/imaptar/cmd/imaptar@v1.3.0 && echo "installed to: ${GOBIN:-${GOPATH:-$HOME/go}/bin}/imaptar"

[2023-05-11] Removing files known to Git

Use case: One has a Git repository in which a file often changes and a directory of unmanaged backup files (simple copies). Worrying about losing data, the following is written:

$ for FILE in "$DIRECTORY"/*; do git cat-file 2>/dev/null -p "$(git hash-object "$FILE")" | cmp --quiet "$FILE" && rm "$FILE"; done

Slightly edited 2023-06-20.

[2023-05-01] Installing Go 1.20

# URL='https://go.dev/dl/go1.20.3.linux-amd64.tar.gz' CHECKSUM='979694c2c25c735755bf26f4f45e19e64e4811d661dd07b8c010f7a8e18adfca' ; [ "$(curl -f#SL "$URL" | tee /tmp/go.tar.gz | sha256sum | cut -d\  -f1)" = "$CHECKSUM" ] && rm -rf /usr/local/go && tar -C /usr/local -vxzf /tmp/go.tar.gz

Whilst developing brief, I noticed Go 1.20's new bytes.Clone convenience function. It was enough to push me to update.

[2023-04-17] My preferred rsync invocation

$ rsync -cavz --delete root@jfrech.com:to-be-exfiltrated /tmp/exfiltrated

[2023-03-31] Dynamic libraries' version bumps

Since my VPS is running Debian 12 (bookworm) and I today decided to recompile my webserver which uses CGo to embed libbrotli on my Pop!_OS 22.04 LTS machine, glibc 2.31 did not cut the required versions 2.32 and 2.34. As such, I chose to pull testing packages on my public-facing webserver:

# tail -n1 /etc/apt/sources.list
deb http://deb.debian.org/debian testing main

I find it an offence that ed was not present on my machine. And somehow the above borked my machine to the extent that systemd-resolved.service was suddenly missing and thus apt could not resolve deb.debian.org.

[2023-03-19] Starting to swap

My VPS (Debian 11.5) ran out of memory and had no zero bytes of swap set.

# swapon --show
# fallocate -l 8G /swapfile
# chmod 600 /swapfile
# mkswap /swapfile
Setting up swapspace version 1, size = 8 GiB (8589930496 bytes)
no label, UUID=cd0d1bde-a291-4eea-9fc8-092e7a4062fd
# swapon /swapfile

[2023-03-07] The three-bit colors

for m in 30 90; do for n in $(seq $((m)) $((m+7))); do printf '%2d \033[%dm########\033[m | \033[%dm        \033[m\n' $n $n $((n+10)); done; [ $m -eq 30 ] && echo; done

[2023-03-06] Git synchronisation sanity

$ echo '*** working tree' && git status --porcelain && echo -e '\n*** local' && git show-ref && echo -e '\n*** remote' && git ls-remote -q

[2023-03-01] Referential intransparency in Go's type system

Only the first of the following two Go programs compiles. Tested on Go 1.18--1.20.

package main; import "fmt"; func main() {                  if x := struct{}{}; true { fmt.Println(x) } }
package main; import "fmt"; func main() { type S struct{}; if x := S{}       ; true { fmt.Println(x) } }

[2023-02-25] Shell oddities

I just now realised the following:

$ export v=0
$ v=1 printf $v\\n
0
$ v=2 env | grep '^v='
v=2
$ v=3; printf $v\\n
3
$ v=4; env | grep '^v='
v=4

I. e. there is a discrepancy between processes interpreting the environment variables after a shell has spawned them and the shell itself subsituting variables when interpreting arguments.

$ v=4; v=5 v=6 echo $v v=7; echo v=8 $v v=9; env | grep '^v='

Cf. https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

[2023-02-24] Git adventures

Sometimes, skimming through git log, I spot a typo only a few commits back in a repository I am fine force-pushing. in a commit message. The following shows a potential git lens workflow.

$ HEAD=$(git log --format=%H -1) && git stash -u   # [!] loses staged/unstaged distinction
$ git log --format=fuller --graph --all
... find COMMIT_TO_AMEND ...
$ git reset --hard $COMMIT_TO_AMEND
$ git commit --amend
$ git cherry-pick $(git log --format=%H $COMMIT_TO_AMEND..$HEAD | tac | xargs)
$ git log --format=fuller --graph --all
... verify ...
$ git push --force && git stash pop

Cf. https://en.wikipedia.org/wiki/Bidirectional_transformation

[2023-02-23] Go maps are safe for concurrent read-only use.

In contrast to e. g. C++'s maps' operator[], go maps are not modified on read, making the naïve conception of maps as a concrete tree-like bit soup lead to the claimed behaviour.

Cf. https://groups.google.com/g/golang-nuts/c/HpLWnGTp-n8/m/hyUYmnWJqiQJ
Cf. https://en.cppreference.com/w/cpp/container/map/operator_at

[2023-02-22] Git squashing

I found the following test quite handy not to lose work.

$ git log --oneline -10
000000a (HEAD -> master) final-squashme
0000009 squashme
0000008 squashme
0000007 squashme
0000006 squashme
0000005 squashme
0000004 squashme
0000003 squashme
0000002 squashme
0000001 last-stable (origin/master, origin/HEAD)
$ find . -type f | grep -v '^\./\.git/' | xargs sha512sum | sha512sum
000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  -
$ git reset --soft 0000001
$ find . -type f | grep -v '^\./\.git/' | xargs sha512sum | sha512sum
000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  -
$ echo "((sha512sum's outputs MUST match))" >/dev/null
$ git commit -m new-stable
[master 000000b] new-stable
...

For origin-double-checking, I like to use git log --all --graph.

[2023-02-13] Extract .eml dates

grep -h '^Date:' -riI | sed 's/^Date: *//' | xargs -L1 -I{} -- date --date={} +'%Y-%m-%d %H:%M:%S' | sort

[2023-01-28] Generating random hex strings

$ hd /dev/urandom | sed 's/^[^ ]*  //; s/  |.*//; s/ //g; s/\(.\)/\1\n/g' | grep -v '^$' | head -n 12 | xargs echo | sed 's/ //g'

[2023-01-26] Using go's fuzzer

Only one fuzz test can be started, new interesting fuzzing arguments may be viewed via -test.fuzzcachedir.
Cf. https://go.dev/security/fuzz/ [accessed 2023-01-26]

$ go test -fuzz=EncodedMailHeader -test.fuzzcachedir=/tmp/fcd

[2023-01-23] Network listening

I today learnt that listening on localhost:8000 is not the same as listening on :8000; the firewall is not to blame.

[2022-12-29] A go toolchain bug

When reorganizing qep's project structure on disk, the following go toolchain bug tripped me up. Naturally, I abandoned work and focused on crystallizing it:

#! /bin/sh

# Jonathan Frech, 2022-12-29
# A demonstration of a go toolchain bug: a malformed replace directive leaks
# into unrelated error messages.

set -e
cd "$(mktemp -d)" && pwd


cat >bugged-output <<'EOF'
go version go1.19.3 linux/amd64

main.go:4:5: unknown@v0.0.0-00010101000000-000000000000: replacement directory /forbidden does not exist
main.go:6:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:7:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:8:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:9:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:10:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:11:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:12:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:13:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
main.go:14:5: unknown@v0.0.0-00010101000000-000000000000 (replaced by /forbidden): reading /forbidden/go.mod: open /forbidden/go.mod: no such file or directory
EOF


go version && echo

cat >go.mod <<'EOF'
module main

go 1.19

replace unknown => /forbidden
require unknown v0.0.0-00010101000000-000000000000
EOF

cat >main.go <<'EOF'
package main

import (
    "unknown"

    "unrelated-0"
    "unrelated-1"
    "unrelated-2"
    "unrelated-3"
    "unrelated-4"
    "unrelated-5"
    "unrelated-6"
    "unrelated-7"
    "unrelated-8"
)
EOF

go build

[2022-12-27] Merging git repositories

A month ago, I wrote a factoid about fusing git repositories using git cherry-pick. This of course modifies the committer's date (though at least keeps the author's date intact!). Today I discovered that git merge --allow-unrelated-histories is a more apt choice for combining parts of a project that co-evolved in separate repositories:

$ git remote -v
$ cd ~/git
$ git clone git@git.jfrech.com:~jfrech/crooked-with-a-pearl.git
...
$ cd crooked-with-a-pearl
$ mkdir pearl
$ ... extract, refactor slightly and prepare for transferal ...
$ ... such that only .git and pearl remain as top-level directories ...
$ git add . && git commit -am 'preparing for transferal'
...
$ git push
...

$ cd ~/git/shiny
$ git remote -v
...
$ git remote add transferal git@git.jfrech.com:~jfrech/crooked-with-a-pearl.git
$ git remote -v
...
$ git fetch transferal
$ [ ! -e pearl ] && git merge --allow-unrelated-histories transferal/master
...
$ [ -d pearl ] && git remote remove transferal

$ git remote -v
$ git log --graph
...
$ git push
...

[2022-12-10] Combining PDFs with qpdf

No, I am not talking about the convolution of probability density functions; I am talking about the unfortunetely standard format for information-interchange of physical-paper-imitating data BLOBs:

qpdf --empty --pages *.pdf -- combined.pdf

Ref. https://stackoverflow.com/a/53754681 [2022-12-10]

[2022-12-08] (Pseudo-)palindromic code golf tasks are non-trivial to define

I thought about defining a code golf taks in terms of properties of the source code and its reverse. Yet immediately one notes that few languages exhibit (pseudo-)palindromic keywords, most of them (i.e. APL or golfing languages) only one-character long ones. Thus the second idea was to adhere to (pseudo-)palindromicity over the line ordering, yet a C-style snippet alike

#define FORWARDS 1
int main() { puts(FORWARDS ? "f" : "-f"); }
#define FORWARDS 0

swiftly outs this idea as unfruitful.

[2022-12-04] Go defer and panic gotcha

I just read the other night, how [A] deferred [function] will run even if the critical section panics [...] [DK16]. Still, a setting distillable to the following had me contemplating reality:

package main

import "os"

func main() {
    defer os.Exit(0)
    panic("won't fire")
}

[DK16] Alan A. A. Donovan, Brian W. Kernighan: The Go Programming Language. Addison-Wesley, 2016. ISBN-13: 978-0-13-419044-0

[2022-11-26] Fusing git repositories one commit at a time

$ cd "$DESTINATION_REPO"
$ git remote add FUSE "$SOURCE_REPO"
$ git fetch FUSE
$ git cherry-pick f0f0c1bba79d28bc36e0ca1dae22c80a8e8f8349
... fixup ...
$ git remote remove FUSE

[2022-11-26] A shell one-liner to generate random hexadecimal data

xxd /dev/urandom | sed 's/^[0-9]*: //; s/  .*$//; s/ //g; s/\(.\)/\1\n/g;' | sed '/^$/d' | head -n40 | xargs echo | sed 's/ //g'

[2022-11-23] Installing go

# URL='https://go.dev/dl/go1.19.3.linux-amd64.tar.gz' CHECKSUM='1bf389df6d7efa6b54b04332c70356ee0d133753b1e58753e80ebafcff0f559c61223ddad3f5d024f0c538dbbd7d6ac92abb6b022f6a171a91a5ef39b0d82c9b' ; [ "$(curl -f#SL "$URL" | tee /tmp/go.tar.gz | sha512sum | cut -d\  -f1)" = "$CHECKSUM" ] && rm -rf /usr/local/go && tar -C /usr/local -vxzf /tmp/go.tar.gz

[2022-10-28] Jubilations

A long-standing (over a year!) validator bug has finally been resolved: https://github.com/validator/validator/issues/1166 ; I mailed Henri Sivonen to fix his HTML parser, but apparently my surmised root cause of this validator behaviour was wrong. Anyways, I am glad to be able to use color-scheme-dependant theme-colors without upsetting the validator.

[2022-10-22] Installing FreeBSD 13

A bit worryingly, FreeBSD 14's installer complained about a base.txz checksum mismatch (using the ftp://fpt5.de.freebsd.org mirror).

# TARGET=/dev/sdX SOURCE_XZ='https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/13.1/FreeBSD-13.1-RELEASE-amd64-mini-memstick.img.xz' SOURCE_SIZE='455889408' SOURCE_DIGEST='a519326bb0fcce5da4b86eb202894baafe12aa4f2d226c90f8db45aece731d0e54914340be84a2986c40fca81cc80b1bd6c21b0c3d9c0d25401c82ed9d2f756b' && [ "$SOURCE_DIGEST" = "$(curl -fsSL "$SOURCE_XZ" | xz -d | tee "$TARGET" | sha512sum | cut -d\  -f1)" ] && sync -f && [ "$SOURCE_DIGEST" = "$(head -c"$SOURCE_SIZE" "$TARGET" | sha512sum | cut -d\  -f1)" ] && echo success || echo corrupted

[2022-10-21] Installing FreeBSD 14

I today tried Guix, but I cannot get it to work without using a login manager, a category of software I despise. As such, the dreams of an FSF compliant and ethically sound GNU/Linux OS broken, I will turn my back on Linux.

# TARGET=/dev/sdX SOURCE_XZ='https://download.freebsd.org/snapshots/amd64/amd64/ISO-IMAGES/14.0/FreeBSD-14.0-CURRENT-amd64-20220930-42dc8696df5-258315-mini-memstick.img.xz' SOURCE_SIZE='499175936' SOURCE_DIGEST='780c92bbb6d3eb0d49d5f3c7061e4b4cd5ac33a3ec12404918491568e40dd21987298a0cbbfc592c07bae6eebf2fd0938fa2ad2a27330a0d69923671e7652c94' && [ "$SOURCE_DIGEST" = "$(curl -fsSL "$SOURCE_XZ" | xz -d | tee "$TARGET" | sha512sum | cut -d\  -f1)" ] && sync -f && [ "$SOURCE_DIGEST" = "$(head -c"$SOURCE_SIZE" "$TARGET" | sha512sum | cut -d\  -f1)" ] && echo success || echo corrupted

[2022-10-20] In praise of gnome-disks

I am ashamed to admit it: I am currently in possession of an electron-based brain employing Redmond malware in its tenth incarnation. However, I am at present, progressively, in the act of fleeing. Since I air-gapped the system and still want to extract remnants of what I did in the filthy times of old, I opted for a thumb drive. Mine being populated by Pop!_OS' installer, I needed to format it, preferably to a FATty type. Therein lied the trouble: I do not exactly know what I did wrong (possibly too excitetly unplugging or deleting the partition table one too many times), but neither Windows' formatter nor gparted were able to cope with my thumb drive's state. To the rescue came gnome-disks with its Debian 11 package called gnome-disk-utility. Though I am an avid GUI denier, I still format my drives in a clicky manner and GNOME's utility is both better designed than my previous two choices from an UX and aesthetic point of view and actually did the deed.

[2022-10-18] Version integrity and force-pushing

After yesterday's agonizing encounters with go's build system:

go: downloading pkg.jfrech.com/go/webutils v0.0.0-20221004154235-906e87a86844
webserver-binary imports
        page/dpfs_jfrech_com: pkg.jfrech.com/go/webutils@v0.0.0-20221004154235-906e87a86844: invalid version: unknown revision 906e87a86844

I today had the epitome that possibly my splendid habit of git comment -a --amend && git push --force could be at fault.
Deleting all go.sum files and everything below every go.mod's go version declaration, GOPROXY=direct GOSUMDB=off go mod tidy got ahold of my ordeal.

[2022-10-15] A html.spec.whatwg.org and validator.w3.org inconsistency

I found this behaviour the other day (Warning: Consider using the h1 element as a top-level heading only (all h1 elements are treated as top-level headings by many screen readers and other tools). ; From line 21, column 17; to line 21, column 20 ; <h1>Naviga); cannot report it as the validator does not throw an error, merely a warning.

[2022-10-15] A possible validator.w3.org bug

I would argue that this use of <meta name="theme-color" ... /> is valid and should not error.

Ref. https://github.com/validator/validator/issues/1166
Ref. https://github.com/validator/validator/issues/1424

[2022-10-14] CSS' url(...) is relative to the CSS source file, even when it is a data URI

After hours of work, I had converted knôtM 3 to using self-managed fonts and including them via a stylesheet represented by a data URI. After that, I was stumped for a while why no fonts loaded: using a url(/...) with an absolute path but relative host, I had specified a relative host to no URL, but an anonymous data URI. As so often, it is blatently obvious that this approach could never have worked.
Conclusio: Specify a full URL (or URI, but base64-encoding fonts incurs 4/3 data usage as well as probably breaking both the font and glyph cache) when using @font-face to include fonts from an anonymous, abstract place of pure data.

[2022-10-07] A curious GHC parse error

do { let _ = undefined; return () }

[2022-10-06] Get go's environment variables on the target system for cross-compilation

go tool dist env | grep -P '^(GOARCH|GOOS)'

[2022-10-05] base64 representation of a message digest

I would use `... | hex -d | base64`, yet -- to me bewilderingly -- `hex` does not exist. With the below approach of note is the double-escaped \ which forms printf character escape sequences: not for the shell, once for sed and once for xargs.

... | sha512sum | cut -d\  -f1 | sed 's/\([0-9a-f]\{2\}\)/\\\\x\1/g' | xargs printf | base64 -w0

[2022-10-04] Generating UUIDs

xxd /dev/urandom | grep -oP '(?<=: )[0-9a-f ]*(?=  )' | sed 's/ //g' | grep -oP '^.{12}' | head

[2022-09-26] Convert a .NEF to some renderable representation

for nef in *.nef; do dcraw -c -w "$nef" | convert ppm:- "${nef%.nef}.jpg" && echo >&2 "$nef"; done

Ref. https://www.dechifro.org/dcraw/

[2022-09-21] MIME type encodings

It is written text/plain; charset=utf-8, not text/plain; encoding=utf-8.

[2022-09-18] Expat license

Hosted by the FSF: https://directory.fsf.org/wiki/License:Expat.

[2022-09-14] Known hosts' key's fingerprints

$ ssh-keygen -lf ~/.ssh/known_hosts
$ ssh-keygen -lf ~/.ssh/known_hosts -F jfrech.com

[2022-09-11] Installing FreeBSD on a Raspi

# [ "$(curl -f#SL 'https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/13.1/FreeBSD-13.1-RELEASE-arm64-aarch64-RPI.img.xz' | tee /tmp/freebsd.img.xz | sha512sum | cut -d\  -f1)" = '761ca4f17da9b0da8a8b6418d0463152ba16147022b15549d7c8b1c3020a2f89c7d56c04cbc9bc1c5ec54dd4f563f7289313526aa0287e0afc43ecabd0f6e2f8' ] && xz -d /tmp/freebsd.img.xz && dd if=/tmp/freebsd.img of=/dev/sdb status=progress conv=fsync bs=4M && sync -f

Root's password is root.

[2022-09-02] Shell variable default

echo "${1:-$HOME/.config}"

[2022-08-23] Installing newer go

It supposedly fixed a file descriptor starving problem. Also, I wanted to use `encoding/xml`'s `func (d *Decoder) InputPos() (line, column int)`.

[ -w /usr/local ] && [ "$(curl -fsSL 'https://go.dev/dl/go1.19.linux-amd64.tar.gz' | tee /tmp/go.tar.gz | sha256sum | cut -d' ' -f1)" = '464b6b66591f6cf055bc5df90a9750bf5fbc9d038722bb84a9d56a2bea974be6' ] && rm -rf /usr/local/go && tar -C /usr/local -xzf /tmp/go.tar.gz && rm -f /tmp/go.tar.gz

[2022-06-26] Creating a temporary OpenSSH key

$ ssh-keygen -t ed25519 -f"$HOME"/.ssh/tempkey -N '' -C "delete one day after $(date)"
$ ssh-keygen -lf ~/.ssh/tempkey

[2022-06-23] Installing go

# [ -w /usr/local ] && [ "$(curl -fsSL 'https://go.dev/dl/go1.18.3.linux-amd64.tar.gz' | tee /tmp/go.tar.gz | sha256sum | cut -d' ' -f1)" = '956f8507b302ab0bb747613695cdae10af99bbd39a90cae522b7c0302cc27245' ] && rm -rf /usr/local/go && tar -C /usr/local -xzf /tmp/go.tar.gz && rm -f /tmp/go.tar.gz && echo 'successfully installed go1.18.3.linux-amd64'

[2022-06-17] Debugging git's operation

GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone https://git.jfrech.com/not-yet-implemented

[2022-05-25] LaTeX' backend may need to be run twice

Especially if tikz drawings jump unanchordly all over the page, running the backend again might jiggle everything in place. I wasted an undisclosed amount of hours doubting digital reality yesterday. (For bilbiographical references or indexes, a third run could even be necessary.)

[2022-05-23] Flashing a FreeBSD thumb drive (yet again; this time in one short line)

# curl -f#SL https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/13.1/FreeBSD-13.1-RELEASE-amd64-mini-memstick.img >/dev/sdb && sync -f

[2022-05-03] Checking all files are named after their hash

for f in *; do [ "$(sha512sum "$f" | cut -d' ' -f1)" = "$f" ] || echo FAILURE "$f"; done

[2022-04-23] Installing sbt on Debian

# bin='/usr/local/bin' ; [ ! -d "$bin"/sbt.pkg ] && { mkdir -p "$bin" && rm -rf /tmp/installing-sbt && mkdir -p /tmp/installing-sbt && curl -fsSL https://github.com/sbt/sbt/releases/download/v1.6.2/sbt-1.6.2.tgz | tar -C /tmp/installing-sbt -vxz && mv /tmp/installing-sbt/sbt "$bin"/sbt.pkg && rm -rf /tmp/installing-sbt && cd "$bin" && ln -sf sbt.pkg/bin/sbt ;} || echo aborting

[2022-04-14] Go 1.17 misleading compiler error

In Go 1.17, the following exclaims assignment mismatch: 2 variables but 1 value before noticing undefined: y. Go 1.18 does away with the rather unhelpful first message.

package main; func main() { x, ok := map[int]int{}[y] }

[2022-04-01] Haskell DSL meddling

What bit me today was -XCPP being dominant to -XQuasiQuotes (template haskell), meaning any DSLs not fixed under preprocessing will be meddled with -- resulting in nigh unpredictable outcomes.

[2022-04-01] NTFS corruption

Incriminating myself, I will admit that I do own a solid-state drive with a bootable and licensed copy of Windows 10. Yet, wanting to attempt to fix a bluetooth speaker's firmware, I yesterday was met with a nonstarting Windows with its recovery tool unable to help. Potentially replugging my four external drives and disc drive confused the Windows bootloader, yet after examining the partition using # mkdir MNT && mount /dev/sdd3 MNT, I was met with a frightening message similiar to this one. The most amusing part of this story -- I find -- is how the mount tool on Debian was able to explain to me what I had to do in Windows' recovery console: chkdsk /f C: -- it worked flawlessly and I could install Bose's evil spyware inside a bare-metal running massive hunk of spyware. Yet, the speaker is no longer supported so all efforts where at last in vein.

[2022-03-30] Types across Haskell module boundaries

Although it happens seldomly, when I define an integer constant in a module which does not enforce any further type requirements and want to use it in another module in the context of an Int -- for example (5 <) $ OtherModule.n -- the integer constant is unchangeably typed an Integer. I see how it would be difficult to type-infer across already compiled object files (and the implications for dependent object files with possibly type clashes throughout), yet the occasional irritation remains. I find sprinkling type annotations :: Int the most immediately useful.

[2022-03-28] The shell's new lines

Amazed by discovery: Instead of fumbling $ printf '%s\n%s\n' "$a" "$b", a wiser approach may be $ echo $"$a\n$b".

[2022-03-29] I noticed this shell's capability whilst reading Allan Odgaard's post macOS 10.15: Slow by Design. See also the bash manual (do not fret; $'...' appears not to be a bashism).

[2022-03-26] Fixing vim's Haskell syntax highlighting when working with quasi quotation

Quickly inside an editing session:

:syntax region TemplateHaskellQuasiQuote start='\[[a-z][a-zA-Z0-9_']*|' end='|\]' | highlight link TemplateHaskellQuasiQuote Comment

As an autocmd:

autocmd FileType haskell syntax region TemplateHaskellQuasiQuote start='\[[a-z][a-zA-Z0-9_']*|' end='|\]' | highlight link TemplateHaskellQuasiQuote Comment

[2022-03-15] Another vim annoyance

I also do not like how xxxx and 4x behave differently when at the end of a line:

wakka wik-wuk
            ^ `xxxx` results in:
wakka wik
wakka wik-wuk
            ^ `4x` results in:
wakka wik-wu

[2022-03-15] A vim bug

Especially when writing Haskell, I routinely get momentarily magnificently irritated by the "feature" that an "escaped" parenthesis does count towards matching parenthesis highlighting yet not towards %-jumping:

sortRecords = sortOn (\(Record { value1, value2 } -> f value2 value1))
--                   ^ when pressing `%` here, you jump to there ------^
--                     ^ pressing `%` fails here

[2022-03-14] non-descending ls

ls -d
Ref. https://www.linuxquestions.org/questions/linux-newbie-8/using-%27ls%27-to-list-only-the-current-directory-543135/#post2696628

[2022-03-08] rsync and slashes

$ rsync old/ new

[2022-03-01] A shell oddity

$ echo 'V=".  ."; echo $V' | bash
. .
$ echo 'V=".  ."; echo $V' | zsh
.  .

[2022-02-28] Switching again to Debian

# DEVICE='/dev/sde' ; lsblk ; curl -f#SL 'https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-11.2.0-amd64-netinst.iso' -o /tmp/debian.iso && [ "$(sha512sum /tmp/debian.iso | cut -d' ' -f1)" = 'c685b85cf9f248633ba3cd2b9f9e781fa03225587e0c332aef2063f6877a1f0622f56d44cf0690087b0ca36883147ecb5593e3da6f965968402cdbdf12f6dd74' ] && dd if=/tmp/debian.iso of="$DEVICE" bs=4M conv=fsync status=progress

[2022-01-08] A poor man's directory fingerprint

find <dir/> -type f | sed "s/^/'/; s/$/'/" | xargs -L1 sha512sum | sort

[2022-01-06] Screen resolution in X11

$ xwininfo -root | grep '^  \(Width\|Height\): [1-9][0-9]*$' | sed 's/.*: //' | tr '\n' 'N' | sed 's/N$/\n/; s/N/x/'

[2022-01-02] A changing Safari topbar look

<meta id="wakka" name="theme-color" content="#f90000">
<script><!-- function clr(r, g, b) { function f(n) { hex = (n & 0xff).toString(16); while (hex.length < 2) hex = '0' + hex; return hex }; document.getElementById('wakka').content = '#' + f(r) + f(g) + f(b); }; async function f() { for (var j = 0; j < 250; ++j) { await new Promise(r => setTimeout(r, 10)); clr(j, 0, 0); } }; f(); --></script>

[2022-01-03] Converting epoch to iso

date --date="@$(date +%s)"

[2022-01-02] An ssh-tunneled http reverse proxy using go

I just began tinkering with golang.org/x/crypto/ssh and find their reverse proxy capabilites amazing: when allowing the VPS' ssh deamon's GatewayPorts option

# sed --in-place /etc/ssh/sshd_config 's/^#GatewayPorts no$/GatewayPorts yes/' && systemctl restart sshd

the following go code can be run on a local machine, hooking this machine into the global network where the VPS resides:

// Jonathan Frech, 2022-01-02

// on the VPS' side:
//     # sed --in-place /etc/ssh/sshd_config 's/^#GatewayPorts no$/GatewayPorts yes/' && systemctl restart sshd

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "path/filepath"
    knownhosts "golang.org/x/crypto/ssh/knownhosts"
    ssh "golang.org/x/crypto/ssh"
)


func main() {
    privkeypath := "id_rsa"
    dotsshpath := filepath.Join(os.Getenv("HOME"), ".ssh")
    serveraddress := "jfrech.com:22"

    privkey, err := ioutil.ReadFile(filepath.Join(dotsshpath, privkeypath))
    if err != nil {
        log.Fatalf("could not read private key: %v", err)
    }
    signer, err := ssh.ParsePrivateKey(privkey)
    if err != nil {
        log.Fatalf("could not parse private key: %v", err)
    }

    hostKeyCallback, err := knownhosts.New(filepath.Join(dotsshpath, "known_hosts"))
    if err != nil {
        log.Fatalf("could not build hostKeyCallback: %v", err)
    }

    config := &ssh.ClientConfig{
        User: "root",
        Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
        HostKeyCallback: hostKeyCallback,
    }
    client, err := ssh.Dial("tcp", serveraddress, config)
    if err != nil {
        log.Fatal("could not dial: %v", err)
    }
    defer client.Close()

    l, err := client.Listen("tcp", "0.0.0.0:80")
    if err != nil {
        log.Fatalf("no tcp forward: %v", err)
    }
    defer l.Close()

    http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Bin ich schon drin?")
    }))
}

One may use # netstat -tlnp on the VPS' side to check ssh's gateway setting; 127.0.0.1:80 is a bad sign since the reverse proxy will not be accessible from outside the VPS' local address. 0.0.0.0:80 is what one wants to see (a very permissive mask).

[2021-11-22] A possible typo in Go's documentation

Currently, https://pkg.go.dev/net/http#Response reads in part

// Uncompressed reports whether the response was sent compressed but
// was decompressed by the http package. When true, reading from
// Body yields the uncompressed content instead of the compressed
// content actually set from the server, ContentLength is set to -1,
// and the "Content-Length" and "Content-Encoding" fields are deleted
// from the responseHeader. To get the original response from
// the server, set Transport.DisableCompression to true.
Uncompressed bool

Should it not say content actually sent from the server?

[2021-11-21] Disabling my Lenovo ThinkPad X250's trackpad

For nearly two weeks now, I own a refurbished ThinkPad. And whilst I am configuring dwm on my new portable machine, I tried myself at a concise awk expression to prove my red nub commitment.

xinput set-prop "$(xinput list | gawk '/Synaptics TM3075-002/ { match($0, /id=([0-9]*)/, arr); print arr[1] }')" 'Device Enabled' 0

[2021-11-04] Go reading and writing files

fileR, err := os.Open(filename)
/* equivalent to: `os.OpenFile(filename, os.O_RDONLY, 0)` */

fileW, err := os.OpenFile(filename, os.O_EXCL|os.O_CREATE|os.O_WRONLY, 0644)
/* note: `os.Create(filename)` is equivalent to `os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)`, opening in read-write mode and giving everyone read-write permissions

/* see also: https://pkg.go.dev/os#pkg-constants */

[2021-10-26] Shell case

case "$(uname)" in
    Darwin) echo 'Why not use a really free FreeBSD?' ;;
    *) echo 'non-specific uname' ;;
esac

[2021-10-12] Installing go

# [ $(id -u) = 0 ] && rm -rf /bin/go && curl -f#SL https://dl.google.com/go/go1.17.2.linux-amd64.tar.gz | tar xz -f - -C /bin && printf 'now add /bin/go/bin to your $PATH\n'

[2021-10-11]

https://play.golang.org/p/kv34cASB_0k

[2021-10-09] Halt Debian

systtetmctl halt

[2021-10-08] Installing Debian after all

Since Debian is only mainline-Linux and proprietary-possible nonfree, I decided to give it another try as my daily driver.

# [ -n "$(id -u)" ] && lsblk && printf 'flash to /dev/' && read DEVICE && lsblk | grep "^$DEVICE" && URL_IMAGE='https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-11.0.0-amd64-netinst.iso' && URL_CHECKSUMS='https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA512SUMS' && [ "$(curl -f#SL "$URL_IMAGE" | tee /tmp/debian.iso | sha512sum | cut -d' ' -f1)" = "$(curl -fsSL "$URL_CHECKSUMS" | grep "^[0-9a-f]\{128\}  ${URL_IMAGE##*/}$" | cut -d' ' -f1)" ] && dd if=/tmp/debian.iso of=/dev/"$DEVICE" bs=64K conv=fsync status=progress && sync

[2021-10-08] Guix on the Pinebook Pro

Over the past few days I have dreamt of a Guix running on a microSD card on my Pinebook Pro. After I yesterday bought a USB C to Cat adapter (ICY BOX IB-AC535-C), it finally takes shape.
I used the following Guix SD raw image: https://ci.guix.gnu.org/search/latest/image?query=spec:images+status:success+system:x86_64-linux+pinebook-pro-barebones-raw-image

... login as root, no password set ...
# cfdisk /dev/mmcblk1
... resize /dev/mmcblk1p1 to the full remaining size ...
# resize2fs /dev/mmcblk1p1
# ip link set eth0 up && dhclient
# guix pull

[2021-10-08] A true gigabyte of random data

$ mv /tmp/random.data "$(head -c 1000000000 /dev/urandom | tee /tmp/random.data | sha512sum | cut -d' ' -f1)".data

[2021-10-07] Entering the void

# lsblk ; read ; DEVICE=/dev/sdd ; ISO='void-live-x86_64-musl-20210218.iso' ; ISO_TEMP='/tmp/voidlinux.iso' ; [ "$(curl -f#SL "https://alpha.de.repo.voidlinux.org/live/current/$ISO" | tee "$ISO_TEMP" | sha256sum | cut -d' ' -f1)" = "$(curl -fsSL 'https://alpha.de.repo.voidlinux.org/live/current/sha256sum.txt' | grep "^SHA256 ($ISO) = [0-9a-f]\{64\}\$" | cut -d' ' -f4)" ] && printf 'successfully downloaded and verified hash: %s\n' "$ISO_TEMP" && dd if="$ISO_TEMP" of="$DEVICE" bs=16K status=progress

[2021-10-06] Giving Parabola another try

# lsblk | grep sdd ; printf 'Download parabola and burn it to /dev/sdd? (Enter or SIGINT) ' ; read && curl -fsSL https://redirector.parabola.nu/iso/x86_64-systemd-lxde-2019.06-pre/parabola-x86_64-systemd-lxde-2019.06-pre-complete.iso | dd if=/dev/stdin of=/dev/sdd bs=16M

[2021-10-06] Debian on a Raspberry Pi Zero

$ curl -fsSL https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip | gunzip - -c | sudo dd if=/dev/stdin of=/dev/sde bs=4M conv=fsync

Ubuntu did not work; possibly because I am using a Pi Zero (which appears to be equivalent to B+ image-wise)

$ curl -f#SL https://cdimage.ubuntu.com/releases/21.04/release/ubuntu-21.04-preinstalled-server-arm64+raspi.img.xz | xz -d > rp.img && sudo dd if=rp.img of=/dev/sde bs=1M status=progress

[2021-09-29] vim's standard syntax highlighting definitions

/usr/share/vim/vim82/syntax/

[2021-09-29] ansiclr

Since I no longer install my own jtool, the following one-liner is now useful.

$ curl -fsSL https://raw.githubusercontent.com/jfrech/jt/master/toolbox/ansiclr/ansiclr.c | gcc -x c - -o /tmp/ansiclr && /tmp/ansiclr

[2021-09-28] Hopes and dreams

The below invocations do not work. Apparently one has to do more than dd the image (ref. https://www.freshports.org/sysutils/u-boot-pinebookpro/; ref. https://ftp.openbsd.org/pub/OpenBSD/snapshots/arm64/INSTALL.arm64)

# curl -f#SL 'https://download.freebsd.org/ftp/releases/arm64/aarch64/ISO-IMAGES/13.0/FreeBSD-13.0-RELEASE-arm64-aarch64-PINEBOOK.img.xz' | xz -d - > /tmp/pbp.img && dd if=/tmp/pbp.img of=/dev/sde status=progress bs=64K
# curl -f#SL 'https://personalbsd.org/images/FreeBSD-aarch64-13.0-RELEASE-Pinebook-Pro-20210720.img.xz' | xz -d - > /tmp/pbp.img && dd if=/tmp/pbp.img of=/dev/sde status=progress bs=64K

[2021-09-27] A bash prompt

Since I am now heavily invested into Guix and the GNU ecosystem, I decided to write a bash prompt.

# Jonathan Frech, 2021-09-28
# a minimalistic two-line bash prompt; uses Unicode characters

export PROMPT_COMMAND='[ -f /tmp/fl ] || (echo LyogSm9uYXRoYW4gRnJlY2gsIDIwMjEtMDktMjggKi8KLyogZmwsIGZpbGwgbGluZSAtLSBmaWxsIHRoZSB3aG9sZSBsaW5lIHdpdGggZmFpbnRseQogICBjb2xvcmVkICdib3ggZHJhd2luZ3MgbGlnaHQgaG9yaXpvbnRhbCcgY2hhcmFjdGVycwogICAoZGVjaW1hbCBVbmljb2RlIGNvZGUgcG9pbnQgOTQ3MikgKi8KCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3lzL2lvY3RsLmg+CiNpbmNsdWRlIDx1bmlzdGQuaD4KCmludCBtYWluKCkgewogICAgc3RydWN0IHdpbnNpemUgdzsKICAgIGlvY3RsKFNURE9VVF9GSUxFTk8sIFRJT0NHV0lOU1osICZ3KTsKCiAgICBwcmludGYoIlwzM1tHXDMzWzkwbSIpOwogICAgZm9yIChpbnQgaiA9IDA7IGogPCB3LndzX2NvbDsgKytqKQoJICAgIHByaW50ZigiXHhlMlx4OTRceDgwIik7CiAgICBwcmludGYoIlwzM1ttIik7Cn0K | base64 -d - > /tmp/fl.c && gcc -O3 /tmp/fl.c -o /tmp/fl) ; printf "\33[90m\xe2\x80\xa2\33[m\n" && /tmp/fl'
export PS1='\[\e[G\e[90m\]╭────── \[\e[m\]\w\[\e[90m\] ─── \u@\h ─── \D{%Y-%m-%d %H:%M:%S} \[\e[m\]\n\[\e[90m\]╰─ \[\e[m\e[$((92-!!$?))m\]\$\[\e[m\] '

[2021-09-26] Burning a Guix thumb drive (again, now from within Guix)

Now I can use lsblk instead of FreeBSD's geom disk list.

$ guix install curl
$ lsblk
$ sudo su
# curl -f#SL https://ci.guix.gnu.org/search/latest/ISO-9660?query=spec:images+status:success+system:x86_64-linux+image.iso -o /tmp/guix.iso && dd if=/tmp/guix.iso of=/dev/sdd status=progress bs=64K

[2021-09-26] Burning a Guix thumb drive

# curl -f#SL https://ftp.gnu.org/gnu/guix/guix-system-install-1.3.0.x86_64-linux.iso -o guix.iso && dd if=guix.iso of=/dev/da0 status=progress bs=64K

[2021-09-25] Installing dig using apt

# apt install dnsutils

[2021-09-21] Installing Go

Since Debian's packages are so unbelievably outdated (go1.15.9 on a fresh installation of Debian 11 Bullseye), I have moved to installing binaries by hand.

rm -rf /bin/go /usr/local/go && mkdir -p /usr/local/go && curl -fsSL https://golang.org/dl/go1.17.1.linux-amd64.tar.gz | tar -C /usr/local -xz && ln /usr/local/go/bin/go /bin/go

[2021-09-07] Converting epoch to iso

date -r "$(date +'%s')" +'%Y-%m-%d_%Hh%Mm%Ss'

[2021-09-07] One of the most useful shell features

Even though I am aware of ${var%pat}, ${var%%pat}, ${var#pat} and ${var##pat} I still cannot remember which expression does which and always have to look it up. The trouble is, looking this feature up is no easy feat as it as far as I know has no distinctive name. As such, I have reproduced its documentation:

${var%pat}  remove the shortest match from the right
${var%%pat} remove the longest match from the right
${var#pat}  remove the shortest match from the left
${var##pat} remove the longest match from the left

As such, to get a filepath's parent directory one may use ${var%/*} and to get its filename ${var##*/}. Running the shell script

#! /bin/sh

fp=/parent/path/file
echo "$fp"
echo "${fp%/*}"
echo "${fp##*/}"

produces:

/parent/path/file
/parent/path
file

Ref. https://tldp.org/LDP/abs/html/parameter-substitution.html#PARAMSUBREF

[2021-09-01] More sane image writing

Consoluting the handbook (https://docs.freebsd.org/en/books/handbook/bsdinstall/#bsdinstall-usb), the following may be advisable:

dd if=FreeBSD-13.0-RELEASE-amd64-memstick.img of=/dev/da0 bs=1M conv=sync && sync

[2021-08-31] Flashing an image

For a long time, I have used balenaEtcher to flash bootable thumb drives on my MacBook. Yet I feel it is incredibly bloated. Thus I started to dd the image directly. lsblk or diskutil list are useful companions.

% thumbdrive='/dev/disk2' ; image='FreeBSD-13.0-RELEASE-amd64-mini-memstick.img' ; sudo dd bs=64k if="$image" of="$thumbdrive" && sudo head -c "$(wc -c "$image" | cut -d' ' -f2)" /dev/disk2 | cmp "$image" && echo 'successfully flashed thumb drive'

[2021-08-20] Paranoically erasing a 128MB SD card

% lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
...
sde      8:64   1 121.3M  0 disk 
...
% sudo dd if=/dev/urandom of=/dev/sde status=progress ibs=1 obs=1

[2021-08-17] Adding a JPEG's date, time and dimensions to its filename

find . | grep '\.jpg$' | while read f; do d="$(dirname "$f")"; b="$(basename "$f")"; mv "$f" "$d/$(identify -format '%[EXIF:DateTime] %wwx%hh' "$f" | sed 's/:/-/g; s/ /_/g')_$b"; done

[2021-07-18] Installing brave on Manjaro

Unfortunately, Manjaro no longer supports brave as a main pacman package. As such, it is probably most convenient to install it via paru (formerly yay). Since paru is not and most likely never will be in any official pacman repository, its installation is a bit more involved:

% tmp="/tmp/$(uuidgen)" && mkdir -p "$tmp" && cd "$tmp" && git -C "$tmp" clone https://aur.archlinux.org/paru.git && cd "$tmp/paru" && (makepkg -si || echo 'Have you run `# pacman -S base-devel`?') && paru -S brave-bin

[2021-07-01] German words with at least four vowels

% curl -s http://www.netzmafia.de/software/wordlists/deutsch.txt | grep -i '[aeiou]\{4\}' --color=always

[2021-06-22] Low color depth vim styling

Default color schemes can be found under /usr/share/vim/vim??/colors. I plan to create a minimalistic, low color depth scheme.

[2021-06-22] The missing Manjaro architect

Since Guix feels to bloated and iffy, I plan to move back to Manjaro. Yet I would like to use XMonad as my window manager. A few months or years ago, one was able to perform a guided non-graphical installation using Manjaro architect; this ISO has disappeared from manjaro.org yet is available on the experimental subdomain: https://hacked.manjaro.org/download/#architect. I am unsure if this ISO is up to date and/or it can be easily upgraded to a recent state.

I did however read that the XFCE ISO has an architect option. I will try this route before installing a potentially stale ISO. [2021-06-25] After having booted the XFCE ISO, I dug further and realized that Manjaro architect has been dropped as a project. What a shame.

[2021-06-21] Parabola GNU Linux-libre

Curiously, after having installed Parabola once and scrambled its keys, unable to recover since pacman did not even manage to install keys, I could not get Parabola to boot after GRUB. I now tried to install the boot loader under / and it worked! (I am currently using the bloated GUI install; https://wiki.parabola.nu/Get_Parabola#Parabola_SystemD_LXDE_ISO.) Apparently, two days ago the mirror switch redirected me to a flaky mirror and muddling with the mirror list manually made pacman lose confidence. Anyhow, a pacman -Syyu took a bit and https://wiki.parabola.nu/Installation_Guide#Verification_of_package_signatures's recommendation of installing pacman -Sy archlinux-keyring archlinuxarm-keyring parabola-keyring reduced the number of missing keys to one.

Annoyingly, some mirrors seem to be offline, leading to a error: failed to retrieve file '...' from redirector.parabola.nu : Operation too slow. Less than 1 bytes/sec transferred in the last 10 seconds.
I have not yet resolved the missing key issue and am left unable to update my system; one wiki thread I found is https://labs.parabola.nu/boards/5/topics/628; I will attempt to remedy the situtation using pacman-key --refresh.

I have abandonded Parabola since it feels to cumbersome. I will now install Guix, another supposedly free distribution.

[2021-06-19] Refresh pacman keys

After installing the bloated GUI variant of Parabola and fiddling with the mirrors via # vi /etc/pacman.d/mirrorlist, the error: key "sixteen hex digits" could not be looked up remotely crept up again and again. See also https://wiki.parabola.nu/Installation_Guide#Verification_of_package_signatures.
Alas, even pacman-key --refresh-keys && pacman -Syyu did not aid.

[2021-06-04] Disable Firefox 89.0's new Proton theme ([2021-08-15] Does no longer work in version 91.0.)

In effect, disable all boolean flags in about:config which match proton.
Cf. https://www.askvg.com/tip-restore-old-classic-theme-and-ui-in-firefox-89-and-later-versions/, accessed 2021-06-04

[2021-05-30] Avoiding metadata in tar balls using GNU tar

% directory=~/some-dir date=2021-05-30 tar --sort=name --owner=root:0 --group=root:0 --mtime="UTC $date" -vcf "$directory".tar "$directory"

[2021-05-26] An erroneous GHC source identification

Cf. https://blog.jfrech.com/242/

% printf 'j=\\\n0;import J\n' > /tmp/j.hs && ghc -cpp /tmp/j.hs
[1 of 1] Compiling Main             ( /tmp/j.hs, /tmp/j.o )

/tmp/j.hs:1:5: error: parse error on input ‘import’
  |
1 | j=\
  |     ^^^^^^

[2021-05-04] A complete standalone certbot invocation

% apt install --assume-yes certbot && certbot certonly --agree-tos --no-eff-email --email info@jfrech.com --standalone --preferred-challenges http --domains jfrech.com,factoids.jfrech.com

[2021-05-02] Follow a systemd log

% sudo journalctl -f -u wakka.service

[2021-04-27] A shell rc's ssh invoker

% echo 'eval "$(ssh-agent -s)" && ssh-add "$HOME/.ssh/github-ssh"' >> "$HOME/.shrc"

[2021-04-26] Slow snake script's scrambled symbols

import random;''.join(hex(random.randint(1,15))[2:] for _ in range(8))

[2021-04-26] FreeBSD font kerning problems

Even after installing Victor Mono through pkg install -y victor-mono-ttf, the kerning is still off. I do neither know the cause nor how to fix it. Two links regarding fonts I found are https://forums.FreeBSD.org/threads/howto-nice-fonts.2021/post-11892 and https://docs.freebsd.org/en_US.ISO8859-1/books/handbook/x-fonts.html

[2021-04-20] Another attempt at FreeBSD XMonad configuring

# pkg install ghc hs-xmonad hs-xmobar
# pkg install devel/pkgconf hs-cabal-install

$ cabal install --lib xmonad xmonad-contrib
% setxkbmap -layout de

[2021-04-18] Installing FreeBSD 13.0 amd64 mini-memstick

I felt I had to leave Manjaro xfce4 (replaced by XMonad) behind. As I tried to formulate in Cccc, I feel a deep dissatisfaction with computing, the pseudo-non-proprietary nature and general associated stigma with it. Since FreeBSD 13.0-RELEASE has been recently released (https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/13.0 states 2021-04-09 as a date), I decided to give it a try. In the following, I have documented my initial installation process, with a lot of details gathered from blog and BSD forum posts.

... booting into memstick ...
... FreeBSD greeter ...
... 1. Boot Multi user [Enter] ...
[Enter]
... Welcome ...
<Install> [Enter]
... Keymap Selection ...
(select keymap)
[Space] [Up] [Enter]
... Set Hostname ...
twr.jfrech.local
<OK> [Enter]
... Distribution Select ...
<OK> [Enter]
... Network Installation ...
<OK> [Enter]
... Network Configuration ...
<OK> [Enter]
<Yes> [Enter]
<Yes> [Enter]
<No> [Enter]
[Tab] [Enter]
... Mirror Selection ...
(select mirror)
<OK> [Enter]
... Partitioning ...
Auto (ZFS) [Enter]
... ZFS Configuration ...
>>> Install <Select> [Enter]
stripe <OK> [Enter]
(select the correct disk to format)
[Space] [Enter]
[Left] [Enter]
... Fetching Distribution ...
... Archive Extraction ...
... FreeBSD Installer...
Changing local password for root
New Password:*****
Retype new Password:*****
... Select local or UTC (Greenwich Mean Time) clock ...
<Yes> [Enter]
... Time Zone Selector ...
(select time zone) ...
... Time & Date ...
<Skip> [Enter]
<Skip> [Enter]
... System Configuration ...
[ ] local_unbound
[*] sshd
[ ] moused
[*] ntpdate
[*] ntpd
[*] powerd
[*] dumpdev
<OK> [Enter]
... System Hardening ...
<OK> [Enter]
... Add User Accounts ...
Username: j
Full Name: j
Uid (Leave empty for default): 
Login group [j]: 
Login group is j. Invite j into other groups? []: wheel video
Login class [default]: 
Shell (sh csh tcsh nologin) [sh]: 
Home directory [/home/j]: 
Home directory permissions (Leave empty for default): 
Use password-based authentication [yes]: 
Use an empty password? (yes/no) [no]: 
Use a random password? (yes/no) [no]: 
Enter password: *****
Enter password again: *****
Lock out the account after creation? [no]: 
...
OK? (yes/no): yes
adduser: INFO: Successfully added (j) to the user database.
Add another user? (yes/no): no
... Final Configuration ...
Exit <OK> [Enter]
... Manual Configuration ...
<No> [Enter]
... Complete ...
<Reboot> [Enter]

After reboot, one may configure the system:

$ su
# pkg install xorg x11/nvidia-driver
y

# echo 'font8x16="/usr/share/vt/fonts/vgarom-thin-8x16.fnt"' >> /etc/rc.conf
# echo 'kld_list="nvidia-modeset"' >> /etc/rc.conf

# echo 'vbe_max_resolution="1080p"' >> /boot/loader.conf
# echo 'kern.vty=vt' >> /boot/loader.conf
# echo 'nvidia_load="YES"' >> /boot/loader.conf

Installing xfce4 is a breeze:

# pkg install xfce4
# startxfce4

I have not yet gotten XMonad to work ... Something regarding unfindable dynamic libraries.

# pkg install xterm
# pkg install go

# pkg install ghc hs-xmonad hs-xmobar hs-cabal-install
# cabal update && cabal install xmonad xmobar
# pkg install xterm ghc vim konsole hs-xmonad hs-xmobar

Multiple ways to set the virtual terminal's font:

$ vidcontrol -f /usr/share/vt/fonts/vgarom-thin-8x16.fnt

$ vidfont
... VGAROM, 8x16 (thin) ...

# echo 'font8x16="/usr/share/vt/fonts/vgarom-thin-8x16.fnt"' >> /etc/rc.conf

[2021-04-16] Fix system time

% wrzl timedatectl set-ntp true
Ref. https://github.com/jfrech/wrzl

[2021-04-16] Creating a monocolored .png file using ImageMagick

% convert -size 1920x1080 canvas:'#123456' mono.png

[2021-04-15] A non-invisible XMonad.Prompt.ShellPrompt invocation

Run: konsole -e sh -c 'ls && sleep 1'

[2021-04-14] A golfing thought

Why does cc -xc -D'f(x,y,z)for(;*y;z++)x[z*=x[z]>0]=*y++;' =(echo 'main(){char X[99],Y[99];strcpy(X,"abcdefghijk");strcpy(Y,"wxyz");char*x=X,*y=Y;int z=4;f(x,y,z);puts(x);}') not seem to work?
Ref. https://codegolf.stackexchange.com/a/223125/73111

[2021-04-14] Degenerated structures on elliptic curves

Not verifying associativity is common, as it most of the time is a rather lengthy and uninsightful computation. Nevertheless, entrop-x has a short proof why not inverting the third intersection point in the origin (provided an elliptic curve in Weierstraß normal form, i. e. the origin is an inflection point) does lead to an algebraic structure worth studying on said elliptic curve: take any point A on the curve and look at B := A+A, that is the third point in the multiset defined by intersecting the tangent at A with the curve. Since no inversion is involved, symmetrically A+B = A holds. Assuming a group structure, one deduces A = A+B = A + (A+A), thus 0 = A-A = A+A = 2A and every element is of order <= 2.
Ref. entrop-x, 2017-12-16@07:41: https://crypto.stackexchange.com/questions/53974/when-adding-two-points-on-an-elliptic-curve-why-flip-over-the-x-axis#comment119429_53980

[2021-04-13] Closed-source, proprietary software for Ubuntu

Most pograms weighted by use are probably prorpietary. Most software left is open-source yet definitely not free. A well-known open-source software exclusive to a certain Redmond-based monopoly's cornerstone is Notepad++. Yet the orthoganality thesis applies: there is a closed-source, proprietary piece of software for Ubuntu (an OS which is not free, plainly free-er): Primo (ref. http://www.ellipsa.eu/public/primo/primo.html). It even comes with an EULA.

[2021-04-12] XMonad's prompt's font

After hours of unfruitful XMonad configuring, I added XPC { font = "xft:" } to my shellPrompt invocation (see https://hackage.haskell.org/package/xmonad-contrib-0.16/docs/XMonad-Prompt-Shell.html) and finally saw a prompt!

...
    , ((modMask, xK_p), shellPrompt def { font = "xft:" })
...

[2021-04-10] Fix TTY resolution

Alt+Ctrl+F2

% wrzl vim /etc/default/grub
... GRUB_GFXMODE=1920x1080
... GRUB_GFXPAYLOAD_LINUX=1920x1080

% wrzl update-grup && reboot

% setfont /usr/share/kbd/consolefonts/ter-112n.pdf.gz

[2021-04-03] Download all Shakespeareian sonnets

% curl -fsSL shakespeare.mit.edu/Poetry/sonnets.html | grep -o '^<DT><A HREF="[^"]*"' | grep -o '"[^"]*"$' | grep -o '[^"]*' | sed 's|^|shakespeare.mit.edu/Poetry/|' | xargs -L1 curl -fsSL > shakespeare.html

[2021-03-16] macOS Safari favicon behavior

macOS Safari may add a white background to a tab's favicon to apparently enhance contrast in dark mode, though the exact methodology by which this is achieved is not known to me.
One may define a favicon mask (<link rel="mask-icon" href="..." color="#ac0101">). This mask is displayed on the touch bar (for me it does not seem to be used for the pinned tab icon); yet only when exactly one tab is open and all favorite pages are shown. Open tabs are instead displayed as a page content preview.

[2021-03-10] Sprangling webby stars

for (var j = 0; j < 1024; ++j) document.getElementsByTagName('body')[0].innerHTML += '<div style="position: fixed; z-index: -8096; min-height: .1em; min-width: .1em; background-color: #aaaa88; left: ' + Math.random()*100 +'%; top: ' + Math.random()*100 + '%"></div>'

[2021-03-07] Take only the third page of a PDF file using qpdf

% qpdf --empty --pages in.pdf 3 -- out.pdf

[2021-02-26] Install Lagrange, a Geminispace browser, from the AUR

% rm -rf "$HOME/src/lagrange" && mkdir -p "$HOME/src" && cd "$HOME/src" && git clone https://aur.archlinux.org/lagrange.git && cd lagrange && sudo pacman --noconfirm -S base-devel && makepkg --noconfirm -si

[2021-02-25, 2021-02-26] LaTeX gender star typesetting

Die Last der \emph{Versager\textasteriskcentered{}innen}.

Ref. The Comprehensive LaTeX Symbol List.

[2021-02-25] validator.w3.org's hottest tips

[2021-02-18, 2021-02-09] GitHub SSH test

% printf 'Testing GitHub ...\n' && eval "$(ssh-agent -s)" && ssh-add "$HOME/.ssh/github-ssh" && ssh -T git@github.com

[2021-02-17] (La?)TeX non-breaking space and soft hyphen

I~became unrecog\-nizable.

[2021-02-12] Do not forget to display: block; an <img> tag

Else it may lead no unwanted whitespace.

[2021-02-09] Install zathura together with pdf-poppler (required to be able to read pdf documents)

% sudo pacman --noconfirm -S zathura zathura-pdf-poppler

[2021-02-09] Keep GitHub ssh access working

% eval "$(ssh-agent -s)" && ssh-add "$HOME/.ssh/github-ssh" && ssh -T git@github.com

[2021-02-06] Setup GitHub ssh access

% . =(curl -fsSL s.jfrech.com/github-ssh.sh)

[2021-02-06] Give ImageMagick more cache disk space

% sudo vim /etc/ImageMagick-6/policy.xml +66

[2021-02-04] Configure a fresh manjaro installation

% curl -fsSL s.jfrech.com/setup-manjaro.sh | sh

[2021-02-04] Installing the Win-10 GNU+Linux subsystem

No doubt it is a sin to make oneself dependent on proprietary Redmond software. However, what is one supposed to do if one's own state's institutions force one to use proprietary software? Is it really better to use Skype on an Ubuntu machine? I opted to keep my soul separated from "work" and thus begrudgingly installed Windows 10.
Yet I cannot and do not want to be able to stand PowerShell: Install "Debian" and "Windows Terminal" from the Microsoft Store (make sure to simply close the login request which pops up) and follow https://aka.ms/wslinstall: Run PowerShell as administrator (possibly one may also be able to use the Windows Terminal for this purpose) and run dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart. Then restart. Launch "Debian" and setup the GNU+Linux system. After installation, the Windows Terminal should supply "Debian (Ctrl+Shift+4)" as an option in the downwards facing arrow in the tab bar.
To be able to edit the Windows Terminal's configuration file, I also installed Notepad++: https://notepad-plus-plus.org/downloads/v7.7.1/. Of course, at first launch I had to immediately install an update. After having installed a program that can manipulate textual config files, I selected "Settings (Ctrl+Alt+,)" and edited line 11 to mention line 49's guid. This way, Windows Terminal always starts up with a Debian Bash prompt.

[2021-02-03] Useful curl invocations

% #     f: fail silently
% #      sS: silent mode yet still show errors
% #        L: follow links
% curl -fsSL 'https://...'

% # only usable in non-critical password usage scenarios
% #     u: set user name and password
% curl -u username:password -fsSL 'https://...'

[2021-02-03] Useful tar invocations

Creation

% ./generate-data.sh > data
% [ -e data.tar ] && exit 0

% # generate a tar ball yet compress it yourself
% # (`tar -z` may not imply `gzip --best`)
% #    v: verbosely
% #     c: create
% #      f: filename
% tar -vcf data.tar data
% gzip --best data

% # if `data` should not be removed
% gzip --best --keep data

Extraction

% #    v: verbosely
% #     x: extract
% #      f: filename
% tar -vxf data.tar

% tar -vxf data.tar.gz

[2021-02-02] Default vim settings

I never quite remember where the default vim settings are located. On my current Fedora 33 (x86-64) system, I commented out every single line in /etc/vimrc to remove the odd bloaty choices of Fedora. I am very certain I will soon switch away from Fedora, I have to admit not to grok its appeal.

[2021-02-02] Full-page screenshot on Chromium-based browsers

I wanted to screenshot a web page (i. e. generate a static .png image) yet found my screen to be too pixel-sparse for the entire page to be viewable at a reasonable non-blur-pixelated scale. As such, I seeked and found a solution: Ctrl+Shift+I to enter "developer tools", followed by Ctrl+Shift+M to "[t]oggle device toolbar". In the top bar, one may choose rendering approach, ficticious device width and zoom (I chose Responsive, 1000 x 1000 @ 150%) and is then able via a menu accessed by three vertical dots at the top-right of the web page window to "Capture [a] full size screenshot".

[2021-01-31] base64

Ref. https://tools.ietf.org/search/rfc4648

[2021-01-31] SVG references

[2021-01-29] List all files in all repositories which are not being tracked.

% find "$HOME/git" -mindepth 1 -maxdepth 1 -type d | xargs -L1 -I{} -- sh -c 'printf "\n\33[1m=== %s ===\33[m\n" "{}"; printf "\33[2m" ; git -C {} clean -xfdn ; printf "\33[m" ; git -C {} status -s ; git -C {} cherry -v'

[2021-01-26] Where does Brave store user data?

On my *nix-y system, I found it at "$HOME/.config/BraveSoftware/Brave-Browser".

[2021-01-25] How to view a singular file's git history?

% git log --follow -p <file>

TODO I am unsure what --follow and -p exactly do.

Related: https://stackoverflow.com/a/9807682

[2021-01-29] Starting a local network ssh daemon

% systemctl status sshd || sudo systemctl start sshd && systemctl status sshd
% ip addr | grep '^\s*inet\s\+'

[2021-01-31] Get ssh fingerprint

On a new connection, the keys should theoretically be certified. Even if I unwisely often assume no man-in-the-middle attack to be happening (esp. on local networks), verification is easily performed by using `ssh-keygen -l`:

% ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub

[2021-01-26] Consider marking C++ class constructors explicit.

NOTE. I am clearly misunderstanding explicit. This factoid is of little value.

If marked explicit, implicit type conversions are forbidden. Note: When initializing classes with numeric values, an explicit constructor may be suboptimal as it also restricts the number type, i. e. I thought the following would not compile:

class A {
    private: float x;
    public: explicit A(float const x) : x{x} { ; }
};
int main() {
    A a{0};
}

See also https://en.cppreference.com/w/cpp/language/explicit

[2021-01-26] Designing HTML anchors with cross-site privacy in mind

Since the web stems from a time of naïf optimism, many once well-ment features can be weaponized. As such, due diligence is required when crafting HTML anchors:

<a href="..." target="_blank" rel="external noreferrer noopener">

I am still deliberating and researching the optimal rel values. Some further ideas and links include:

[2021-01-29] Disabling brew's diagnostics

% brew analytics off

See also docs.brew.sh/Analytics.
Source: @article{en_2020-06-20_ct_homebrew-analytics,author={Crumbach,Ralf},title={Homebrew},journal={c't~; Magazin für Computer-Technik},date={2020-06-20},pages={8}}

Systems administration

[2021-01] Displaying traffic

I found bmon to be a nifty tool. One only has to realize that scrolling down is most likely beneficial.

Less immediately useful factoids

[2020-12-04] OEIS fake entry baiting

In OEIS sequence A074025, at first glance one might be surprised to read the entry 99999999999999999999. Disappointingly, one soon realizes this "term [to be] a fake" (quote retrieved 2021-01-29).

[2021-01-26] C++ default initialization versus declaration

Declaring is not not initializing; int x;. Yet {}-ing is zeroing: int x{}; int y{0}; int z(); int w(0);. Furthermore, std::vector<int> xs(5); forms a well-defined object, i. e. xs[3] == 0.

[2021-01-19] C++ stdlib vector element destruction

When a std::vector exceeds its capacity and needs to grow, it need not copy itself to a new memory block and then construct the pushed vector, but may do so in a potentially unintuitive order.
NOTE. An example may be of use.
NOTE. I ought to verify that the standard has no stance in this matter.