Nothing Times

Macro detour

There's tons to be said about macrophotography, and I don't intend to cover much of anything here.

The higher your focal length, the more magnification you get, but the less of the image is in focus.

The more you open up your aperture, the more light gets in, but the less of the image is in focus.

The smaller the object, the more magnification you need, and the more light you need to get in.

Already at half-macro or 1÷2 magnification (on a 36✕24mm sensor, capturing a surface of 72✕48mm), you'll find that opening at f/4, the depth of field is rather narrow:

Small flowers

Flow gynoecium

Things get wilder at 2.5✕ ultramacro (on a 36✕24mm sensor, capturing a surface of 14.4✕9.6mm) and f/4. For an object of relative depth (not very flat in the much narrower plane of focus), a couple of options are available:

We do the latter here using Helicon Focus. Here are 80 frames shown at 5 frames per second:

And the picture they combine to form:

Lighter

As magnification keeps increasing, photography gets harder: it requires extensive preparation including cleaning (very poorly done here), and working around vibrations through dozens and dozens, sometimes hundreds of frames.

Pentax K10D

What a trip down memory lane! My first digital camera in all its CCD, APS-C, 10MP, 2006 glory.

Pentax K10D

Here, equipped with a SMC Pentax-A 1:4 70-210 and compared with today's Sony α7R V equipped with the FE 4/70-200 Macro G OSS II.

Petit Casino

70mm f/4; Pentax 1/60s, Sony 1/200s. The difference between full frame and APS-C explains different zooms at same focal distance.

Pentax

Store front, Pentax

Sony

Store front, Sony

Mint in “macro”

70mm f/4, both 1/60s.

Pentax

Plant closeup, Pentax

Sony

Plant closeup, Sony

Made 1000 Teekos… Now what?

After my favourite video games, Tetris and N++, time to post about my favourite board game.

My first encounter with Teeko was in 2016, running into its Wikipedia page and devouring Blake Eskin's 2001 WaPo article.

After a journey of many seasons, I'm running an online version, and own over 900 physical copies of my own take (as a few were gifted or traded).

Teeko in its case, near a deck of cards and a chess clock

Teeko unpacked: a textile board, 2✕4 pieces

It feels like merely the beginning though.

Online version: needs work!

The online version was built around my personal desire for remote play, and to turn my phone into a board at an instant's notice. It's functional for both. But…

Physical version: needs distribution?

The original trademark, registration #519087, expired in 2021. I have no problem distributing the game under its original name, and my design is distinct enough.

The stocks for boards, pieces, and bags are living in my bedroom closet. I have yet to print rules, and some assembly is required, but it's otherwise ready.

You can write to preorders@teeko.cc, but I have no concrete plans to distribute it beyond hand-delivering it around me at the moment.

Missed in Toronto

Of the many places I've visited in Toronto, a few instantly come to mind as dearly missed.

Granted, they're all from or near my old neighbourhood. But that only makes visiting them all easier.

Egg Club

BLT sandwich

Yes, it's a promotional photo. But that's the real deal.

If you're into the premise, every sandwich on their menu is fantastic.

Don't miss their hash browns. They come in the menu offer, unfortunately with brewed coffee that's only so-so.

Page One Cafe

Page One's front

Image from AccessTO

A cafe + bar. Despite living in San Francisco before, this is where I finally got into speciality coffee. Nice collection of typewriters.

Tsujiri

Matcha parfait

Image from Tripadvisor

I love matcha in all its forms. From o matcha to parfaits and shaved ice through lattes and cakes, I've had immense joy going through Tsujiri's menu.

Icha Tea

Icha Tea's counter

Image from blogTO

A bit further west from the rest, very much worth the walk. Great selection of premium teas served gongfu, delicious-looking desserts (never tried), a calm atmosphere, laptop-friendly.

N++: platforming perfection

Tetris got its post; time to cover my other favourite video game.

N++ is, in my opinion, the best platforming game ever made.

Launched under the Metanet Software umbrella, the third in a series of excellent games by Canadian duo Mare Sheppard and Raigan Burns, it features instant restarts upon failure, great physics, simple and elegant visuals, an addictive soundtrack, no scrolling, and pure determinism.

Once introduced to all the elements that can appear in a level, you can understand each new level through visual inspection before it starts. No surprises. Easy to learn but hard to master. Everybody will find their skills challenged here.

The level editor with online sharing complements thousands of levels of increasing difficulty, separated between solo, co-op and race categories, and only cleared by series of 5.

If you play one platformer in your life, make it N++.

Switch trailer

GDC talk

Decades of calculators

Given how slow my CASIO PB-700 was at plotting graphs, around age 8, my parents upgraded me to the Sharp EL-9400 (manual).

Sharp EL-9400

It was a big step up for math, but barely programmable. I wanted a fast BASIC playground.

After a lot of starring in stores and begging, I received the dream machine: the TI-92 Plus (manual). It was a TI-89 in the body of a TI-92. Fantastic machine to code in BASIC and, as I discovered after breaking an arm, take notes in class.

TI-92 Plus

Came with a powerful Symbolic Algebraic System and Cabri Géomètre (a brilliant app to construct geometry). Once I discovered how to transfer files from the Internet onto it, a lot of games followed.

It lasted quite a few years. When it finally gave up, I immediately replaced it with its successor, the TI Voyage 200 (manual), which I've kept to this day.

TI Voyage 200

Smaller form factor but AAA batteries instead of AA, double the flash, a really minor revision.

In my adult life, having lost interest in calculators for anything but quick calculations on the go, and having embraced RPN to the point of implementing a postfix language for fun, I've acquired a HP Prime (manual).

HP Prime

Sadly, I don't care to get past the home screen anymore.

PB-700: 1983 pocket computer

side.avif

My first computer, or what I remember as such, is older than me. Passed down by my father, it was made by CASIO in Japan in 1983, the year System V launched.

200 × 88 × 23 mm, 4 KB of RAM, 4 lines of 20 characters or 32 lines of 160 pixels, with optional printers, tape, and RAM expansions I never saw.

Mine still works great today. And by great, I mean that plotting sin(x) and cos(x) across the screen in BASIC, highlights of my childhood, still takes mere minutes to complete.

Overview

CoverFrontBack, openedContrast controlPort

10 PRINT

10 PRINT "HELLO"20 GOTO 10Running

Booklet (in French)

Booklet coverBooklet 1Booklet 2Booklet 3Booklet 4Booklet 5Booklet 6Booklet 7Booklet 8Booklet 9Booklet 10Booklet 11

Tetromino galore

I've been mesmerised by Tetris for as long as I can remember.

Nowadays I play a lot of the open source Apotris on Analogue Pocket, Tetris Effect Connected on TV, and the occasional Puyo Puyo Tetris on Switch.

I'm fairly terrible at those, but who cares? It's fun with friends, it's fun when I have a few minutes on the go.

Apotris

Apotris in particular deserves a shoutout. You can play it for free on any potato, even from your browser.

Some videos copied straight from their homepage:

Soon, Tetris Forever

I can't wait for Tetris Forever to come out.

Grenoble, France

Grenoble seen from Bastille

Come to Grenoble, we have bubbles!

Grenoble-Alpes Métropole is an urban area of around 445,000 people surrounded by mountains.

Ranked #1 city for quality of life by Oxford Economics, it welcomes around 65,000 students every year.

Isère and Bastille

It has great museums, a vibrant cultural scene.

Musée de Grenoble

Bicycle lanes abound and public transportation is plentiful. History and nature are never far away.

Château de Vizille

Vizille

Big downside of the city: it's really hot in the summer.

Recommendations

La Rivière des Parfums

Front of La Rivière des Parfums

La Rivière des Parfums is a casual Vietnamese restaurant in Grenoble, France.

It's a small place with a few tables and a counter. The menu is simple, the food is delicious. The staff is friendly and the service is fast.

Super affordable. Their vegetarian bò bún, plenty enough for a meal, is 8€.

Bò bún, as servedBò bún, stirred

My fish shell

After many years on an ever-growing zsh configuration, I switched to fish a few years ago.

While perfectly satisfied with my setup, I wanted something I could recommend to a beginner. fish's simplicity and modern defaults seem like a much better starting point if eschewing POSIX compatibility.

My configuration hasn't grown much since, but a few quality of life improvements have accumulated, so I figured it is worth sharing.

Installs on Apple Silicon macOS

Let's assume you're starting from scratch and want to adopt all my suggestions. Open Terminal.app and run the following:

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
$ /opt/homebrew/bin/brew install aria2 bat delta direnv eza fish fzf keychain mise tig wezterm zoxide
$ chsh -s /opt/homebrew/bin/fish

~/.wezterm.lua

Most likely, you'll need to choose another font on line 3.

Unless, of course, you're interested in purchasing PragmataPro, a most excellent project I use nearly everywhere (eg my main site).

local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.font = wezterm.font 'PragmataPro Liga'
config.font_size = 14
config.hide_tab_bar_if_only_one_tab = true
config.native_macos_fullscreen_mode = true
config.pane_focus_follows_mouse = true
config.use_fancy_tab_bar = false
config.window_decorations = 'RESIZE'
config.window_padding = { left = 0, right = 0, top = 0, bottom = 0 }
return config

~/.config/fish/config.fish

I made it so it could be copied anywhere; none of the tools need to be installed, but they will be enabled if they are.

if type -q /opt/homebrew/bin/brew; /opt/homebrew/bin/brew shellenv       | source; end
if type -q keychain;               keychain --eval --quiet --inherit any | source; end
if type -q direnv;                 direnv hook fish                      | source; end
if type -q fzf;                    fzf --fish                            | source; end
if type -q zoxide;                 zoxide init fish                      | source; end
if type -q mise;                   mise activate fish                    | source; end
if type -q caniuse;                caniuse --completion-fish             | source; end
  1. The first line enables Homebrew on Apple Silicon macOS.
  2. keychain starts SSH and GPG agents as needed.
  3. direnv automatically sets up environments per project.
  4. fzf is a fuzzy finder that can be used to search for files and commands.
  5. zoxide speeds up file system navigation. I barely cd anymore.
  6. mise manages versioned toolchains per project.
  7. caniuse is caniuse.com for the command line.

We've reached the right step to switch from Terminal.app and zsh to WezTerm and fish. Close Terminal.app and start WezTerm before we move along.

Install node and caniuse through mise

> mise use -g node@latest
> npm install -g @bramus/caniuse-cli

~/.config/fish/functions/

All my functions worth sharing are saved aliases, so I provide commands to recreate them.

c.fish, g.fish

clear the shell, invoke git in one character.

> alias --save c clear
> alias --save g 'command git'

cat.fish

Replace cat with bat. Use /bin/cat when you need the real thing.

> alias --save cat bat

dl.fish

Download files with aria2.

> alias --save dl 'aria2c -x5 -j5'

ls.fish

Use eza instead of ls.

> alias --save ls 'eza --color=always --icons=always --long --git'

Leverage eza and bat in fzf

> set -U FZF_ALT_C_OPTS  "--preview 'eza --tree --color=always {}'"
> set -U FZF_CTRL_T_OPTS "--preview 'bat -n --color=always --line-range :500 {}'"

Get rid of the greeting

I don't need to be welcomed and invited to type help every time.

> set -U fish_greeting

~/.ssh/config extracts

I like my keys to be added to the agent automatically on first use, for host keys to be automatically accepted for new hosts, and to minimize bandwidth consumption.

AddKeysToAgent yes
Compression yes
StrictHostKeyChecking accept-new

~/.gitconfig extracts

With this configuration in place, git help config should open a page in your browser. I won't describe every detail, but a few essentials.

Only including 2 aliases, ss and sss, as everyone should know how status offers a compact output with -s and -b, and is sped up by -uno to avoid looking at the working tree in large repositories.

You should try tig for a quick view of your repository's history. lazygit does a lot more.

You can and should sign your commits with ssh (unless you prefer PGP).

[core]
	autocrlf = false
	whitespace = blank-at-eol,blank-at-eof
	pager = delta
[gc]
	auto = 0
[user]
	signingKey = ~/.ssh/id_ed25519
[fetch]
	prune = true
[push]
	default = current
[rerere]
	enabled = true
	autoUpdate = true
[color]
	ui = true
[branch]
	autosetuprebase = always
[log]
	date = iso
[rebase]
	autosquash = true
	autostash = true
[alias]
	cm = commit -v
	ss = status -sbuno
	sss = status -sb
[tag]
	sort = version:refname
[tig]
	show-changes = true
	commit-order = topo
	line-graphics = utf-8
	mouse = true
	blame-options = -C -C -C
[difftool]
	prompt = false
[mergetool]
	prompt = false
[commit]
	gpgsign = true
[pull]
	rebase = true
[init]
	defaultBranch = main
[help]
	format = web
[gpg]
	format = ssh
[submodule]
	recurse = true
[interactive]
	diffFilter = delta --color-only
[delta]
	navigate = true
	side-by-side = true
[merge]
	conflictstyle = diff3
[diff]
	colorMoved = default

NetEscape: challenging web agents

My employer, Twin Labs, builds ML-powered web automation.

We shipped my side project, NetEscape, an obstacle course for web agents.

Largely designed around our technology's current limitations, it proves a challenge for the agents we've put our hands on.

It is, however, easy for humans. Feel free to try it! Should you complete it, we look forward to your submission…

A little meta

This blog is powered by a static site generator and live previewer, 11ty.

direnv automates the installation of mise, which automates the installation of node and pnpm.

A blog command automates the installation of further dependencies and the invokation of package.json scripts.

It is deployed to xmit, my very own hosting platform, from a public GitHub repository.

GitHub Actions are available on the deploy branch, largely unused. Usually much faster to deploy locally.

Articles are written in Markdown, images are authored in high-res AVIF and made available in AVIF and JPEG in a variety of sizes.

An index lists all posts, its JSON Feed provides the last 10 posts to feed readers.

Update (2024-09-18): There is also a newspaper view for that old-school feel now.

Scavengers Reign (2023)

Scavengers Reign poster

Sci-fi animation inappropriate for children. Nothing short of my favourite piece of media for adults.

A visual masterpiece backing a captivating story, it will take your breath away.

I strongly recommend going in blind, then watching the Scavengers short included below.
That said, teaser & trailer follow in case you need convincing.

Scavengers (a 2016 short)

Teaser

Trailer

Hono Coffee House

Hono coffee shop front

Hono Coffee House is my favourite coffee shop in Grenoble, France.

Carrying their own roast and that of nearby Chulo, offering a variety of brewing methods and alternative drinks, they're a must-taste for any coffee lover visiting the city.

They also offer a great selection of vegan food, some gluten-free.

I visit almost daily, most often enjoy an oat milk flat white. I'm also partial to their dirty chaï, and would suggest espresso tonics if you're feeling adventurous.

Cup of dirty chaï

Neuf Lamen

My bowl at Neuf Lamen on Thursday night

Felt compelled to share that Neuf Lamen is a brilliant eatery in Grenoble, France.

I eat there often and always leave happy. The staff is super friendly and welcoming.

Their braised beef lamen is worth singling out for me, though I've never been disappointed.

Fediverse identity ownership falls short

I enjoy using my own domains — though I rent a few too many! One of them, rrier.fr was originally purchased solely so I could use pc@rrier.fr as my E-mail address.

Naturally, I wanted to also be known as @pc@rrier.fr on the Fediverse, as part of owning my online identity. Unfortunately, this turned out more challenging that I expected. Here are a few approaches I tried and what I learned along the way.

Forwarding WebFinger

My first approach, documented during my migration to xmit.co, was to set up a WebFinger redirect. https://rrier.fr/.well-known/webfinger redirected to https://mastodon.social/.well-known/webfinger?resource=acct%3Apcarrier%40mastodon.social, the WebFinger URL for @pcarrier@mastodon.social.

This let people search for @pc@rrier.fr and find an account. Unfortunately, that indirection would be resolved right there and then: they would then see and follow the mastodon.social account. I couldn't move providers smoothly, as the process to relocate an account disappears all previous content.

I wanted more control over where my content is hosted and stored authoritatively. Onto what seemed like the natural solution.

Running Mastodon

In my opinion, for a single customer, a server requires too much setup and maintenance work, and too many resources. I gave up a few steps into an installation when I realized the amount of memory my VPS would probably need, so I can't say much more.

I looked around, and found what I think is a better solution for my needs:

Running GoToSocial

Setup was a breeze. Everything is lightweight and fast. I have minor complaints, notably lack of edit capability (already on the roadmap), but it's a fantastic piece of software.

It does, however, suffer from what appears to be limitations inherent to the design of the Fediverse:

I'd love to learn that those issues can be addressed without protocol changes, or that such protocol changes are underway. In the meantime, I've learnt to live with those grievances. Edit: Not a great UX, but everything seems workable in the end.

Desk setup

Here's my desk, where I spend way too much time. Please pardon the total lack of cable management.

My desk, overview

Probably the most obvious characteristic is the big display.

At 8K and 65 inches, the Samsung Neo QLED 8K QN900D takes most of the space on my 200⨉50cm desk. While far from perfect, with a surface equivalent to 4⨉4K or 16⨉1080p, it's fantastic for interacting with and keeping an eye on tons of windows at once.

The sound system is a pair of Focal Alpha 80 Evo studio monitors I adore, connected to a Mackie Mix5 mixing table which has caused me a lot of troubles but does the job of mixing the audio from 2 computers at once.

Computers at my desk

There are, in fact, 3 computers in total.

Inputs on my desk

To control them, I wouldn't deviate from the HHKB line of products; lately a Happy Hacking Keyboard Hybrid Type-S Snow. I resisted Type-S for far too long, I love its feel. For the pointer, I alternate between a Logitech MX Master 3S and a Logitech MX Ergo.

Though my desk can be raised and lowered electrically, I rarely stand in front. My Steelcase Gesture chair is quite comfortable.

Also pictured are:

Espresso on the go

Mobile espresso gear, packed, with a banana for scale

Here's my mobile espresso setup, that I use when I'm out and about.

It has nothing on my main setup but size.

Add roasted beans, a scale & a kettle. Compact yet capable.

Mobile espresso gear, unpacked, with a banana for scale

A few tunes

Early study. It ain't good, but it's mine.

Played with (roughly) the constraints of a Game Boy first.

Dropped the constraints, kept a video game feel.

I'd like to find the time and motivation to make more.

Main espresso gear

I love lighter-roast espresso. Here's my main setup, that I use regularly at home.

Overview of my main espresso gear

From left to right then back to front:

Coming soon:

Dump off landing

My landing page had a “dump” section. Bringing back this blog is the perfect opportunity to move its content to a post.

Old stuff

Future stuff?

Should either become more concrete, it'll move to my creations.

Videos

What a time sink video can be.

Random shader I made

The puzzle of motivation — Dan Pink

Growing a Language — Guy L. Steele Jr.

Transcript.

Programming Obesity: A Code Health Epidemic — Aaron W Hsu

Chromebook for devs

This article was migrated from Medium.

Those notes assume the reader is very familiar with Unix environments. Get out whilst you can.

Put your Chromebook in developer mode. Read carefully about the procedure and its implications. Be ready to wipe your Chromebook again if things go South.

Use Crosh Window so keyboard shortcuts won’t get swallowed.

Install Ubuntu

Install Crouton, get a chroot up and running:

crosh> shell
chronos@localhost ~ $ sudo sh -e ~/Downloads/crouton -r trusty -t xiwi -e

Convenience launchers

/usr/local/bin/s

Useful to quickly open a shell or run a command in the chroot.

crosh> shell
chronos@localhost ~ $ sudo tee /usr/local/bin/s <<EOF
#!/bin/sh
exec sudo enter-chroot -l "\\$@"
EOF
chronos@localhost ~ $ sudo chmod a+x /usr/local/bin/s

/usr/local/bin/x

Starts your X environment.

crosh> shell
chronos@localhost ~ $ sudo tee /usr/local/bin/x <<EOF
#!/bin/sh
exec sudo enter-chroot xinit
EOF
chronos@localhost ~ $ sudo chmod a+x /usr/local/bin/x

Configure apt

Make those changes before installing anything.

/etc/apt/apt.conf.d/90noextras

Not much room on your average Chromebook, so let’s minimize disk utilization.

APT::Install-Recommends “false”;
APT::AutoRemove::RecommendsImportant “false”;
APT::AutoRemove::SuggestsImportant “false”;
Acquire::Languages “none”;

/etc/apt/preferences.d/backports

Backports are a no-brainer for zsh users, as our favourite shell won’t have manpages otherwise. We enable them for all packages here.

Package: *
Pin: release a=trusty-backports
Pin-Priority: 500

/etc/apt/sources.list

Pick and choose, I doubt you want them all…

deb http://us.archive.ubuntu.com/ubuntu/ trusty main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu trusty-security main restricted universe multiverse
deb http://extras.ubuntu.com/ubuntu trusty main
deb http://archive.canonical.com/ubuntu/ trusty partner
deb http://repos.azulsystems.com/ubuntu stable main
deb http://dl.google.com/linux/chrome/deb/ stable main
deb http://dl.google.com/linux/chrome-remote-desktop/deb/ stable main
deb http://linux.dropbox.com/ubuntu trusty main
deb http://downloads.hipchat.com/linux/apt stable main
deb http://repository.spotify.com stable non-free
deb http://archive.getdeb.net/ubuntu trusty-getdeb apps games
deb https://get.docker.io/ubuntu docker main
deb http://debian.sur5r.net/i3/ trusty universe
deb http://winswitch.org/ trusty main
deb http://debrepos.franzoni.eu/atom squeeze main
deb http://ppa.launchpad.net/webupd8team/sublime-text-3/ubuntu trusty main
deb http://ppa.launchpad.net/git-core/ppa/ubuntu trusty main
deb http://ppa.launchpad.net/nowrep/qupzilla/ubuntu trusty main
deb http://ppa.launchpad.net/noobslab/indicators/ubuntu trusty main
deb http://ppa.launchpad.net/mc3man/trusty-media/ubuntu trusty main
deb http://ppa.launchpad.net/hugegreenbug/cmt2/ubuntu trusty main
deb http://ppa.launchpad.net/modriscoll/nzbget/ubuntu trusty main

First apt-get update

apt-get update will complain about missing keys. To import them, use something like:

% sudo apt-key adv --keyserver pgp.mit.edu --recv
1234567890ABCDEF FEDCBA0987654321

You should be verifying those PGP keys. [insert thought-through security blah blah everybody will ignore]

Configure the X session

As i3 maps quite a lot under its modifier, I use Mod4 (presented by i3 as “win” during the configuration assistant) but make it Right Alt instead of the Search key to avoid any conflicts. Sorry to users of non-US keyboards.

~/.xinitrc

#!/bin/sh -e
xrdb -merge ~/.Xresources
xmodmap ~/.Xmodmap
exec zsh -lc 'exec i3'

~/.Xmodmap

remove mod1 = Alt_R
add mod4 = Alt_R

~/.Xresources

Really a matter of taste…

URxvt*foreground: white
URxvt*background: black
URxvt*cursorColor: red

Running VPNs

Make sure the resolvconf package isn’t installed so /etc/hosts will be correctly written, both in the crouton chroot and on the host (as crouton ties them together).

TUN devices get automatically destroyed by the network manager, shill, which will break OpenConnect, vpnc and OpenVPN. To disable this behaviour until the next boot:

crosh> shell
chronos@localhost / $ sudo initctl stop shill && sudo shill --device-black-list=tun0,tun1

What’s next?

I kept most of my personal configuration out of this document, but I’d be happy to explore more in future articles. Let me know what you’d like to see covered on Twitter!

Page Cache My Assets

Many services rely on a dataset stored on disk.

If accesses are frequent and non-linear, performance remains reasonable as long as they are cached in memory. Then suddenly, some background job is triggered, a backup for example, and the data gets evicted from the page cache. Performance drops.

In many cases this is acceptable. The service throughput drops. In a request-reply model, requests get queued. But if latency is not critical, remains below the client timeout, and if the machine is dimensioned properly, data will be cached again, the service will catch up. The temporary slowdown was acceptable.

In other cases, this is catastrophic. Think high-frequency trading.

Here comes pcmad, the “Page Cache My Assets” daemon. It simply locks and unlocks files in memory as requested. When a file is locked, it won’t be evicted, whatever happens on the server. If the system runs out of memory, the oom-killer would be likely to kill this daemon first, so the upstart job and systemd unit indicate that killing pcmad should be avoided at all costs.

A simple and documented protocol, based on ØMQ and MessagePack, makes pcma easy to integrate with your existing services. For scripts, we also ship a client.

The project reached 0.2.0. It isn’t stabilized yet, so the protocol might not remain backward-compatible. However the code is simple and passed reviews, so feel free to give it a go!

Ubuntu Precise MOTD

--- /etc/pam.d/login.before
+++ /etc/pam.d/login
@@ -85 +85 @@
-session optional pam_motd.so
+# session optional pam_motd.so

A similar change is required for all PAM services showing the MOTD, often including sshd.

--- /etc/pam.d/login.before
+++ /etc/pam.d/login
@@ -85 +85 @@
-session optional pam_motd.so
+session optional pam_motd.so noupdate

Again, the same change is required in all services using pam_motd.so. You also need to disable the execution on boot with this change:

--- /etc/init/mounted-run.conf.before
+++ /etc/init/mounted-run.conf
@@ -22 +22 @@
- [ -d "/etc/update-motd.d" ] && run-parts --lsbsysinit /etc/update-motd.d > /run/motd &
+ # [ -d "/etc/update-motd.d" ] && run-parts --lsbsysinit /etc/update-motd.d > /run/motd &

Finding the Fedora 15 installer

On fedoraproject.org, the new prominent installation media with Fedora 15 is the live desktop, eg. Fedora-15-x86_64-Live-Desktop.iso.

Download it, boot it in VirtualBox. Gnome 3 will use the fallback mode. How do you start the installer? Well, turns out it is normally made prominent by a Gnome Shell extension (~/.local/share/gnome-shell/extensions/Installer@shell-extensions.fedoraproject.org/).

Did I mention that in fallback mode, which you can enjoy with most virtualization technologies, Gnome Shell is not running? Instead the installer ends up in the menu. Somehow it took me over 15 minutes to find it. Most people would be ashamed, I blog about it.

In case you wonder how to start the Fedora 15 installer in your virtual machine (SEO)… You can find it in Applications → System Tools → Install to Hard Drive. Alternatively, Alt+F2, liveinst. My bad for not partaking in the testing effort…

It makes me feel old and nerdy, but I love console-based installation processes.

7clock

I wanted a minimal, fullscreen clock I could run without X. In the longer term, I am thinking about a locking console “screensaver”; (more about that later). I ended up writing a small library (240 lines and counting) to render a 7-segment display in monospaced text at any “resolution”.

The end result adapts to the console size, instantaneously if resized. It lacks any options, if I'm bored again I might come back to it. It should be quite efficient, though more trivial optimizations are possible.

Older screenshots from various prototypes (the test program is available alongside the clock; as usual, I recommend sticking to the instructions in INSTALL at the root of the repo):

errnos

As a Technical Support Engineer at Red Hat, I got to read a lot of logs, error messages and code. One of my pain points was errnos.

They rely on magic numbers, which is perfectly understandable given their use cases (eg return values for system calls). But obviously, we're not going to be using magic numbers everywhere, hence they are defined as constants for the C preprocessor.

Numbers are not very user-friendly, so why not display them in a human-readable format when a human might want to read it? strerror comes to the rescue! Unfortunately, not every piece of code presenting errors to the user or administrator uses it. There are various reasons for that:

strerror strings are very readable; for example, it will turn ENOMEM into Cannot allocate memory under OSX. I will not lose too much of your time on the annoyances caused by weird usages of errnos, though I encountered quite a few already: they usually do not delay troubleshooting too much if you're not too trusting. For example ENOTDIR, represented by glibc's strerror as Not a directory, indicates when returned by keyctl_search(3) that one of the keyrings is a valid key that isn't a keyring.

The tricky part now? From a number or an strerror description in logs or an output, there is no trivial way to establish which constant to look for. What's more, C preprocessor constants are not available at runtime, you'd need the headers at hand, cpp, and your own list to go through as there isn't a standard one! For example, if you see 44, 0x2c or Channel number out of range, what should you git grep for in the affected software, libc and/or kernel? ECHRNG, of course!

I'd love to give you a simple table listing each errno constant, its representation in decimal and hexadecimal and its strerror description, but there are a few reasons why I can't:

However, this led to the creation of a simple command-line utility, errnos. Build and run it on the system you investigate, or a similar one (same operating system, same libc, same CPU architecture), and you will get something you can store and grep at will. It could also make an ironic wallpaper for your child's room, but don't blame me if they have nightmares of production systems going down.

For once, I used glib as I needed a hashtable of lists and couldn't be bothered implementing those for the millionth time in history (comp. sci. students who have to do so tonight, I share your frustration). There's a limited amount of magic involved in the build process, so please just clone the repository and stick to the build instructions unless you have time to lose.

The first column gives the number in its decimal representation, the second in hexadecimal. The third is either its strerror representation between double quotes or a preprocessor constant.

To close this article, here is the end of its output on my Mac:

$ errnos | tail
Stopped looking at 1128
99    0x63    "Not a STREAM"
99    0x63    ENOSTR
100   0x64    "Protocol error"
100   0x64    EPROTO
101   0x65    "STREAM ioctl timeout"
101   0x65    ETIME
102   0x66    "Operation not supported on socket"
102   0x66    EOPNOTSUPP
103   0x67    "Policy not found"
103   0x67    ENOPOLICY

nato, superglob

When you end up having to dictate Unix commands over the phone, you quickly learn from your colleagues that optimism doesn’t compensate your French accent. Turns out cancelling your lovefilm subscription triggers a similar problem.

The most common answer is to involve the NATO phonetic alphabet. Looking up a table pinned to your desk is tedious, getting fluent takes time. That’s where nato kicks in.

Not much to say, really:

$ nato 'lspci|grep VGA'
lima, sierra, papa, charlie, india, pipe, golf, romeo, echo, papa, space, uppercase victor, uppercase golf, uppercase alpha,
$

After this very useful piece of software (at least to some), let’s have a look at something stupid and useless (I won’t even bother trying to explain the silly reason I needed it). If you ever have a good, real-life reason to run superglob, please E-mail me right away, I’ll owe you the drink of your choice. The idea is to build a glob matching all the arguments provided, but as little more as possible (and we’re far from being clever here).

$ superglob Hello World
[HW][eo][lr]l[do]
$ superglob Foo 'Bar Mitzvah'
[BF][ao][or]*
$ superglob /lib64/libpamc.so.0 \
  /lib64/libpamc.so.0.81.0 /lib64/libpam_misc.so.0 \
  /lib64/libpam_misc.so.0.81.2 /lib64/libpam.so.0 \
  /lib64/libpam.so.0.81.5
/lib64/libpam[._c][.ms][ios][.os][.0c]*

A good example of a really silly behaviour (here, *ahello would likely be the best choice):

$ ~/usr/bin/superglob ahello bahello cbahello
[abc][abh][aeh][ehl][el][lo]*

mkpasswd

You want passwords that are identical with AZERTY, QWERTY and QWERTZ keyboards? And easier to type on a mobile phone (no uppercase)? Alternatively, with the characters you list and just those?

You don’t want to choose a number of characters, how many digits and special characters should appear (or any nonsensical policy when you know what you are doing), but rather would rely solely on the number of bits of entropy you’ll get?

Generated from /dev/random, as it’s a good source of entropy (under a recent Linux kernel at least).

Check out mkpasswd.