https://factoids.jfrech.com/

[2024-12-11] A curious cURL property.

It appears that cURL does not sanitize its -H arguments for spurious CRLF character sequences and blindly sticks them into the HTTP request body. Go's HTTP server, then, correctly rejects the HTTP request. However, a trailing CRLF isn't added by Go's HTTP server in this case---I assume in error. Cf. https://cs.opensource.google/go/go/+/refs/tags/go1.23.4:src/net/http/server.go;l=2058 [2024-12-11]

$ curl jfrech.com -H "x:y$(echo -e '\r\n')"
400 Bad Request$ 
$ curl --version
curl 7.88.1 (x86_64-pc-linux-gnu) libcurl/7.88.1 OpenSSL/3.0.15 zlib/1.2.13 brotli/1.0.9 zstd/1.5.4 libidn2/2.3.3 libpsl/0.21.2 (+libidn2/2.3.3) libssh2/1.10.0 nghttp2/1.52.0 librtmp/2.3 OpenLDAP/2.5.13
Release-Date: 2023-02-20, security patched: 7.88.1-10+deb12u8
Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd

Cf. https://github.com/golang/go/issues/70786 [2024-12-11]

[2024-12-10] Am I confused or is this a Go toolchain bug?

$ go install .
clock.go:10:5: missing go.sum entry for module providing package jfrech.com/hereday (imported by clock); to add:
	go get clock
$ cat go.mod
module clock

go 1.23.2

replace jfrech.com/hereday => pkg.jfrech.com/hereday v0.0.0-20240904082209-e7c7e4e3cee5
$ go get clock
go: added jfrech.com/hereday v0.0.0-00010101000000-000000000000

[2024-12-06] J'uis confus.

master* $ git stash
Cannot save the current status

[2024-12-05] Partly bundle

I went on holidays and couldn't push to some repositories. So I invented a scratch repository where I checked in partial bundles.

$ git bundle create 2024-12-04_06-27_repo.bdl origin/master..master

[2024-11-28] Fetching (quietly!)

$ for x in ~/git/*; do git -C $x fetch -q; done

[2024-11-21] Accumulated cruft

master $ du -hs . && git gc --prune=now --aggressive && du -hs
38M     .
Enumerating objects: 5477, done.
Counting objects: 100% (5477/5477), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5194/5194), done.
Writing objects: 100% (5477/5477), done.
Total 5477 (delta 3728), reused 1400 (delta 0), pack-reused 0
4.1M    .

[2024-11-21] Ich scheine, meinen Kopf verloren zu haben.

$ cd "$(mktemp -d)" && git init . && GIT_AUTHOR_NAME=author-name GIT_AUTHOR_EMAIL=author-email GIT_AUTHOR_DATE='1732180176 +0100' GIT_COMMITTER_NAME=committer-name GIT_COMMITTER_EMAIL=committer-email GIT_COMMITTER_DATE='1732180178 +0010' git commit --allow-empty --allow-empty-message -m '' && git symbolic-ref refs/HEAD HEAD
Initialized empty Git repository in /tmp/tmp.f3tfbRJnlf/.git/
[master (root-commit) ba1822c] 
 Author: author-name 
warning: refname 'HEAD' is ambiguous.
warning: refname 'HEAD' is ambiguous.

Noteworthily, git symbolic-ref HEAD2 HEAD silently does nothing (in error!).

[2024-11-18] Still waiting ...

$ hd /dev/urandom | grep -i '[7t]\.*h\.*[3e]\.*[o0]\.*d\.[0o]\.*r'

[2024-10-19] Install Go 1.23.2

$ echo 'URL="https://go.dev/dl/go1.23.2.linux-amd64.tar.gz" CHECKSUM="542d3c1705f1c6a1c5a80d5dc62e2e45171af291e755d591c5e6531ef63b454e" ; TMP="$(mktemp -d)" && [ "$(curl -fsSL "$URL" | tee "$TMP/go.tar.gz" | sha256sum | cut -d\  -f1)" = "$CHECKSUM" ] && rm -rf /usr/bin/go.toolchain /usr/bin/go && tar -C "$TMP" -xzf "$TMP/go.tar.gz" && mv "$TMP/go" /usr/bin/go.toolchain && ln -sf /usr/bin/go.toolchain/bin/go /usr/bin/go' | doas sh

[2024-10-13] Cannonball stacking in Mathematica/WolframLanguage

H:=3; Graphics3D[Join[Table[Table[Sphere[{x+1/2*j, y+1/2*j, 1/Sqrt[2]*j}, 1/2], {x, H-j}, {y, H-j}], {j, 0, H-1}]]]

[2024-09-10] Fedora is garbage.

I just let a system auto-upgrade from Fedora 38 to Fedora 40 and it kernel-panicked.

[2024-09-09] Sequential multifetch

$ ls -d ~/git/* | xargs -I{} git -C {} fetch

[2024-09-08] "$ export GOMAXPROCS="

Traces looked suspiciously flat; I had set it to one hours ago ...

[2024-09-06] Go performance tuning

I haven't yet tested it, yet "GODEBUG=sbrk" seems to have been potentially useful the last three days. Cf. https://pkg.go.dev/runtime [2024-09-06]

[2024-08-30] An ICE which is known yet still tells one to report it.

$ sh <<'EOF'
#! /bin/sh
#
# Jonathan Frech, 2024-08-30

cd "$(mktemp -d)"

export GOEXPERIMENT=aliastypeparams
go version

go mod init a

mkdir b
cat >b/b.go <<'EOGO'
package b

type T[V any] = S[V]

type S[V any] struct {
    X V
}
EOGO

cat >a.go <<'EOGO'
package a

import "a/b"

type T b.T[int]

func main() {
}
EOGO

go build
EOF
go version go1.23.0 linux/amd64
go: creating new go.mod: module a
# a
<unknown line number>: internal compiler error: panic: importing generic type aliases is not supported in Go 1.23 (see issue #68526)

Please file a bug report including a short program that triggers the error.
https://go.dev/issue/new

Cf. https://web.archive.org/web/20240830162518/https://github.com/golang/go/issues/68526#issuecomment-2251551529 [2024-08-30]

[2024-08-30] Non-roundtripping time zone data

$ cat local-mean-time-time-zone.go
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(1970, time.January, 1, 1, 0, 0, 0, time.Local)
	fmt.Printf("t=%s\n", t.GoString())

	zone1, offset1 := t.Zone()
	fmt.Printf("zone1=%q, offset1=%d\n", zone1, offset1)

	zone2, offset2 := time.Time{}.In(t.Location()).Zone()
	fmt.Printf("zone2=%q, offset2=%d\n", zone2, offset2)

	zone3, offset3 := time.Time{}.In(time.FixedZone(zone1, offset1)).Zone()
	fmt.Printf("zone3=%q, offset3=%d\n", zone3, offset3)
}
$ go run local-mean-time-time-zone.go
t=time.Date(1970, time.January, 1, 1, 0, 0, 0, time.Local)
zone1="CET", offset1=3600
zone2="LMT", offset2=3208
zone3="CET", offset3=3600

[2024-08-29] Updating Go

$ go env GOSUMDB
off
$ su -l j -c 'cd "$(mktemp -d)" && go mod init toolchain_update && go get go@1.23'
Password: 
go: creating new go.mod: module toolchain_update
go: updating go.mod requires go >= 1.23.0; switching to go1.23.0
go: downloading go1.23.0 (linux/amd64)
go: upgraded go 1.22.3 => 1.23.0
$ go version
go version go1.22.3 linux/amd64
$ ~/go/pkg/mod/golang.org/toolchain\@v0.0.1-go1.23.0.linux-amd64/bin/go version
go version go1.23.0 linux/amd64
$ doas ln -sf ~/go/pkg/mod/golang.org/toolchain\@v0.0.1-go1.23.0.linux-amd64/bin/go /usr/bin/go
doas (j@jfrech) password: 
$ go version
go version go1.23.0 linux/amd64

[2024-08-28] Imprecise Git error message

[1] gives multiple reasons for version >2, yet [2] only talks about the checksum algorithm.

[1] https://git.kernel.org/pub/scm/git/git.git/tree/bundle.c?id=159f2d50e75c17382c9f4eb7cbda671a6fa612d1#n526 [2024-08-28]
[2] https://git.kernel.org/pub/scm/git/git.git/tree/bundle.c?id=159f2d50e75c17382c9f4eb7cbda671a6fa612d1#n553 [2024-08-28]

[2024-08-28] Zero times

$ git version
git version 2.39.2
$ git log
commit b83711a25156e592478a33b6f01b9ad6c1a3bd2d (HEAD -> master, origin/master, origin/HEAD)
Author:  <>
Date:   Thu Jan 1 00:00:00 1970 +0000
master $ git cat-file -p b83711a25156e592478a33b6f01b9ad6c1a3bd2d
tree f2430429abb1bc13321010e6ca10369691ba7776
author  <> -62135596800 +0000
committer  <> -62135596800 +0000

$ git fsck
error in commit b83711a25156e592478a33b6f01b9ad6c1a3bd2d: badDateOverflow: invalid author/committer line - date causes integer overflow
Checking object directories: 100% (256/256), done.

[2024-08-28] hd superfluous newline

$ printf '\x78\xda' | hd
00000000  78 da                                             |x.|
00000002

[2024-08-27] When you retract everything.

$ go mod tidy
go: warning: "all" matched no packages

[2024-08-20] Vim is garbage.

Just now, Vim lied in its rendering. A text editor which displays something else than is in the buffer. I need to write Wimzig and turn my back against Vim!

echo eW91IGNhbiB0cnVzdNesID8gbm8gb25lCg== | base64 -d | vim -
f?

[2024-08-17] Goc error database: "path/to/source.go:L:C: pkg.Type is not a type"

May be caused by the "pkg" import being shadowed by a local variable.

[2024-08-17] Restructuring

$ find * -type f | grep '\.go$' | xargs -I{} sed --in-place 's!pkg.jfrech.com/...!pkg.jfrech.com/...!g'

[2024-08-16] "go doc" accepts "/."

$ go doc os/.SEEK_CUR
package os // import "os"

const (
        SEEK_SET int = 0 // seek relative to the origin of the file
        SEEK_CUR int = 1 // seek relative to the current offset
        SEEK_END int = 2 // seek relative to the end
)
    Seek whence values.

    Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd.

[2024-08-16] "godoc" is from 2013, I now want to use "pkgsite".

$ go install golang.org/x/pkgsite/cmd/pkgsite@latest && pkgsite -http=:8081 -open

[2024-08-15] Sysgit-testing pkg.jfrech.com/go/git

$ cd ~/git/go-git && go doc | grep -i sys | sed 's/\$//' | sh

[2024-08-08] Brave: Disallow certain webpage from using ECMAScript

Effectively functions as blocking websites which heavily rely on dynamicity (e.g. DOM hydration).

Settings > Privacy and security > Security > Site and Shields Settings > JavaScript > Not allowed to use JavaScript > Add

[2024-08-07] Go test coverage analysis with bundled packages

$ cd ~/git/go-git && \
>  go test ./... -coverpkg=./encoding/binary/,./encoding/binary/internal \
>  -coverprofile=/tmp/cover.out && go tool cover -html=/tmp/cover.out

Cf. https://stackoverflow.com/a/33457070 [2024-08-07]

"go test -coverpkg=all" Cf. https://go.dev/doc/go1.10#test [2024-08-07]

[2024-08-06] Super-user shell discarding local environment

$ su -

[2024-08-06] Fuzzing

$ while true; do find . -type f | grep '_test\.go$' | while IFS= read -r testdotgo; do grep '^func Fuzz[A-Za-z0-9_]\+(f \*testing.F) {$' "$testdotgo" | grep -o 'Fuzz[^(]*' | while IFS= read -r fuzztarget; do echo "package=$(dirname "$testdotgo") fuzztarget=$fuzztarget"; done; done | sort -R | head -n1 | sed 's!$!; echo "package=$package"; echo "fuzztarget=$fuzztarget"; go test "$package" -fuzz="$fuzztarget" -parallel=6 -fuzztime=10m!' | sh; done

[2024-08-04] Git uses prefix guessing?

$ git version
git version 2.39.2
$ git push --force-with-lease
Everything up-to-date
$ git push --force-with-leas
Everything up-to-date
$ git push --force-with-lea
Everything up-to-date
$ git push --force-with-le
Everything up-to-date
$ git push --force-with-l
Everything up-to-date
$ git push --force-with-
Everything up-to-date
$ git push --force-with
Everything up-to-date
$ git push --force-wit
Everything up-to-date
$ git push --force-wi
Everything up-to-date
$ git push --force-w
Everything up-to-date
$ git push --force-w
Everything up-to-date
$ git push --force-
error: ambiguous option: force- (could be --force-with-lease or --force-if-includes)
...

[2024-08-01] Turning a hexit stream into percent-encoded byte packets

I had seen ($) before in passing and always found it intriguingly beautiful. On a walk today, I realized how it enables one to utilize infinite lists of non-tabular types:

ghci> import Control.Monad (join)
ghci> join . zipWith ($) (cycle [("%" ++), id]) . fmap pure $ "abcdef0123456789"
"%ab%cd%ef%01%23%45%67%89"

Since fmap pure is not the prettiest, one can rewrite to join . zipWith ($) (cycle [\c -> ['%',c], pure]).

[2024-08-01] What an error ...

./SRC.go:L:C: implicit function instantiation requires go1.18 or later (-lang was set to go1.17; check go.mod)

[2024-07-31] Fuzz 'em all.

$ while true; do export FUZZ_TARGET="$(grep '^func Fuzz[A-Za-z0-9_]\+(f \*testing.F) {$' *_test.go | grep -o 'Fuzz[^(]*' | sort -R | head -n1)"; echo "$FUZZ_TARGET=$FUZZ_TARGET"; go test . -fuzz="$FUZZ_TARGET" -parallel=6 -fuzztime=10m || break; done

[2024-07-30] Garbage data

$ hd /dev/urandom | sed 's/^[^ ]*//; s/^ *//; s/|.*//; s/  / /g; s/ *$//; s/^/ /; s/ /\\x/g' | head
\x14\x6c\x3f\x4e\x28\x03\xfe\x16\x1d\x57\x71\x8c\xb1\x17\x6e\x74
\x68\x6c\xe1\xb3\xc8\x74\xe6\xdc\x26\x28\x5d\x57\xc3\x91\x4e\x09
\x71\xb2\x6d\x3f\xf5\x4f\xb4\xbc\x77\x01\xb7\xf3\x43\x65\x98\x1a
\xce\xd2\x48\xf2\x33\x89\x4d\x57\x75\x0c\x04\x32\x12\x2d\x52\xd4
\x89\x8a\x05\x14\xb9\x6a\x4d\xda\x62\xa5\x19\x93\xa4\x3e\x18\x5c
\xe7\x8f\x02\xd4\x9e\x3f\x92\x52\x40\x36\xc0\x99\xe0\xd1\x2f\x30
\xa5\x0a\x90\xf4\x31\xac\xa6\xc4\x6e\x61\xd7\x63\xaf\xdc\x72\x21
\xa6\x9b\x85\x36\x23\xda\x72\x80\x4d\xca\x98\xcb\x8b\xa8\xb7\x94
\x16\x96\xe9\x7e\x30\x20\xc4\xf3\xf0\x15\x02\xa5\x09\xa9\xcb\x64
\x5f\x59\x37\x84\x5c\x59\x59\x3e\xcd\x37\x32\x1e\x56\x20\xce\x00

[2024-07-23] Showing a Systemd unit's filepath

systemctl cat "$UNIT" | sed 's/^# //;q'

[2024-07-23] Messing with APT sources ...

Just using Google's DN server ("8.8.8.8") ... Who has deleted my resolver configuration? I have removed "testing" from "/etc/apt.sources".

# rm -f /etc/resolv.conf && echo nameserver 8.8.8.8 >/etc/resolv.conf && apt install --reinstall resolvconf network-manager libnss-resolve
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 libnl-route-3-200 : Depends: libnl-3-200 (= 3.4.0-1+b1) but 3.7.0-0.3 is to be installed
 libnss-resolve : Depends: systemd (= 247.3-7+deb11u5) but 255.4-1 is to be installed
E: Unable to correct problems, you have held broken packages.

[2024-07-23] What being cut off from the Internet entails

# systemctl restart resolved
Failed to restart resolved.service: Unit resolved.service not found.
# dpkg-reconfigure resolvconf
dpkg-query: package 'resolvconf' is not installed and no information is available
Use dpkg --info (= dpkg-deb --info) to examine archive files.
/usr/sbin/dpkg-reconfigure: resolvconf is not installed
# apt install resolvconf
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  resolvconf
0 upgraded, 1 newly installed, 0 to remove and 3 not upgraded.
Need to get 72.7 kB of archives.
After this operation, 204 kB of additional disk space will be used.
Ign:1 http://deb.debian.org/debian bullseye/main amd64 resolvconf all 1.87
Ign:1 http://deb.debian.org/debian bullseye/main amd64 resolvconf all 1.87
Ign:1 http://deb.debian.org/debian bullseye/main amd64 resolvconf all 1.87
Err:1 http://deb.debian.org/debian bullseye/main amd64 resolvconf all 1.87
  Temporary failure resolving 'deb.debian.org'
E: Failed to fetch http://deb.debian.org/debian/pool/main/r/resolvconf/resolvconf_1.87_all.deb  Temporary failure resolving 'deb.debian.org'
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

[2024-07-23] Swapping?

Why is # swapon /swapfile not reboot-persistent?

[2024-07-19] Swapping!

# [ "$(id -u)" -eq 0 ] && [ ! -e /swapfile ] && fallocate -l 32G /swapfile && chmod 0600 /swapfile && /usr/sbin/mkswap /swapfile && /usr/sbin/swapon /swapfile && /usr/sbin/swapon --show

[2024-07-17] Vim is a buggy mess.

$ hd /dev/urandom | vim

You get thrown into the second vtty screen, yet cannot interact with the editor. Screen resizing makes "hd"'s output visible.

[2024-07-14] Sometimes looking at source frightens; today it bewildered.

$ cd ~ && go test "$(echo -e '\x01')"
panic: path "\x01" not in error "invalid import path \"\\x01\"" [recovered]
        panic: path "\x01" not in error "invalid import path \"\\x01\""

goroutine 1 [running]:
cmd/go/internal/load.(*preload).flush(0xc000030950)
        cmd/go/internal/load/pkg.go:1132 +0x74
panic({0x9cef40?, 0xc000030a00?})
        runtime/panic.go:770 +0x132
cmd/go/internal/load.ImportErrorf({0x7ffc35246ace, 0x1}, {0xa9d423?, 0x1?}, {0xc0001a1240?, 0xc0001a15b8?, 0x0?})
        cmd/go/internal/load/pkg.go:542 +0x174
cmd/go/internal/load.(*Package).load(0xc00019a608, {0xba6e70, 0xf8d0c0}, {0x0, 0x1, 0x0, 0x0, 0x0, 0x0}, {0x7ffc35246ace, ...}, ...)
        cmd/go/internal/load/pkg.go:1949 +0x1214
cmd/go/internal/load.loadImport({0xba6e70, 0xf8d0c0}, {0x0, 0x1, 0x0, 0x0, 0x0, 0x0}, 0xc000030950, {0x7ffc35246ace, ...}, ...)
        cmd/go/internal/load/pkg.go:794 +0x546
cmd/go/internal/load.PackagesAndErrors({0xba6e70?, 0xf8d0c0?}, {0x0, 0x1, 0x0, 0x0, 0x0, 0x0}, {0xc0000307e0, 0x1, ...})
        cmd/go/internal/load/pkg.go:2882 +0xa2b
cmd/go/internal/test.runTest({0xba6e70, 0xf8d0c0}, 0xf1f4e0, {0xc0000222f0?, 0x9cef40?, 0x4c?})
        cmd/go/internal/test/test.go:701 +0x37b
main.invoke(0xf1f4e0, {0xc0000222e0, 0x2, 0x2})
        cmd/go/main.go:257 +0x5c4
main.main()
        cmd/go/main.go:175 +0x6d5

Cf. https://cs.opensource.google/go/go/+/refs/tags/go1.22.5:src/cmd/go/internal/load/pkg.go;l=539 [2024-07-14]

I classify this behaviour a bug.

[EDIT 2024-08-06] Cf. https://github.com/golang/go/issues/68737 [2024-08-06]

[2024-07-14] Installing a new yt-dlp

$ doas sh -c 'apt update && apt upgrade --assume-yes && apt autoremove --assume-yes'
...
$ yt-dlp --version
2023.03.04
$ [ "$(curl -fsSL https://github.com/yt-dlp/yt-dlp/releases/download/2024.07.09/SHA2-256SUMS | grep '\<yt-dlp_linux$' | grep -o '^[0-9a-f]*')" = 77c1571df6c29371e01c26c171ecd92d85aca7b8ae830841bb05adce68778798 ] && mkdir -p ~/.local/bin/ && [ "$(curl -fsSL https://github.com/yt-dlp/yt-dlp/releases/download/2024.07.09/yt-dlp_linux | tee /tmp/yt-dlp | sha256sum | grep -o '^[0-9a-f]*')" = 77c1571df6c29371e01c26c171ecd92d85aca7b8ae830841bb05adce68778798 ] && chmod +x /tmp/yt-dlp && mv /tmp/yt-dlp ~/.local/bin/
$ yt-dlp --version
2024.07.09

[2024-07-14] Coding in the Unix programming environment

$ cd ~/git/go-git/ && grep -rI '\.Checksummer()' | grep -o '^[^:]*' | xargs -I{} sed --in-place 's/\.Checksummer()/.NewChecksummer()/' {}

[2024-07-10] Delete large files

$ du -hs * | sort -h
...
$ du -hs * | sort -h | tail -n 3 | xargs rm -rf

[2024-07-10] Swap isn't for nothing.

Since using Go's embed.FS and my weblog being well over a few gigabytes, Systemd's OOM killer has in the past already sometimes shot down my webserver. Today it happened: my webserver couldn't get afoot even a second. I realized my VPS hadn't had any swap provisioned, so I quickly raced to get it back online:

webserver # swapon --show
webserver # fallocate -l 4G /swapfile
webserver # chmod 600 /swapfile 
webserver # mkswap /swapfile 
mkswap: /swapfile: warning: wiping old swap signature.
Setting up swapspace version 1, size = 8 GiB (8589930496 bytes)
no label, UUID=7f345750-6365-45c3-b5bd-e4f47e91ba8a
webserver # swapon /swapfile
webserver # swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   8G 524K   -2

[2024-07-08] Delete Git tags on the remote

$ git push origin --delete devel/jfrech

[2024-06-27] FreeBSD: restarting the network

After a long sleep, WiFi dropped:

$ doas service netif restart

[2024-06-23] Making a FreeBSD Live CD system on UFS writable

To e.g. mount via $ zpool import -a

$ mount -o rw /

Cf. https://forums.freebsd.org/threads/solved-mount-o-rw-doesnt-work.48081/ [2024-06-23]

(For ZFS Live CD systems, use zfs set readonly=off zroot and on non-FreeBSD systems mount -o remount,rw / may be useful.)

[2024-06-18] Scanning multiple Git repositories' statuses

cd ~/git/ && find . -maxdepth 1 -mindepth 1 -type d | LC_ALL=C sort | while read repo; do echo "### $repo"; git -C "$repo" status; echo; done

[2024-06-14] Dreaming of tools

When refactoring, I am often unsure if I have kept the semantics intact. Thus, a tool which fuzzes different versions of pure functions à la $ go test -run=./pkg/tobe/scrutinized/RefactoredFunc -noreg=7e2f7aef92cd858, where 7e2f7aef92cd858 is the old revision, could be a massive boon. Successful fuzzing wouldn't prove but indicate no regression took place.

[2024-05-27] Installing Go 1.22.3

ICE (cf. https://blog.jfrech.com/287/ [2024-05-27]) was already fixed, but I was on a lagging point release.

$ echo 'URL="https://go.dev/dl/go1.22.3.linux-amd64.tar.gz" CHECKSUM="8920ea521bad8f6b7bc377b4824982e011c19af27df88a815e3586ea895f1b36" ; [ "$(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' | doas sh

[2024-05-27] Internal Go compiler error

Cf. https://blog.jfrech.com/235/ [2024-05-27]

$ go version
go version go1.22.1 linux/amd64
$ cat /tmp/internal-compiler-error.go
package main

func main() {
    panic("?")
    closure := func() {}

    outer:
    for range 0 {
        goto outer
    }
    closure()
}
$ go run /tmp/internal-compiler-error.go
# command-line-arguments
CLOSURE [/tmp/internal-compiler-error.go:11:5:var closure func()]
<unknown line number>: internal compiler error: assertion failed

Please file a bug report including a short program that triggers the error.
https://go.dev/issue/new

[2024-05-25] Go documentation typo

$ sed 's/passed in slices/passed-in slices/g' --in-place https://cs.opensource.google/go/go/+/refs/tags/go1.22.3:src/slices/slices.go;l=341

[2024-05-24] Debugging flaky POP3 behaviour

$ openssl s_client -connect pop3.tal.de:995 -debug

[2024-05-20] Godoc on invisible stuff

$ cd ~/git/brief/ && godoc -http=:8082 & brave-browser --incognito 'http://localhost:8082/pkg/pkg.jfrech.com/brief/?m=all'

Cf. https://stackoverflow.com/a/67189854 [2024-05-20]

[2024-05-20] Vim is garbage.

I detest with a passion the pretentiousness of other people creating software which but evokes vertiginous disgust.

$ vim /tmp/.go
:vspli
iI won't be highlighted in the right split.ESCO/*
$ vim --version
VIM - Vi IMproved 9.0 (2022 Jun 28, compiled May 04 2023 10:24:44)
Included patches: 1-1378, 1499
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Huge version without GUI.  Features included (+) or not (-):
+acl               +file_in_path      +mouse_urxvt       -tag_any_white
+arabic            +find_in_path      +mouse_xterm       -tcl
+autocmd           +float             +multi_byte        +termguicolors
+autochdir         +folding           +multi_lang        +terminal
-autoservername    -footer            -mzscheme          +terminfo
-balloon_eval      +fork()            +netbeans_intg     +termresponse
+balloon_eval_term +gettext           +num64             +textobjects
-browse            -hangul_input      +packages          +textprop
++builtin_terms    +iconv             +path_extra        +timers
+byte_offset       +insert_expand     -perl              +title
+channel           +ipv6              +persistent_undo   -toolbar
+cindent           +job               +popupwin          +user_commands
-clientserver      +jumplist          +postscript        +vartabs
-clipboard         +keymap            +printer           +vertsplit
+cmdline_compl     +lambda            +profile           +vim9script
+cmdline_hist      +langmap           -python            +viminfo
+cmdline_info      +libcall           -python3           +virtualedit
+comments          +linebreak         +quickfix          +visual
+conceal           +lispindent        +reltime           +visualextra
+cryptv            +listcmds          +rightleft         +vreplace
+cscope            +localmap          -ruby              +wildignore
+cursorbind        -lua               +scrollbind        +wildmenu
+cursorshape       +menu              +signs             +windows
+dialog_con        +mksession         +smartindent       +writebackup
+diff              +modify_fname      +sodium            -X11
+digraphs          +mouse             -sound             -xfontset
-dnd               -mouseshape        +spell             -xim
-ebcdic            +mouse_dec         +startuptime       -xpm
+emacs_tags        +mouse_gpm         +statusline        -xsmp
+eval              -mouse_jsbterm     -sun_workshop      -xterm_clipboard
+ex_extra          +mouse_netterm     +syntax            -xterm_save
+extra_search      +mouse_sgr         +tag_binary        
-farsi             -mouse_sysmouse    -tag_old_static    
   system vimrc file: "/etc/vim/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -Wdate-time -g -O2 -ffile-prefix-map=/build/vim-JA6Vy9/vim-9.0.1378=. -fstack-protector-strong -Wformat -Werror=format-security -DSYS_VIMRC_FILE=\"/etc/vim/vimrc\" -DSYS_GVIMRC_FILE=\"/etc/vim/gvimrc\" -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 
Linking: gcc -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim -lm -ltinfo -lselinux -lsodium -lacl -lattr -lgpm 

[2024-05-20] Go doc spec

https://go.dev/doc/comment

[2024-05-20] Go lang spec

https://go.dev/ref/spec

[2024-05-20] Compression musings

When considering tabs versus four spaces, one argument for the former (besides gofmt-compliance) is reduced bytes in source files (I don't want to overwhelm alien historians in 3000 years with unnecessarily generated entropy). One question then is if after compression (i.e. Git database or transparent disk encryption), the same byte reduction is still guaranteed.

I have a hunch that no non-trivial compression algorithm (the identity encoding or bloating encodings surely satisfy the following) has the property that removing bytes before compression results in a byte reduction in the compressed representation. Or such an algorithm would need to give up usability for non-hyper-repetetive data.

[2024-05-20] Un e instable en l'anglais ?

"Parsable" yet "salvageable".

[2024-05-13] Fuzzing modules

fuzzmodule () { cd "$(mktemp -d)" && pwd && git clone -q "$1" ./repo/ && cd repo && find . | grep '_test.go' | while IFS= read -r testdotgo; do grep '^func Fuzz' "$testdotgo" | grep -o 'Fuzz[a-zA-Z0-9_]*' | while IFS= read -r fuzztarget; do echo "$(dirname "$testdotgo")" "$fuzztarget"; done; done | sort -R | sed q | while IFS=' ' read -r dir fuzz; do cd "$dir" && pwd && echo "$fuzz" && go test -fuzz='^'"$fuzz"'$' -fuzztime=10s -parallel=6 || return 1; done; }; while true; do fuzzmodule 'https://git.jfrech.com/~jfrech/brief.git' || break; done

[2024-05-02] Go and versions ...

$ go version && go build
go version go1.20.3 linux/amd64
go: errors parsing go.mod:
***/go.mod:3: invalid go version '1.22.1': must match format 1.23

[2024-04-28] Hidden Go feature

As of Go 1.22, time.ParseDuration's documentation doesn't mention that two different "mu" Unicode code points are recognized.

Cf. https://cs.opensource.google/go/go/+/refs/tags/go1.22.2:src/time/format.go;l=1576-1589 [2024-04-28]

[2024-04-28] Shell drop

$ drop () { awk "{if(NR>$1)print}" "${@:2}"; }

Cf. https://hackage.haskell.org/package/base-4.19.1.0/docs/Prelude.html#v:drop [2024-04-28]

[2024-04-24] Extract a PDF's last page with QPDF

$ SOURCE=source.pdf && { tmp="$(mktemp)" && n="$(qpdf --show-npages "$SOURCE")" && qpdf "$SOURCE" --pages . "$n-$n" -- "$tmp" && echo "$tmp" ;}

[2024-04-18] Go profiling.

$ go test ./exactly/one/package -coverprofile=/tmp/cover.out -cpuprofile=/tmp/cpu.out
$ go tool cover -html=/tmp/cover.out
$ go tool pprof -http=:8081 /tmp/cpu.out

$ go test ./... -coverprofile=/tmp/cover.out
$ go tool cover -html=/tmp/cover.out

[2024-04-17] It is a Git feature.

What is going on is that directory entries are sorted according to their name plus a trailing slash.
Cf. https://git.kernel.org/pub/scm/git/git.git/tree/tree.c?id=21306a098c3f174ad4c2a5cddb9069ee27a548b0#n99 [2024-04-17]

[2024-04-17] Installing Git from source

$ cd ~/mirrored.git/git/ && doas apt install --assume-yes libssl-dev libcurl4-openssl-dev

[2024-04-17] How did this happen?

When developing pkg.jfrech.com/go/git/edit, a test case based off of ~jfrech/brief.git didn't roundtrip. The reason was a non-canonical tree; I am fairly certain generated by standard Git (which version I unfortunately do not know). Note how "constants.go" is listed before "constants":

$ cd ~/git/brief/ && git cat-file -p 2cd4f18048d7796e6a052fb53c23611511d72d0a
040000 tree 44afdd97596ea8cec785ab0dbc71b8b9d18337f7    blobs
100644 blob f9b52c499bab4e7fe63725666be94c25b33b9e0e    briefroot.go
040000 tree c845b744ee6678022b8ad37a96ad9d2dcd56cf1f    cli
040000 tree 0c528cdf5b38096abb27d353d8a9f89f866dba8e    client
040000 tree 6f14e3c7cae15d428ab11f2ccc3a076177c20d13    cmd
040000 tree 17cc7b083aace860178b934e7ed56d6bb74dc36a    columnwriter
040000 tree 1d7078031f42e530c5adcdc690a36a586f72d986    config
100644 blob 80cc6978e2f56c744d5ba49be8317e1e05c9db9d    constants.go
040000 tree 4a933b059b09892763c75aac782290458f47d7a2    constants
040000 tree 33725ec54ba5604f10ef64f62aecf8814e44f4f3    decode
040000 tree 20a33dae0bd8e4d21fab71b93c4ba790525c4656    escape
100644 blob a56580fa1b8d1f9e406d2b60b4c3160913b3b871    go.mod
100644 blob 7020244b67af393a55ba22c5d3f91f22c136366e    go.sum
100644 blob 293d3a958e41ea63ee22a7d3f55863c3bb9da732    licence.txt
040000 tree 38a470d2eecaa17b0b61c65f0ef2f28551aa8d0b    linenormalisation
040000 tree 487a34aa8af26e70cab514e18d83a87e77c054f5    mailx
040000 tree a6a88772a08f4c833b73709099d839fc9ebbc4b4    markdownish
040000 tree e09fa29e0ac3b07be370b0bb1009d0fc157854f4    message
040000 tree 528dffaececcbe50ba55d7b67d53eb36480e93ee    network
040000 tree 7da19041bf5172cdb4fed353a5a74953d05ab37d    stdlibx
040000 tree 7eafc184ca8f0c4ba3d3f0fb3439f42d57a0b530    tequat
040000 tree b78f826846edab4e0db9a90e5f0af38341994260    util
040000 tree 455d02f22a81f616bd79caaa1d1119b025244304    validate

More surprisingly, this appears to be standard Git behaviour:

$ cd "$(mktemp -d)" && git version && git init && export GIT_AUTHOR_NAME=gan GIT_AUTHOR_EMAIL=gae GIT_AUTHOR_DATE='2024-04-17T00:18+0200' GIT_COMMITTER_NAME=gcn GIT_COMMITTER_EMAIL=gce GIT_COMMITTER_DATE='2024-04-17T00:18+0200' && mkdir a && touch a/b && git add . && git commit -m 1 && touch a.c && git add . && git commit -m 2 && git cat-file -p HEAD | grep tree && git cat-file -p HEAD^ | grep tree && echo && git cat-file -p 1222ef52a69967362e391785e5b2e57d3a43a55c && echo && git cat-file -p 878e27c626266ac04087a203e4bdd396dcf74763
git version 2.39.2
Initialized empty Git repository in /tmp/tmp.13oggYBQaq/.git/
[master (root-commit) a6cc959] 1
 Author: gan 
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a/b
[master 8acae20] 2
 Author: gan 
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a.c
tree 1222ef52a69967362e391785e5b2e57d3a43a55c
tree 878e27c626266ac04087a203e4bdd396dcf74763

100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    a.c
040000 tree 4277b6e69d25e5efa77c455340557b384a4c018a    a

040000 tree 4277b6e69d25e5efa77c455340557b384a4c018a    a

For only files, the behaviour is nothing out of the ordinary:

$ cd "$(mktemp -d)" && git version && git init && GIT_AUTHOR_NAME=gan GIT_AUTHOR_EMAIL=gae GIT_AUTHOR_DATE='2024-04-17T00:18+0200' GIT_COMMITTER_NAME=gcn GIT_COMMITTER_EMAIL=gce GIT_COMMITTER_DATE='2024-04-17T00:18+0200' && touch a aa && git add . && git commit -m c && git cat-file -p "$(git cat-file -p HEAD | grep tree | sed s:tree.::)"
git version 2.39.2
Initialized empty Git repository in /tmp/tmp.ae7zS7zHql/.git/
[master (root-commit) 7255e1b] c
 Author: gan 
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a
 create mode 100644 aa
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    a
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    aa

What is going on???

master $ cd "$(mktemp -d)" && git version && git init && GIT_AUTHOR_NAME=gan GIT_AUTHOR_EMAIL=gae GIT_AUTHOR_DATE='2024-04-17T00:18+0200' GIT_COMMITTER_NAME=gcn GIT_COMMITTER_EMAIL=gce GIT_COMMITTER_DATE='2024-04-17T00:18+0200' && mkdir a && touch a/a a. && git add . && git commit -m c && git cat-file -p "$(git cat-file -p HEAD | grep tree | sed s:tree.::)"
git version 2.39.2
Initialized empty Git repository in /tmp/tmp.hT42Xt2IRr/.git/
[master (root-commit) e648bce] c
 Author: gan 
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a.
 create mode 100644 a/a
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    a.
040000 tree 496d6428b9cf92981dc9495211e6e1120fb6f2ba    a
master $ cd "$(mktemp -d)" && git version && git init && GIT_AUTHOR_NAME=gan GIT_AUTHOR_EMAIL=gae GIT_AUTHOR_DATE='2024-04-17T00:18+0200' GIT_COMMITTER_NAME=gcn GIT_COMMITTER_EMAIL=gce GIT_COMMITTER_DATE='2024-04-17T00:18+0200' && touch a a. && git add . && git commit -m c && git cat-file -p "$(git cat-file -p HEAD | grep tree | sed s:tree.::)"
git version 2.39.2
Initialized empty Git repository in /tmp/tmp.tdyM6oqJ4U/.git/
[master (root-commit) 440f1e8] c
 Author: gan 
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a
 create mode 100644 a.
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    a
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    a.

[2024-04-15] Go documentation nit-pick

https://pkg.go.dev/builtin@go1.22.2#string says "A string may be empty, but not nil.". The same sentence applies to a slice of bytes, though with a different meaning.

[2024-04-10] Installing Go 1.22

% doas sh -c 'set -e; [ "$(id -u)" -eq 0 ] || { echo "insufficient privileges"; exit 1; }; [ ! -d /usr/local/go ] || { echo "go already installed"; exit 1; }; rm -f /tmp/go.tar.gz && checksum="$(curl -fsSL https://go.dev/dl/go1.22.2.linux-amd64.tar.gz | tee /tmp/go.tar.gz | sha256sum | grep -o "^[0-9a-f]\{64\}")"; [ "$checksum" = 5901c52b7a78002aeff14a21f93e0f064f74ce1360fce51c6ee68cd471216a17 ] || { echo "bad checksum"; exit 1; }; cd /usr/local && tar xf /tmp/go.tar.gz; [ -e /usr/bin/go ] || { cd /usr/bin && ln -sf /usr/local/go/bin/go; }; go version'

[2024-04-09] Names in Go's type system

I today learnt that type T S and type T = S are two different things.
Cf. https://go.dev/ref/spec#Alias_declarations [2024-04-09]

[2024-04-09] Asserting non-nil receivers in Go

I recently started using

func (t *T) M() {
    _ = *t
    // ...
}

to assert the method is called on a non-nil type. Maybe I should instead be using the much more mysterious

func (t *T) M() {
    t = &*t
    // ...
}

. Note that "&*" can be repeated arbitrarily often.

[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-30]

$ ltrace a.out

[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-20] Shell

set -o pipefail
shopt -s failglob
set -u

set -e

[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-11-06] A Vim syntax highlighting bug for Go source.

T{0,}.f(), T{0x1,}.f()

[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.