]> arthur.barton.de Git - bup.git/blob - cmd/on-cmd.py
Add bup get; see the documentation for further information
[bup.git] / cmd / on-cmd.py
1 #!/bin/sh
2 """": # -*-python-*-
3 bup_python="$(dirname "$0")/bup-python" || exit $?
4 exec "$bup_python" "$0" ${1+"$@"}
5 """
6 # end of bup preamble
7
8 from __future__ import absolute_import
9 import sys, os, struct, getopt, subprocess, signal
10
11 from subprocess import PIPE
12 from bup import options, ssh, path
13 from bup.helpers import DemuxConn, log
14
15
16 optspec = """
17 bup on <hostname> index ...
18 bup on <hostname> save ...
19 bup on <hostname> split ...
20 bup on <hostname> get ...
21 """
22 o = options.Options(optspec, optfunc=getopt.getopt)
23 (opt, flags, extra) = o.parse(sys.argv[1:])
24 if len(extra) < 2:
25     o.fatal('arguments expected')
26
27 class SigException(Exception):
28     def __init__(self, signum):
29         self.signum = signum
30         Exception.__init__(self, 'signal %d received' % signum)
31 def handler(signum, frame):
32     raise SigException(signum)
33
34 signal.signal(signal.SIGTERM, handler)
35 signal.signal(signal.SIGINT, handler)
36
37 try:
38     sp = None
39     p = None
40     ret = 99
41
42     hp = extra[0].split(':')
43     if len(hp) == 1:
44         (hostname, port) = (hp[0], None)
45     else:
46         (hostname, port) = hp
47     argv = extra[1:]
48     p = ssh.connect(hostname, port, 'on--server', stderr=PIPE)
49
50     try:
51         argvs = '\0'.join(['bup'] + argv)
52         p.stdin.write(struct.pack('!I', len(argvs)) + argvs)
53         p.stdin.flush()
54         sp = subprocess.Popen([path.exe(), '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, "w"))
60         for line in iter(dmc.readline, ""):
61             sys.stdout.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)