]> arthur.barton.de Git - bup.git/blob - lib/bup/cmd/daemon.py
Remove Client __del__ in favor of context management
[bup.git] / lib / bup / cmd / daemon.py
1
2 from __future__ import absolute_import
3 import fcntl, getopt, os, socket, subprocess, sys, select
4
5 from bup import options, path
6 from bup.helpers import log, debug1
7
8
9 optspec = """
10 bup daemon [options...] -- [bup-server options...]
11 --
12 l,listen  ip address to listen on, defaults to *
13 p,port    port to listen on, defaults to 1982
14 """
15
16 def main(argv):
17     o = options.Options(optspec, optfunc=getopt.getopt)
18     opt, flags, extra = o.parse_bytes(argv[1:])
19
20     host = opt.listen
21     port = opt.port and int(opt.port) or 1982
22     socks = []
23     e = None
24     for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC,
25                                   socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
26         af, socktype, proto, canonname, sa = res
27         try:
28             s = socket.socket(af, socktype, proto)
29         except socket.error as e:
30             continue
31         try:
32             if af == socket.AF_INET6:
33                 log("bup daemon: listening on [%s]:%s\n" % sa[:2])
34             else:
35                 log("bup daemon: listening on %s:%s\n" % sa[:2])
36             s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
37             s.bind(sa)
38             s.listen(1)
39             fcntl.fcntl(s.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
40         except socket.error as e:
41             s.close()
42             continue
43         socks.append(s)
44
45     if not socks:
46         log('bup daemon: listen socket: %s\n' % e.args[1])
47         sys.exit(1)
48
49     try:
50         while True:
51             [rl,wl,xl] = select.select(socks, [], [], 60)
52             for l in rl:
53                 s, src = l.accept()
54                 try:
55                     log("Socket accepted connection from %s\n" % (src,))
56                     fd1 = os.dup(s.fileno())
57                     fd2 = os.dup(s.fileno())
58                     s.close()
59                     sp = subprocess.Popen([path.exe(), 'mux', '--',
60                                            path.exe(), 'server']
61                                           + extra, stdin=fd1, stdout=fd2)
62                 finally:
63                     os.close(fd1)
64                     os.close(fd2)
65     finally:
66         for l in socks:
67             l.shutdown(socket.SHUT_RDWR)
68             l.close()
69
70     debug1("bup daemon: done")