]> arthur.barton.de Git - bup.git/blob - lib/bup/cmd/on.py
PackWriter_Remote.close: call parent close
[bup.git] / lib / bup / cmd / on.py
1 from __future__ import absolute_import
2 from subprocess import PIPE
3 import getopt, os, signal, struct, subprocess, sys
4
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
9
10
11 optspec = """
12 bup on <hostname> index ...
13 bup on <hostname> save ...
14 bup on <hostname> split ...
15 bup on <hostname> get ...
16 """
17
18 def main(argv):
19     o = options.Options(optspec, optfunc=getopt.getopt)
20     opt, flags, extra = o.parse_bytes(argv[1:])
21     if len(extra) < 2:
22         o.fatal('arguments expected')
23
24     class SigException(Exception):
25         def __init__(self, signum):
26             self.signum = signum
27             Exception.__init__(self, 'signal %d received' % signum)
28     def handler(signum, frame):
29         raise SigException(signum)
30
31     signal.signal(signal.SIGTERM, handler)
32     signal.signal(signal.SIGINT, handler)
33
34     sys.stdout.flush()
35     out = byte_stream(sys.stdout)
36
37     try:
38         sp = None
39         p = None
40         ret = 99
41
42         hp = argv_bytes(extra[0]).split(b':')
43         if len(hp) == 1:
44             (hostname, port) = (hp[0], None)
45         else:
46             (hostname, port) = hp
47         argv = [argv_bytes(x) for x in extra[1:]]
48         p = ssh.connect(hostname, port, b'on--server', stderr=PIPE)
49
50         try:
51             argvs = b'\0'.join([b'bup'] + argv)
52             p.stdin.write(struct.pack('!I', len(argvs)) + argvs)
53             p.stdin.flush()
54             sp = subprocess.Popen([path.exe(), b'server'],
55                                   stdin=p.stdout, stdout=p.stdin)
56             p.stdin.close()
57             p.stdout.close()
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''):
61                 out.write(line)
62         finally:
63             while 1:
64                 # if we get a signal while waiting, we have to keep waiting, just
65                 # in case our child doesn't die.
66                 try:
67                     ret = p.wait()
68                     if sp:
69                         sp.wait()
70                     break
71                 except SigException as e:
72                     log('\nbup on: %s\n' % e)
73                     os.kill(p.pid, e.signum)
74                     ret = 84
75     except SigException as e:
76         if ret == 0:
77             ret = 99
78         log('\nbup on: %s\n' % e)
79
80     sys.exit(ret)