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