All checks were successful
Test / test (push) Successful in 6m2s
- Clarify that the sprite is the author's face on Nedry's body - Explicit Wayland (gtklock module) vs X11/macOS (PAM module) comparison table with an explanation of how each integration works - Accurate per-distro PAM paths (standard/Fedora multilib/Debian multiarch) - scripts/install-macos.sh: one-shot installer for macOS — checks Homebrew, installs brew deps, builds from source, copies binaries, and patches /etc/pam.d/screensaverui (or screensaver) after the last auth line Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
160 lines
4.6 KiB
Markdown
160 lines
4.6 KiB
Markdown
# Ah ah ah, you didn't say the magic word
|
|
|
|
On a failed lock-screen unlock attempt, this spawns a looping animation of **the author's face photoshopped onto Dennis Nedry's body** and plays the "ah ah ah, you didn't say the magic word" clip from Jurassic Park. Each wrong guess adds another sprite at a random screen position. Volume is forced to 100% on the first failure and restored when the screen unlocks.
|
|
|
|
## Platform support
|
|
|
|
The integration method differs by display server:
|
|
|
|
| Platform | Display server | Module loaded | How it works |
|
|
|---|---|---|---|
|
|
| Linux | **Wayland** | `ahfail-module.so` | Loaded directly by `gtklock` via its module API |
|
|
| Linux | **X11** | `libahfail_pam.so` + `ahfail-display` | PAM cleanup hook spawns the display binary after each failed auth |
|
|
| macOS | — | `libahfail_pam.so` + `ahfail-display` | Same PAM approach, hooks into the screensaver PAM stack |
|
|
|
|
The **gtklock module** is Wayland-only — it uses gtklock's internal window API to overlay sprites directly on the lock screen. The **PAM module** works on X11 and macOS by registering a cleanup callback that fires on each failed authentication attempt; it double-forks a standalone display binary (`ahfail-display`) that runs independently of the PAM stack.
|
|
|
|
---
|
|
|
|
## Linux — Wayland (gtklock)
|
|
|
|
### Install dependencies (Arch)
|
|
|
|
```bash
|
|
sudo pacman -S meson ninja rust gtk3 gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gtklock
|
|
```
|
|
|
|
### Build and install
|
|
|
|
```bash
|
|
meson setup builddir
|
|
meson compile -C builddir
|
|
sudo meson install -C builddir
|
|
```
|
|
|
|
Installs:
|
|
- `/usr/lib/gtklock/ahfail-module.so` — gtklock module
|
|
- `/usr/lib/ahfail/libahfail_pam.so` — PAM module (for X11)
|
|
- `/usr/lib/ahfail/ahfail-display` — standalone display binary
|
|
|
|
### Run
|
|
|
|
```bash
|
|
gtklock -m /usr/lib/gtklock/ahfail-module.so
|
|
```
|
|
|
|
### Arguments
|
|
|
|
Pass module arguments after `--`:
|
|
|
|
```bash
|
|
gtklock -m /usr/lib/gtklock/ahfail-module.so -- --deadzone=860,440,200,200
|
|
```
|
|
|
|
- `--deadzone=X,Y,W,H` — rectangle where sprites will not spawn (keep your password field clear)
|
|
- `--audio-uri=URI` — override the default audio clip, e.g. `file:///home/user/custom.mp3`
|
|
|
|
---
|
|
|
|
## Linux — X11 (i3lock, xscreensaver, etc.)
|
|
|
|
Add the PAM module to your screen locker's PAM service file. Use the full path — `$(libdir)/ahfail` is not in PAM's default search path.
|
|
|
|
**Arch / standard:**
|
|
```
|
|
auth optional /usr/lib/ahfail/libahfail_pam.so
|
|
```
|
|
|
|
**Fedora / RHEL (multilib):**
|
|
```
|
|
auth optional /usr/lib64/ahfail/libahfail_pam.so
|
|
```
|
|
|
|
**Debian / Ubuntu (multiarch):**
|
|
```
|
|
auth optional /usr/lib/x86_64-linux-gnu/ahfail/libahfail_pam.so
|
|
```
|
|
|
|
Common service files: `/etc/pam.d/i3lock`, `/etc/pam.d/xscreensaver`, `/etc/pam.d/lightdm`.
|
|
|
|
Optionally pass the display binary path as an argument if it is not at the default location:
|
|
|
|
```
|
|
auth optional /usr/lib/ahfail/libahfail_pam.so display_path=/usr/lib/ahfail/ahfail-display
|
|
```
|
|
|
|
---
|
|
|
|
## macOS
|
|
|
|
### Quick install (recommended)
|
|
|
|
```bash
|
|
git clone https://gitea.weircon.dk/agw/gtk-ahfail.git
|
|
cd gtk-ahfail
|
|
bash scripts/install-macos.sh
|
|
```
|
|
|
|
The script installs Homebrew dependencies, builds from source, copies binaries to `/usr/local/lib/ahfail/`, and patches the screensaver PAM configuration automatically.
|
|
|
|
### Manual install
|
|
|
|
#### Prerequisites
|
|
|
|
```bash
|
|
brew install gtk+3 gstreamer gst-plugins-base gst-plugins-good meson ninja
|
|
```
|
|
|
|
Rust: install via [rustup.rs](https://rustup.rs) if not already present.
|
|
|
|
#### Build
|
|
|
|
```bash
|
|
meson setup builddir
|
|
meson compile -C builddir
|
|
```
|
|
|
|
#### Install
|
|
|
|
```bash
|
|
sudo mkdir -p /usr/local/lib/ahfail
|
|
sudo cp builddir/libahfail_pam.so /usr/local/lib/ahfail/
|
|
sudo cp builddir/ahfail-display /usr/local/lib/ahfail/
|
|
```
|
|
|
|
#### Configure PAM
|
|
|
|
Find the screensaver PAM service file:
|
|
- macOS 13 (Ventura) and later: `/etc/pam.d/screensaverui`
|
|
- macOS 12 and earlier: `/etc/pam.d/screensaver`
|
|
|
|
Add this line after the existing `auth` entries (requires `sudo`):
|
|
|
|
```
|
|
auth optional /usr/local/lib/ahfail/libahfail_pam.so
|
|
```
|
|
|
|
---
|
|
|
|
## Customization
|
|
|
|
The sprite is the author's face on Nedry's body. To use your own:
|
|
|
|
1. Replace the sprite frames in `assets/sprites/` with your own PNG sequence.
|
|
2. Update `assets/ahfail.gresource.xml` if you add or remove files.
|
|
3. Rebuild with Meson.
|
|
|
|
To replace the audio clip, swap `assets/audio/magic-word.mp3` and rebuild.
|
|
|
|
---
|
|
|
|
## Development
|
|
|
|
```bash
|
|
cargo test # unit + integration tests (needs display)
|
|
cargo test --test benchmarks -- --nocapture # sprite placement benchmarks
|
|
cargo clippy # lint
|
|
meson setup builddir && meson compile -C builddir # full build including .so
|
|
xvfb-run meson test -C builddir --verbose # Meson tests headless
|
|
```
|