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