Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# AGENTS.md

Mixmaster 3.0 — vintage Type II anonymous remailer (C). Two binaries share a
`Mix/` spool: `mixmaster` (client + legacy remailer) and `mixremailer` (server).
See `README.md`, `MODERNIZATION.md`, and `Src/remailer/ARCHITECTURE.md` for design.

## Cursor Cloud specific instructions

The cloud VM is **Linux (Ubuntu)**, but the repo's documented build path
(`scripts/build-macos.sh`, `make build`, CI) targets **macOS/Homebrew**. Use the
Linux path instead:

- **Build:** `./scripts/build-linux.sh` (added for Linux; mirrors the macOS
script). Outputs `bin/mixmaster` and `bin/mixremailer`. `./scripts/build-linux.sh clean` cleans.
- **System libs** (installed by the startup update script): `libssl-dev`,
`libpcre3-dev` (PCRE **1** — the vintage code uses the old `pcre.h` API, not
pcre2), `libncurses-dev`, `zlib1g-dev`.
- **`-fcommon` is mandatory.** Legacy globals are declared (not just `extern`)
in a shared header; modern GCC/Clang default to `-fno-common` and would fail
linking with "multiple definition" errors. `build-linux.sh` adds `-fcommon`.
- **bison is NOT needed:** `Src/parsedate.tab.c` is committed for bison-free builds.

### Run / test (from repo root, after build)

Always export the spool path first: `export MIXPATH="$PWD/Mix"`.

- **Spool setup:** `./scripts/setup-mixdir.sh` seeds `Mix/` from `conf/`
(config, keyrings, lists). Re-seed config with `SETUP_FORCE_CFG=1`.
- **Client:** `./bin/mixmaster` (no args) opens the ncurses menu; needs a TTY.
CLI flags skip the menu (`--version`, `--help`, `-T` list remailers,
`-l <chain> -t <addr>` encrypt, `-S` flush pool, `-G` generate keys).
- **Server smoke test (matches CI):** `MIXPATH="$PWD/Mix" ./bin/mixremailer -M`.
The first `-M`/`-G` auto-generates the remailer's RSA key (OpenSSL 3 path).
- **Unit test:** `cc -DHAVE_SETENV -include string.h -o /tmp/t Src/tests/test-parse_yearmonthday.c && /tmp/t`
(the `-include string.h` works around a missing include the source omits; do
not edit the source). The same function is asserted at every `mixmaster` startup.

### Non-obvious runtime gotchas

- **No MTA on the VM.** `mix.cfg` defaults `SENDMAIL` to `/usr/lib/sendmail -t`,
which does not exist here. For local delivery tests, point `SENDMAIL` at a
capture script in `Mix/mix.cfg` (env `SENDMAIL` does **not** override the
config value). Outbound mail is then written to a file instead of sent.
- **Pool batching holds single messages.** With default `POOLSIZE`/`RATE`, one
pooled message is held for anonymity and won't flush. Force it for testing by
setting `POOLSIZE 0` / `RATE 100` in `mix.cfg` (or per the `mixmaster(1)`
`--POOLSIZE=0 --RATE=100` overrides).
- **Self-addressed messages loop back:** sending to the remailer's own
`REMAILERADDR` stores the packet in the pool (prefix `i*`) for local
processing rather than mailing it; feed it to `./bin/mixremailer -R < <file>`
to decrypt the next hop.
- **Bundled sample keys (2007) are expired** — the `Key ... has expired` and
`Statistics are older than one day` warnings are benign. For a working hop,
publish the locally generated key: `cat Mix/key.txt >> Mix/pubring.mix`.
- `Mix/`, `bin/`, `Src/Makefile`, secrets/keyrings are gitignored runtime
artifacts — safe to delete and regenerate.
78 changes: 78 additions & 0 deletions scripts/build-linux.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# Author: BrainX
# Date: 2026-06-17
# Description: Build Mixmaster 3.0 on Linux (Debian/Ubuntu) using system libraries.
# Usage:
# ./scripts/build-linux.sh
# ./scripts/build-linux.sh clean
#
# Notes:
# Requires dev packages: libssl-dev libpcre3-dev libncurses-dev zlib1g-dev
# (PCRE1 / libpcre3-dev is required — the vintage code uses the old pcre.h API.)
# bison is NOT needed: Src/parsedate.tab.c is tracked for bison-free builds.
# -fcommon is required: legacy code declares globals in a shared header, which
# modern GCC/Clang (-fno-common default) would otherwise reject at link time.

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SRC="${ROOT}/Src"
BIN="${ROOT}/bin"

cleanup() {
local code=$?
if [[ $code -ne 0 ]]; then
echo "build-linux.sh: interrupted or failed (exit $code)" >&2
fi
exit "$code"
}
trap cleanup INT TERM

check_headers() {
local missing=()
[[ -f /usr/include/openssl/ssl.h ]] || missing+=("libssl-dev")
[[ -f /usr/include/pcre.h ]] || missing+=("libpcre3-dev")
[[ -f /usr/include/ncurses.h || -f /usr/include/curses.h ]] || missing+=("libncurses-dev")
[[ -f /usr/include/zlib.h ]] || missing+=("zlib1g-dev")
if [[ ${#missing[@]} -gt 0 ]]; then
echo "Missing dev libraries. Install with:" >&2
echo " sudo apt-get install -y ${missing[*]}" >&2
exit 1
fi
}

if [[ "${1:-}" == "clean" ]]; then
make -C "$SRC" clean 2>/dev/null || true
rm -f "$SRC/Makefile" "$BIN/mixmaster" "$BIN/mixremailer"
echo "Clean complete."
exit 0
fi

check_headers

INC="-I/usr/include"
DEF="-DUSE_ZLIB -DUSE_PCRE -DUSE_NCURSES -DHAVE_NCURSES_H -DUSE_AES -DHAVE_SETENV -DSPOOL='\"${ROOT}\"' -fcommon"
LIBS=""
LDFLAGS="-lcrypto -lpcre -lncurses -lz"

mkdir -p "$BIN"
cd "$SRC"

HOST="$(hostname -s 2>/dev/null || echo linux)"
{
echo "# Makefile generated on ${HOST} $(date)"
sed -e "s#%MIXDIR##" \
-e "s#%LIBS#${LIBS}#" \
-e "s#%LDFLAGS#${LDFLAGS}#" \
-e "s#%INC#${INC}#" \
-e "s#%DEF#${DEF}#" < Makefile.in
echo "CC = cc"
} > Makefile

echo "Building mixmaster + mixremailer in ${SRC}..."
make mixmaster mixremailer

install -m 755 mixmaster "${BIN}/mixmaster"
install -m 755 mixremailer "${BIN}/mixremailer"
echo "Success: ${BIN}/mixmaster ($(file -b "${BIN}/mixmaster"))"
echo "Success: ${BIN}/mixremailer ($(file -b "${BIN}/mixremailer"))"
Loading