Skip to content

Added tmux and multi-wide compatibility#112

Open
aditya-kapadia wants to merge 18 commits into
brockgr:masterfrom
aditya-kapadia:master
Open

Added tmux and multi-wide compatibility#112
aditya-kapadia wants to merge 18 commits into
brockgr:masterfrom
aditya-kapadia:master

Conversation

@aditya-kapadia

Copy link
Copy Markdown

No description provided.

Virat Gohil and others added 18 commits September 25, 2018 11:21
fixing macos mojave issues
fixing macos mojave issues
A  Formula/csshx.rb
D  Formula/csshx.rb
Fix compatibility with macOS Big Sur
…kends

Stdlib-only Python 3 cluster-SSH tool under csshx-latest/. Replaces
the original csshX TIOCSTI keystroke-injection hack with real PTYs
and a pluggable Launcher protocol.

Backends shipped: WaveTerm, tmux, iTerm2, Terminal.app, Kitty, WezTerm,
plus a Manual fallback that prints attach commands for any terminal.
Master process owns every PTY and bridges them through per-slave UNIX
sockets gated by 32-byte AUTH tokens. Suite of 33 pytest cases.

The original Perl csshX, README.txt, and surrounding files are left
exactly as-is. A new top-level README.md points users at both.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
slave.py: add a per-slave scrollback buffer (capped at 64 KiB) that
captures every byte the PTY emits before any terminal block has
connected, then replays it to each new client right after AUTH. The
bridge previously dropped any output that arrived between fork-exec of
ssh and the launcher spawning the visible block — which on WaveTerm is
long enough to lose the banner, MOTD, and login prompt, leaving the
block blank. A small state_lock makes the "extend scrollback / snapshot
writers" and "replay scrollback / register writer" paths atomic so no
chunk is duplicated or lost across the race.

waveterm.py: flip _run's default to capture=True so the legacy wsh
probes in tile() (setlayout, layout, tile) plus deleteblock and
settitle no longer spit error text into the user's terminal on modern
wsh builds where those subcommands have been renamed or removed.

Adds tests/test_slave_bridge.py covering: late-client scrollback
replay, scrollback cap, and that a wrong AUTH token never receives any
buffered output. Skips cleanly on hosts without Unix-domain sockets.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When the master rejects an AUTH attempt it closes the socket without
sending any data. The fallback attach client used to read 0 bytes,
fall through to ``return 0``, and exit silently — the spawned terminal
block flashed and disappeared with no explanation. Track whether any
bytes have been received; on EOF with received_any=False, print a
specific diagnostic to stderr (token mismatch is the realistic cause)
and exit 1.

Adds tests/test_attach.py covering:
  - AUTH rejection (server closes immediately) → rc=1 with stderr
  - Normal EOF after data → rc=0, no rejection message
  - Bad argv → rc=2
  - Connect to missing socket → rc=1

Skips on Windows since attach.py is a Unix-only client.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two issues bit only on macOS, both via tests that exercised AF_UNIX
sockets and a Slave shutdown path:

* macOS limits ``sockaddr_un.sun_path`` to 104 bytes (Linux is 108).
  pytest's ``tmp_path`` lives at
  ``/private/var/folders/.../pytest-of-USER/pytest-N/test_name0/``
  which routinely blew past the limit and aborted ``bind()``. Replace
  ``tmp_path`` with a new ``short_socket_dir`` fixture that uses
  ``tempfile.mkdtemp(prefix="csshx-")`` for a path with plenty of
  headroom under the cap.

* ``shutdown_slave`` calls ``os.kill(slave.pid, SIGTERM)``. POSIX
  treats ``os.kill(0, ...)`` as "signal every process in my process
  group" — i.e. pytest itself. Tests that built a Slave with
  ``pid=0`` were one accidental cleanup-call away from the test runner
  killing itself. Add a ``harmless_pid`` fixture that spawns a
  short-lived ``time.sleep`` subprocess and yields its PID; reap it on
  teardown. ``test_broadcaster.py`` still passes ``pid=0`` because
  that suite never reaches ``shutdown_slave``, only the broadcaster
  write path.

Both fixtures live in ``tests/conftest.py`` so they're available to
any future test that touches the bridge or shutdown path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
attach.py calls sys.stdin.fileno() and sys.stdout.fileno() to drive its
select() loop. pytest's default capsys swaps both with StringIO mocks
that have no real fd, so attach.main() raises io.UnsupportedOperation
before it can ever observe the AUTH reject.

Add a stdio_devnull fixture in tests/conftest.py that opens
os.devnull (rb/wb), monkeypatches sys.stdin/sys.stdout to point at
those file objects, and closes them on teardown. Wire it into the two
attach tests that actually call attach.main() with a connecting socket
(test_auth_rejection_returns_1_with_clear_stderr and
test_clean_eof_after_data_returns_0). sys.stderr is deliberately left
alone so capsys.readouterr().err keeps capturing the error message
we assert on — no need to switch to capfd.

The other two attach tests (bad argv, missing socket) return before
ever touching stdin/stdout fds, so they don't need the fixture.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add csshx-latest: Python rewrite of csshX with pluggable terminal bac…
CRITICAL fixes:
- Bounded reap with SIGKILL fallback (no more hang-on-shutdown)
- StrictHostKeyChecking=accept-new injected when user did not set it
- --max-hosts cap (default 16) to prevent fork-bomb typos
- Broadcaster logs per-slave write failures (no more silent drops)
- WaveTerm bash export parser uses shlex.split (handles all quote forms)

MUST HAVE features:
- Per-slave focus toggle: Ctrl-T <digit> for 1-9, Ctrl-T i for 10+
- iTerm2 and Apple Terminal close_block actually closes the pane now
- Launcher.start(total) lifecycle hook (drops CSSHX_HOST_COUNT env smuggle)
- ~/.config/csshx-latest/config.toml or ~/.csshrc cluster aliases
- TCP-22 preflight, --strict / --no-preflight flags
- Per-block SIGWINCH via dedicated control socket (WINSZ commands)
- Real-PTY round-trip integration test
- --reconnect with exponential backoff on slave death
- Tile after every spawn so panes stay balanced

Other:
- Alpha brace expansion: host-{a..c}
- Always use the stdlib attach client (control socket needs dual sockets)
- 150 tests passing (was 111)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants