]> arthur.barton.de Git - bup.git/blob - lib/bup/ssh.py
cefa54385307ed290dd55c856c5fb6d50dcf90e0
[bup.git] / lib / bup / ssh.py
1 import os, re, subprocess
2 from bup import helpers
3
4 def connect(rhost, subcmd):
5     assert(not re.search(r'[^\w-]', subcmd))
6     main_exe = os.environ.get('BUP_MAIN_EXE') or sys.argv[0]
7     nicedir = os.path.split(os.path.abspath(main_exe))[0]
8     nicedir = re.sub(r':', "_", nicedir)
9     if rhost == '-':
10         rhost = None
11     if not rhost:
12         argv = ['bup', subcmd]
13     else:
14         # WARNING: shell quoting security holes are possible here, so we
15         # have to be super careful.  We have to use 'sh -c' because
16         # csh-derived shells can't handle PATH= notation.  We can't
17         # set PATH in advance, because ssh probably replaces it.  We
18         # can't exec *safely* using argv, because *both* ssh and 'sh -c'
19         # allow shellquoting.  So we end up having to double-shellquote
20         # stuff here.
21         escapedir = re.sub(r'([^\w/])', r'\\\\\\\1', nicedir)
22         force_tty = helpers.atoi(os.environ.get('BUP_FORCE_TTY'))
23         cmd = r"""
24                    sh -c PATH=%s:'$PATH BUP_FORCE_TTY=%s bup %s'
25                """ % (escapedir, force_tty, subcmd)
26         argv = ['ssh', rhost, '--', cmd.strip()]
27         #helpers.log('argv is: %r\n' % argv)
28     def setup():
29         # runs in the child process
30         if not rhost:
31             os.environ['PATH'] = ':'.join([nicedir,
32                                            os.environ.get('PATH', '')])
33         os.setsid()
34     return subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
35                             preexec_fn=setup)