import std/[os, osproc, sequtils, strformat, strutils, sugar] import hwylterm proc checkHost(host: seq[string]): string = case host.len: of 1: return host[0] of 0: quit $bb"[red]expected hostname" else: quit $bb"[red]expected one positional argument" proc check(name: string): bool = (execCmd &"ssh -O check {name}") == 0 proc startSsh(name: string) = discard execCmd &"ssh -M -f -N {name}" proc activateTunnel(name: string, port: int): int = execCmd &"""ssh -fNL "{port}:localhost:{port}" {name}""" proc exitSsh(name: string):int = execCmd &"ssh -O exit {name}" proc up(port: int, host: seq[string]) = ## activate a tunnel let name = checkHost host echo "activating connection to: ", name if not check(name): startSsh(name) quit activateTunnel(name, port) proc down(host: seq[string]) = ## disable all tunnels for a host let name = checkHost host echo "deactivating connection to: ", name quit exitSsh(name) proc collectControllers(): seq[string] = let sshDir = (getEnv "HOME") / ".ssh" collect(for _,p in walkDir(sshDir): p) .map(extractFilename) .filterIt(it.startsWith("control")) proc killCmd() = ## kill all open tunnels let controllers = collectControllers() if controllers.len == 0: quit 0 for c in controllers: let host = c.lastPathPart().split("-")[2] let code = exitSsh(host) if code != 0: quit $bb"[red][[Error]failed to exit connection for host: " & host proc show() = ## show active connections let controllers = collectControllers() echo bbfmt"[yellow]{controllers.len}[/] active connections" if controllers.len == 0: quit 0 echo "hosts:" echo controllers.mapIt(" " & it.split('-')[1]).join("\n") when isMainModule: import cligen, hwylterm/cligen hwylCli(clCfg) let hostUse = $bb("$command [green]hostname[/] [[[i]flags[/]]\n${doc}[b]Options[/]:\n$options") dispatchMulti( [up , usage=hostUse ], [down , usage=hostUse ], [show , usage=clCfg.use ], [killCmd, usage=clCfg.use, cmdName = "kill"], )