From: Fredrik Tolf Date: Sun, 15 Jan 2012 07:06:54 +0000 (+0100) Subject: Merge branch 'master' into python3 X-Git-Url: http://dolda2000.com/gitweb/?p=pdm.git;a=commitdiff_plain;h=5d0664aa6dde860573fe4bcf8d1b312b7c6c4271;hp=d7ad337ed6a9350932b83ed320c4ebd39621e355 Merge branch 'master' into python3 --- diff --git a/pdm/__init__.py b/pdm/__init__.py index b3cce04..537a31e 100644 --- a/pdm/__init__.py +++ b/pdm/__init__.py @@ -9,7 +9,7 @@ This package contains the following modules: - srv -- Server module - cli -- Client module - - perf -- Library for implementing object for the PERF protocol + - perf -- Library for implementing objects for the PERF protocol The protocol allows multiple management subprotocols for different modes of operation. Currently, the following two management protocols @@ -19,13 +19,13 @@ are supported. accepts arbitrary Python code, executes it in the daemon process, and returns its replies, all in text form. The protocol is simple, generic, and has few failure modes, but is hardly suitable for - programmatic interaction. See the documentation for pdm.srv.repl - and pdm.cli.replclient for further details. + programmatic interaction. See the documentation for L{pdm.srv.repl} + and L{pdm.cli.replclient} for further details. - The PERF protocol is intended for programmatic interaction with the daemon process. Various Python modules may expose objects that implement one or several of a few pre-defined interfaces that allow for various forms of inspection and management of the program - state. See the documentation for pdm.srv.perf and - pdm.cli.perfclient for further details. + state. See the documentation for L{pdm.srv.perf} and + L{pdm.cli.perfclient} for further details. """ diff --git a/pdm/cli.py b/pdm/cli.py index 0b31682..272be86 100644 --- a/pdm/cli.py +++ b/pdm/cli.py @@ -19,16 +19,21 @@ def resolve(spec): return spec sk = None try: - if "/" in spec: + if ":" in spec: + p = spec.rindex(":") + first, second = spec[:p], spec[p + 1:] + if "/" in second: + import sshsock + sk = sshsock.sshsocket(first, second) + else: + sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sk.connect((first, second)) + elif "/" in spec: sk = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sk.connect(spec) elif spec.isdigit(): sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.connect(("localhost", int(spec))) - elif ":" in spec: - sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - p = spec.rindex(":") - sk.connect((spec[:p], int(spec[p + 1:]))) else: raise Exception("Unknown target specification %r" % spec) rv = sk diff --git a/pdm/sshsock.py b/pdm/sshsock.py new file mode 100644 index 0000000..feb2f9f --- /dev/null +++ b/pdm/sshsock.py @@ -0,0 +1,73 @@ +import sys, os +import subprocess, socket, fcntl, select + +class sshsocket(object): + def __init__(self, host, path, user = None, port = None): + args = ["ssh"] + if user is not None: + args += ["-u", str(user)] + if port is not None: + args += ["-p", str(int(port))] + args += [host] + args += ["python", "-m", "pdm.sshsock", path] + self.proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) + fcntl.fcntl(self.proc.stdout, fcntl.F_SETFL, fcntl.fcntl(self.proc.stdout, fcntl.F_GETFL) | os.O_NONBLOCK) + + def close(self): + if self.proc is not None: + self.proc.stdin.close() + self.proc.stdout.close() + self.proc.wait() + self.proc = None + + def send(self, data, flags = 0): + self.proc.stdin.write(data) + return len(data) + + def recv(self, buflen, flags = 0): + if (flags & socket.MSG_DONTWAIT) == 0: + select.select([self.proc.stdout], [], []) + return self.proc.stdout.read(buflen) + + def fileno(self): + return self.proc.stdout.fileno() + + def __del__(self): + self.close() + +def cli(): + fcntl.fcntl(sys.stdin, fcntl.F_SETFL, fcntl.fcntl(sys.stdin, fcntl.F_GETFL) | os.O_NONBLOCK) + sk = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + sk.connect(sys.argv[1]) + buf1 = "" + buf2 = "" + while True: + wfd = [] + if buf1: wfd.append(sk) + if buf2: wfd.append(sys.stdout) + rfd, wfd, efd = select.select([sk, sys.stdin], wfd, []) + if sk in rfd: + ret = sk.recv(65536) + if ret == "": + break + else: + buf2 += ret + if sys.stdin in rfd: + ret = sys.stdin.read() + if ret == "": + break + else: + buf1 = ret + if sk in wfd: + ret = sk.send(buf1) + buf1 = buf1[ret:] + if sys.stdout in wfd: + sys.stdout.write(buf2) + sys.stdout.flush() + buf2 = "" + finally: + sk.close() + +if __name__ == "__main__": + cli()