1#!/bin/sh 2"""": # -*-python-*- 3# https://sourceware.org/bugzilla/show_bug.cgi?id=26034 4export "BUP_ARGV_0"="$0" 5arg_i=1 6for arg in "$@"; do 7 export "BUP_ARGV_${arg_i}"="$arg" 8 shift 9 arg_i=$((arg_i + 1)) 10done 11# Here to end of preamble replaced during install 12bup_python="$(dirname "$0")/../../config/bin/python" || exit $? 13exec "$bup_python" "$0" 14""" 15# end of bup preamble 16 17from __future__ import absolute_import 18from subprocess import PIPE 19import getopt, os, signal, struct, subprocess, sys 20 21sys.path[:0] = [os.path.dirname(os.path.realpath(__file__)) + '/..'] 22 23from bup import compat, options, ssh, path 24from bup.compat import argv_bytes 25from bup.helpers import DemuxConn, log 26from bup.io import byte_stream 27 28 29optspec = """ 30bup on <hostname> index ... 31bup on <hostname> save ... 32bup on <hostname> split ... 33bup on <hostname> get ... 34""" 35o = options.Options(optspec, optfunc=getopt.getopt) 36opt, flags, extra = o.parse(compat.argv[1:]) 37if len(extra) < 2: 38 o.fatal('arguments expected') 39 40class SigException(Exception): 41 def __init__(self, signum): 42 self.signum = signum 43 Exception.__init__(self, 'signal %d received' % signum) 44def handler(signum, frame): 45 raise SigException(signum) 46 47signal.signal(signal.SIGTERM, handler) 48signal.signal(signal.SIGINT, handler) 49 50sys.stdout.flush() 51out = byte_stream(sys.stdout) 52 53try: 54 sp = None 55 p = None 56 ret = 99 57 58 hp = argv_bytes(extra[0]).split(b':') 59 if len(hp) == 1: 60 (hostname, port) = (hp[0], None) 61 else: 62 (hostname, port) = hp 63 argv = [argv_bytes(x) for x in extra[1:]] 64 p = ssh.connect(hostname, port, b'on--server', stderr=PIPE) 65 66 try: 67 argvs = b'\0'.join([b'bup'] + argv) 68 p.stdin.write(struct.pack('!I', len(argvs)) + argvs) 69 p.stdin.flush() 70 sp = subprocess.Popen([path.exe(), b'server'], 71 stdin=p.stdout, stdout=p.stdin) 72 p.stdin.close() 73 p.stdout.close() 74 # Demultiplex remote client's stderr (back to stdout/stderr). 75 dmc = DemuxConn(p.stderr.fileno(), open(os.devnull, "wb")) 76 for line in iter(dmc.readline, b''): 77 out.write(line) 78 finally: 79 while 1: 80 # if we get a signal while waiting, we have to keep waiting, just 81 # in case our child doesn't die. 82 try: 83 ret = p.wait() 84 if sp: 85 sp.wait() 86 break 87 except SigException as e: 88 log('\nbup on: %s\n' % e) 89 os.kill(p.pid, e.signum) 90 ret = 84 91except SigException as e: 92 if ret == 0: 93 ret = 99 94 log('\nbup on: %s\n' % e) 95 96sys.exit(ret) 97