1 from __future__ import absolute_import
2 from subprocess import PIPE
3 import getopt, os, signal, struct, subprocess, sys
5 from bup import options, ssh, path
6 from bup.compat import argv_bytes
7 from bup.helpers import DemuxConn, log
8 from bup.io import byte_stream
12 bup on <hostname> index ...
13 bup on <hostname> save ...
14 bup on <hostname> split ...
15 bup on <hostname> get ...
19 o = options.Options(optspec, optfunc=getopt.getopt)
20 opt, flags, extra = o.parse_bytes(argv[1:])
22 o.fatal('arguments expected')
24 class SigException(Exception):
25 def __init__(self, signum):
27 Exception.__init__(self, 'signal %d received' % signum)
28 def handler(signum, frame):
29 raise SigException(signum)
31 signal.signal(signal.SIGTERM, handler)
32 signal.signal(signal.SIGINT, handler)
35 out = byte_stream(sys.stdout)
42 hp = argv_bytes(extra[0]).split(b':')
44 (hostname, port) = (hp[0], None)
47 argv = [argv_bytes(x) for x in extra[1:]]
48 p = ssh.connect(hostname, port, b'on--server', stderr=PIPE)
51 argvs = b'\0'.join([b'bup'] + argv)
52 p.stdin.write(struct.pack('!I', len(argvs)) + argvs)
54 sp = subprocess.Popen([path.exe(), b'server'],
55 stdin=p.stdout, stdout=p.stdin)
58 # Demultiplex remote client's stderr (back to stdout/stderr).
59 dmc = DemuxConn(p.stderr.fileno(), open(os.devnull, "wb"))
60 for line in iter(dmc.readline, b''):
64 # if we get a signal while waiting, we have to keep waiting, just
65 # in case our child doesn't die.
71 except SigException as e:
72 log('\nbup on: %s\n' % e)
73 os.kill(p.pid, e.signum)
75 except SigException as e:
78 log('\nbup on: %s\n' % e)