Complete the wireless network menu, which since its 2013 introduction
stopped just short of usefulness: it could scan the airwaves and list
networks configured in wpa_supplicant.conf(5), but selecting a scanned
network did nothing, the configuration editor displayed values it could
not change, and nothing was ever written back to disk. All three
XXXDT-unfinished paths are now implemented.
Selecting an unmarked ([ ]) entry joins that network. The security
type is derived from the wpa_cli(8) scan_results flags (PSK, SAE, EAP,
WEP, or open) and the user is prompted accordingly: passphrases and
keys through an obscured password box with validation (8-63 character
passphrase or 64-digit hex pre-shared key; 5/13 character ASCII or
10/26 digit hex WEP key), EAP through identity and password prompts.
The resulting network block is appended to wpa_supplicant.conf(5) with
priority=5 and wpa_supplicant(8) is reloaded via wpa_cli(8)
reconfigure, so the join both takes effect immediately and survives a
reboot. Manually Connect, which previously dead-ended in the editor
with no SSID, now prompts for an SSID and security type and joins with
scan_ssid=1 so cloaked or unlisted networks are probed.
Selecting a marked ([X]) entry edits that configuration for real.
Edits accumulate in a scratch struct so Cancel discards them; Save/Exit
splices the modified block back into wpa_supplicant.conf(5) and reloads
wpa_supplicant(8). New menu entries allow adding any WPA_NETWORK
property not currently set and forgetting the network entirely (with
confirmation). Secret properties are masked in the menu; the mask list
now also covers eappsk and private_key2_passwd, which the original
inline pattern missed.
Persistence is built on a new fork-minimal API in media/wlan.subr:
f_wpa_network_block() serializes a WPA_NETWORK struct into a
network={ ... } block (forkless), quoting per wpa_supplicant.conf(5)
semantics -- list and integer properties bare, wep_keyN verbatim since
quoting there distinguishes an ASCII key from a raw hex key, a psk of
exactly 64 hex digits bare to mean a raw pre-shared key, everything
else quoted. An ssid containing a backslash is written using the
P"..." syntax so the printf(3)-encoded text reported by wpa_cli(8)
scan_results is decoded back to the on-air byte sequence rather than
matched literally. f_wpa_supplicant_network_write() appends a block;
f_wpa_supplicant_network_replace() replaces or removes the n-th block
via a single awk(1) that numbers blocks exactly as
f_wpa_supplicant_parse() numbers structs (empty blocks uncounted), so
struct N always addresses file block N. The replacement text rides in
on ENVIRON[] because, unlike -v, it does not mangle backslash
sequences. Default overrides, blobs, custom definitions, and comments
in the file are preserved.
Displaying data gleaned from the airwaves invites a POLA violation: an
SSID is an arbitrary byte string, and while modern wpa_cli(8)
printf(3)-encodes scan results, values parsed from quoted
wpa_supplicant.conf(5) strings arrive as raw bytes -- so a hostile SSID
containing ANSI CSI sequences could repaint the TUI and forge what the
user believes they are selecting. A new forkless strings.subr routine,
f_str2printable(), converts control characters to `?' and every SSID,
BSSID, and description is scrubbed through it at render time (raw bytes
remain in the structs, since an SSID must match on-air); menu
selections are compared in printable form on both sides.