sshmd 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sshm/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """sshm — cross-platform SSH session manager with a background daemon."""
2
+
3
+ __version__ = "0.1.0"
sshm/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ """Allow running as python -m sshm."""
2
+ from .cli import main
3
+
4
+ main()
sshm/autostart.py ADDED
@@ -0,0 +1,163 @@
1
+ """Cross-platform autostart management for sshmd daemon."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ from .procutil import daemon_interpreter
11
+ from .state import log_file, port_file, resolve_port, write_port
12
+
13
+
14
+ def _find_sshmd() -> str:
15
+ sshmd = shutil.which("sshmd")
16
+ if sshmd:
17
+ return sshmd
18
+ return f"{sys.executable} -m sshm.daemon"
19
+
20
+
21
+ # --- Windows ---
22
+
23
+ def _win_daemon_cmd() -> str:
24
+ """Task command line: pythonw (no console window) from the current environment."""
25
+ return f'"{daemon_interpreter()}" -m sshm.daemon'
26
+
27
+
28
+ def _win_install() -> None:
29
+ cmd = [
30
+ "schtasks", "/create",
31
+ "/tn", "sshmd",
32
+ "/tr", _win_daemon_cmd(),
33
+ "/sc", "onlogon",
34
+ "/rl", "limited",
35
+ "/f", # force overwrite
36
+ ]
37
+ result = subprocess.run(cmd, capture_output=True, text=True)
38
+ if result.returncode != 0:
39
+ raise RuntimeError(f"Failed to create scheduled task: {result.stderr}")
40
+
41
+
42
+ def _win_uninstall() -> None:
43
+ cmd = ["schtasks", "/delete", "/tn", "sshmd", "/f"]
44
+ subprocess.run(cmd, capture_output=True, text=True)
45
+
46
+
47
+ # --- Linux (systemd) ---
48
+
49
+ _SYSTEMD_UNIT = """\
50
+ [Unit]
51
+ Description=SSH Session Manager Daemon
52
+ After=network.target
53
+
54
+ [Service]
55
+ Type=simple
56
+ ExecStart={cmd}
57
+ Restart=on-failure
58
+ RestartSec=5
59
+
60
+ [Install]
61
+ WantedBy=default.target
62
+ """
63
+
64
+
65
+ def _linux_install() -> None:
66
+ sshmd = _find_sshmd()
67
+ unit_dir = Path.home() / ".config" / "systemd" / "user"
68
+ unit_dir.mkdir(parents=True, exist_ok=True)
69
+ unit_file = unit_dir / "sshmd.service"
70
+ unit_file.write_text(_SYSTEMD_UNIT.format(cmd=sshmd), encoding="utf-8")
71
+
72
+ subprocess.run(["systemctl", "--user", "daemon-reload"], check=True)
73
+ subprocess.run(["systemctl", "--user", "enable", "sshmd.service"], check=True)
74
+ subprocess.run(["systemctl", "--user", "start", "sshmd.service"], check=True)
75
+
76
+
77
+ def _linux_uninstall() -> None:
78
+ subprocess.run(["systemctl", "--user", "stop", "sshmd.service"], capture_output=True)
79
+ subprocess.run(["systemctl", "--user", "disable", "sshmd.service"], capture_output=True)
80
+ unit_file = Path.home() / ".config" / "systemd" / "user" / "sshmd.service"
81
+ unit_file.unlink(missing_ok=True)
82
+ subprocess.run(["systemctl", "--user", "daemon-reload"], capture_output=True)
83
+
84
+
85
+ # --- macOS (launchd) ---
86
+
87
+ _LAUNCHD_PLIST = """\
88
+ <?xml version="1.0" encoding="UTF-8"?>
89
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
90
+ <plist version="1.0">
91
+ <dict>
92
+ <key>Label</key>
93
+ <string>com.sshm.daemon</string>
94
+ <key>ProgramArguments</key>
95
+ <array>
96
+ {args}
97
+ </array>
98
+ <key>RunAtLoad</key>
99
+ <true/>
100
+ <key>KeepAlive</key>
101
+ <true/>
102
+ <key>StandardErrorPath</key>
103
+ <string>{log_path}</string>
104
+ </dict>
105
+ </plist>
106
+ """
107
+
108
+
109
+ def _macos_install() -> None:
110
+ sshmd = _find_sshmd()
111
+ parts = sshmd.split()
112
+ args_xml = "\n".join(f" <string>{p}</string>" for p in parts)
113
+ log_path = log_file()
114
+
115
+ plist_dir = Path.home() / "Library" / "LaunchAgents"
116
+ plist_dir.mkdir(parents=True, exist_ok=True)
117
+ plist_file = plist_dir / "com.sshm.daemon.plist"
118
+ plist_file.write_text(
119
+ _LAUNCHD_PLIST.format(args=args_xml, log_path=log_path),
120
+ encoding="utf-8",
121
+ )
122
+
123
+ subprocess.run(["launchctl", "load", str(plist_file)], check=True)
124
+
125
+
126
+ def _macos_uninstall() -> None:
127
+ plist_file = Path.home() / "Library" / "LaunchAgents" / "com.sshm.daemon.plist"
128
+ if plist_file.exists():
129
+ subprocess.run(["launchctl", "unload", str(plist_file)], capture_output=True)
130
+ plist_file.unlink(missing_ok=True)
131
+
132
+
133
+ # --- Public API ---
134
+
135
+ def install_autostart() -> str:
136
+ # Persist the effective port so the autostarted daemon — which doesn't
137
+ # inherit the interactive shell's SSHM_PORT — binds the same port the CLI
138
+ # will dial.
139
+ write_port(resolve_port())
140
+
141
+ if sys.platform == "win32":
142
+ _win_install()
143
+ return "Installed as Windows scheduled task (runs on logon)"
144
+ elif sys.platform == "darwin":
145
+ _macos_install()
146
+ return "Installed as macOS LaunchAgent"
147
+ else:
148
+ _linux_install()
149
+ return "Installed as systemd user service"
150
+
151
+
152
+ def uninstall_autostart() -> str:
153
+ port_file().unlink(missing_ok=True)
154
+
155
+ if sys.platform == "win32":
156
+ _win_uninstall()
157
+ return "Removed Windows scheduled task"
158
+ elif sys.platform == "darwin":
159
+ _macos_uninstall()
160
+ return "Removed macOS LaunchAgent"
161
+ else:
162
+ _linux_uninstall()
163
+ return "Removed systemd user service"