]> arthur.barton.de Git - bup.git/blob - cmd/on--server-cmd.py
README: add 0.30.x to CI status table
[bup.git] / cmd / on--server-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
10
11 from bup import options, helpers, path
12 from bup.compat import environ, py_maj
13 from bup.io import byte_stream
14
15 optspec = """
16 bup on--server
17 --
18     This command is run automatically by 'bup on'
19 """
20 o = options.Options(optspec)
21 (opt, flags, extra) = o.parse(sys.argv[1:])
22 if extra:
23     o.fatal('no arguments expected')
24
25 # get the subcommand's argv.
26 # Normally we could just pass this on the command line, but since we'll often
27 # be getting called on the other end of an ssh pipe, which tends to mangle
28 # argv (by sending it via the shell), this way is much safer.
29
30 stdin = byte_stream(sys.stdin)
31 buf = stdin.read(4)
32 sz = struct.unpack('!I', buf)[0]
33 assert(sz > 0)
34 assert(sz < 1000000)
35 buf = stdin.read(sz)
36 assert(len(buf) == sz)
37 argv = buf.split(b'\0')
38 argv[0] = path.exe()
39 argv = [argv[0], b'mux', b'--'] + argv
40
41
42 # stdin/stdout are supposedly connected to 'bup server' that the caller
43 # started for us (often on the other end of an ssh tunnel), so we don't want
44 # to misuse them.  Move them out of the way, then replace stdout with
45 # a pointer to stderr in case our subcommand wants to do something with it.
46 #
47 # It might be nice to do the same with stdin, but my experiments showed that
48 # ssh seems to make its child's stderr a readable-but-never-reads-anything
49 # socket.  They really should have used shutdown(SHUT_WR) on the other end
50 # of it, but probably didn't.  Anyway, it's too messy, so let's just make sure
51 # anyone reading from stdin is disappointed.
52 #
53 # (You can't just leave stdin/stdout "not open" by closing the file
54 # descriptors.  Then the next file that opens is automatically assigned 0 or 1,
55 # and people *trying* to read/write stdin/stdout get screwed.)
56 os.dup2(0, 3)
57 os.dup2(1, 4)
58 os.dup2(2, 1)
59 fd = os.open(os.devnull, os.O_RDONLY)
60 os.dup2(fd, 0)
61 os.close(fd)
62
63 environ[b'BUP_SERVER_REVERSE'] = helpers.hostname()
64 os.execvp(argv[0], argv)
65 sys.exit(99)