]> arthur.barton.de Git - bup.git/blob - lib/cmd/daemon-cmd.py
Bypass Python 3 glibc argv problems by routing args through env
[bup.git] / lib / cmd / daemon-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")/bup-python" || exit $?
13 exec "$bup_python" "$0"
14 """
15 # end of bup preamble
16
17 from __future__ import absolute_import
18 import sys, getopt, socket, subprocess, fcntl
19
20 from bup import compat, options, path
21 from bup.helpers import *
22
23 optspec = """
24 bup daemon [options...] -- [bup-server options...]
25 --
26 l,listen  ip address to listen on, defaults to *
27 p,port    port to listen on, defaults to 1982
28 """
29 o = options.Options(optspec, optfunc=getopt.getopt)
30 opt, flags, extra = o.parse(compat.argv[1:])
31
32 host = opt.listen
33 port = opt.port and int(opt.port) or 1982
34
35 import socket
36 import sys
37
38 socks = []
39 e = None
40 for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC,
41                               socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
42     af, socktype, proto, canonname, sa = res
43     try:
44         s = socket.socket(af, socktype, proto)
45     except socket.error as e:
46         continue
47     try:
48         if af == socket.AF_INET6:
49             log("bup daemon: listening on [%s]:%s\n" % sa[:2])
50         else:
51             log("bup daemon: listening on %s:%s\n" % sa[:2])
52         s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
53         s.bind(sa)
54         s.listen(1)
55         fcntl.fcntl(s.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
56     except socket.error as e:
57         s.close()
58         continue
59     socks.append(s)
60
61 if not socks:
62     log('bup daemon: listen socket: %s\n' % e.args[1])
63     sys.exit(1)
64
65 try:
66     while True:
67         [rl,wl,xl] = select.select(socks, [], [], 60)
68         for l in rl:
69             s, src = l.accept()
70             try:
71                 log("Socket accepted connection from %s\n" % (src,))
72                 fd1 = os.dup(s.fileno())
73                 fd2 = os.dup(s.fileno())
74                 s.close()
75                 sp = subprocess.Popen([path.exe(), 'mux', '--',
76                                        path.exe(), 'server']
77                                       + extra, stdin=fd1, stdout=fd2)
78             finally:
79                 os.close(fd1)
80                 os.close(fd2)
81 finally:
82     for l in socks:
83         l.shutdown(socket.SHUT_RDWR)
84         l.close()
85
86 debug1("bup daemon: done")