Fix Fenrir Unix socket ownership reporting

This commit is contained in:
Storm Dragon
2026-05-07 23:43:11 -04:00
parent 6d4f55ffe5
commit 37e281a1f7
3 changed files with 142 additions and 6 deletions

128
AGENTS.md Normal file
View File

@@ -0,0 +1,128 @@
## Development Philosophy
**Clean code over backward compatibility.** Breaking changes are acceptable in major versions.
- PEP8 compliance (snake_case for all variables/functions/settings)
- Remove deprecated code completely - no compatibility hacks
- Trust users to update configs when upgrading
**Exception**: Never break core accessibility (speech output, basic navigation).
## Core Architecture
### Drivers
- **Screen**: `vcsaDriver` (TTY), `ptyDriver` (terminal emulation)
- **Input**: `evdevDriver` (evdev), `x11Driver` (X11 terminal mode)
- **Speech**: `speechdDriver` (speech-dispatcher), `genericDriver` (subprocess)
- **Sound**: `gstreamerDriver` (GStreamer), `genericDriver` (Sox subprocess)
- **Remote**: `unixDriver` (Unix sockets), `tcpDriver`
### Command System
Commands in trigger folders execute automatically:
- `onKeyInput/`, `onCursorChange/`, `onScreenUpdate/`, `onScreenChanged/`, `onHeartBeat/`
- Numeric prefixes control priority (lower = higher priority): `15000-char_echo.py`
- Manual commands in `commands/commands/`
### Core Managers (in `src/fenrirscreenreader/core/`)
`fenrirManager.py`, `commandManager.py`, `eventManager.py`, `screenManager.py`, `inputManager.py`, `outputManager.py`
### Configuration
- Main: `config/settings/settings.conf`
- Keyboards: `config/keyboard/` (desktop.conf, laptop.conf)
- Sounds: `config/sound/`
- Punctuation: `config/punctuation/`
## 🚨 CRITICAL: Files to NEVER Modify
**These are timing-critical - only fix critical bugs, never refactor:**
- `evdevDriver.py` - Input event processing
- `vcsaDriver.py` - Screen monitoring
Symptoms of breakage: echo changes, input lag, missing screen updates, sync issues.
## Development Commands
```bash
# Run from source (requires root)
cd src/ && sudo ./fenrir -f -d # foreground with debug
# Validation before commit
python3 tools/validate_syntax.py --fix
python3 tools/validate_release.py --quick
# Tests
pytest tests/
pytest tests/ --cov=src/fenrirscreenreader --cov-report=html
```
**Note**: Standard TTY Fenrir blocks - only one instance at a time. `fenrir -x`
can run multiple foreground X terminal instances. Ask user to run tests that
need real Fenrir instances or root access.
## Creating Commands
Use `commands/command_template.py` as base. Required methods:
- `initialize(self, environment)`, `shutdown()`, `run()`, `get_description()`
### Import Pattern (Required)
Fenrir's command loader doesn't support relative imports:
```python
import os, importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'base_file.py')
_spec = importlib.util.spec_from_file_location("base_module", _base_path)
_module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module)
BaseClass = _module.BaseClass
```
### Consolidated Base Classes
- **Bookmarks**: `bookmark_base.py` - `BookmarkCommand(id, 'read'|'set'|'clear')`
- **Adjustments**: `adjustment_base.py` - `AdjustmentCommand('speech'|'sound', 'rate'|'pitch'|'volume', 'inc'|'dec')`
- **VMenu Search**: `vmenu_search_base.py` - `VMenuSearchCommand('a'-'z')`
## VMenu System
Application-specific menus in `vmenu-profiles/KEY/{app}/`:
- Directories = submenus, `.py` files = actions
- Activate: `Fenrir+F10`, navigate with arrows, Enter to execute
## Remote Control
Unix socket: `/tmp/fenrirscreenreader-deamon.sock`
TCP: localhost:22447
```bash
echo "command say Hello" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "setting set speech#rate=0.8" | nc localhost 22447
```
In `fenrir -x`, each instance has a private socket:
`/tmp/fenrirscreenreader-<pid>.sock`. One instance may also own the standard
socket. Use `ls`/`list` on the standard socket to discover registered instances
and their socket paths. Untargeted remote commands use a short cross-process
claim lock so only one instance handles the same broadcast command; direct
commands to a private instance socket still run on that instance.
Disable in untrusted environments: `[remote] enable=False`
## Key Implementation Details
- Commands via `command_mod.command()` instantiation
- Bookmark structure: `env['commandBuffer']['bookMarks'][ID][app]['1'/'2']`
- VMenu search: `env['runtime']['vmenuManager'].searchEntry(char)`
## Recent Fixes (Reference)
- Enhanced application detection for screen/tmux sessions
- Table navigation consistency (sound feedback)
- Blank line detection in 22 command files
- Character/space review during navigation
## Safe vs Risky Changes
**Safe**: Commands, VMenu profiles, config handling, sound/speech drivers, docs
**Risky (extra testing)**: Core managers, event processing
**Avoid**: evdevDriver, vcsaDriver, timing-critical code

View File

@@ -5,4 +5,4 @@
# By Chrys, Storm Dragon, and contributors.
version = "2026.05.07"
code_name = "testing"
code_name = "master"

View File

@@ -115,14 +115,22 @@ class driver(remoteDriver):
def _socket_file_matches_socket(self, fenrir_sock, socket_file):
try:
socket_stat = os.stat(socket_file)
if os.stat(socket_file).st_uid != os.getuid():
return False
fd_stat = os.fstat(fenrir_sock.fileno())
socket_inode = str(fd_stat.st_ino)
with open("/proc/net/unix", "r", encoding="utf-8") as proc_file:
for line in proc_file:
line_parts = line.split()
if (
len(line_parts) >= 8
and line_parts[6] == socket_inode
and line_parts[7] == socket_file
):
return True
except OSError:
return False
return (
socket_stat.st_dev == fd_stat.st_dev
and socket_stat.st_ino == fd_stat.st_ino
)
return False
def _cleanup(self):
for fenrir_sock in self.fenrirSocks: