]> arthur.barton.de Git - bup.git/blob - lib/cmd/on--server-cmd.py
Remove $(dirname "$0") from sys.path
[bup.git] / lib / cmd / on--server-cmd.py
1 #!/bin/sh
2 """": # -*-python-*-
3 # https://sourceware.org/bugzilla/show_bug.cgi?id=26034
4 export "BUP_ARGV_0"="$0"
5 arg_i=1
6 for arg in "$@"; do
7     export "BUP_ARGV_${arg_i}"="$arg"
8     shift
9     arg_i=$((arg_i + 1))
10 done
11 # Here to end of preamble replaced during install
12 bup_python="$(dirname "$0")/../../config/bin/python" || exit $?
13 exec "$bup_python" "$0"
14 """
15 # end of bup preamble
16
17 from __future__ import absolute_import
18
19 # Intentionally replace the dirname "$0" that python prepends
20 import os, sys
21 sys.path[0] = os.path.dirname(os.path.realpath(__file__)) + '/..'
22
23 import struct
24
25 from bup import compat, options, helpers, path
26 from bup.compat import environ, py_maj
27 from bup.io import byte_stream
28
29 optspec = """
30 bup on--server
31 --
32     This command is run automatically by 'bup on'
33 """
34 o = options.Options(optspec)
35 opt, flags, extra = o.parse(compat.argv[1:])
36 if extra:
37     o.fatal('no arguments expected')
38
39 # get the subcommand's argv.
40 # Normally we could just pass this on the command line, but since we'll often
41 # be getting called on the other end of an ssh pipe, which tends to mangle
42 # argv (by sending it via the shell), this way is much safer.
43
44 stdin = byte_stream(sys.stdin)
45 buf = stdin.read(4)
46 sz = struct.unpack('!I', buf)[0]
47 assert(sz > 0)
48 assert(sz < 1000000)
49 buf = stdin.read(sz)
50 assert(len(buf) == sz)
51 argv = buf.split(b'\0')
52 argv[0] = path.exe()
53 argv = [argv[0], b'mux', b'--'] + argv
54
55
56 # stdin/stdout are supposedly connected to 'bup server' that the caller
57 # started for us (often on the other end of an ssh tunnel), so we don't want
58 # to misuse them.  Move them out of the way, then replace stdout with
59 # a pointer to stderr in case our subcommand wants to do something with it.
60 #
61 # It might be nice to do the same with stdin, but my experiments showed that
62 # ssh seems to make its child's stderr a readable-but-never-reads-anything
63 # socket.  They really should have used shutdown(SHUT_WR) on the other end
64 # of it, but probably didn't.  Anyway, it's too messy, so let's just make sure
65 # anyone reading from stdin is disappointed.
66 #
67 # (You can't just leave stdin/stdout "not open" by closing the file
68 # descriptors.  Then the next file that opens is automatically assigned 0 or 1,
69 # and people *trying* to read/write stdin/stdout get screwed.)
70 os.dup2(0, 3)
71 os.dup2(1, 4)
72 os.dup2(2, 1)
73 fd = os.open(os.devnull, os.O_RDONLY)
74 os.dup2(fd, 0)
75 os.close(fd)
76
77 environ[b'BUP_SERVER_REVERSE'] = helpers.hostname()
78 os.execvp(argv[0], argv)
79 sys.exit(99)