root / trunk / twisted / runner / inetdtap.py

Revision 24441, 5.1 kB (checked in by thijs, 1 year ago)

Merge maintainer-email-2438: Get rid of references to maintainer email addresses from code.

Author: thijs
Reviewer: exarkun
Fixes: #2438

Line 
1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 #
5
6 """
7 Twisted inetd TAP support
8
9 Maintainer: Andrew Bennetts
10
11 Future Plans: more configurability.
12 """
13
14 import os, pwd, grp, socket
15
16 from twisted.runner import inetd, inetdconf
17 from twisted.python import log, usage
18 from twisted.internet.protocol import ServerFactory
19 from twisted.application import internet, service as appservice
20
21 try:
22     import portmap
23     rpcOk = 1
24 except ImportError:
25     rpcOk = 0
26
27
28 # Protocol map
29 protocolDict = {'tcp': socket.IPPROTO_TCP, 'udp': socket.IPPROTO_UDP}
30
31
32 class Options(usage.Options):
33
34     optParameters = [
35         ['rpc', 'r', '/etc/rpc', 'RPC procedure table file'],
36         ['file', 'f', '/etc/inetd.conf', 'Service configuration file']
37     ]
38
39     optFlags = [['nointernal', 'i', "Don't run internal services"]]
40     zsh_actions = {"file" : "_files -g '*.conf'"}
41
42 class RPCServer(internet.TCPServer):
43
44     def __init__(self, rpcVersions, rpcConf, proto, service):
45         internet.TCPServer.__init__(0, ServerFactory())
46         self.rpcConf = rpcConf
47         self.proto = proto
48         self.service = service
49
50     def startService(self):
51         internet.TCPServer.startService(self)
52         import portmap
53         portNo = self._port.getHost()[2]
54         service = self.service
55         for version in rpcVersions:
56             portmap.set(self.rpcConf.services[name], version, self.proto,
57                         portNo)
58             inetd.forkPassingFD(service.program, service.programArgs,
59                                 os.environ, service.user, service.group, p)
60
61 def makeService(config):
62     s = appservice.MultiService()
63     conf = inetdconf.InetdConf()
64     conf.parseFile(open(config['file']))
65
66     rpcConf = inetdconf.RPCServicesConf()
67     try:
68         rpcConf.parseFile(open(config['rpc']))
69     except:
70         # We'll survive even if we can't read /etc/rpc
71         log.deferr()
72    
73     for service in conf.services:
74         rpc = service.protocol.startswith('rpc/')
75         protocol = service.protocol
76
77         if rpc and not rpcOk:
78             log.msg('Skipping rpc service due to lack of rpc support')
79             continue
80
81         if rpc:
82             # RPC has extra options, so extract that
83             protocol = protocol[4:]     # trim 'rpc/'
84             if not protocolDict.has_key(protocol):
85                 log.msg('Bad protocol: ' + protocol)
86                 continue
87            
88             try:
89                 name, rpcVersions = service.name.split('/')
90             except ValueError:
91                 log.msg('Bad RPC service/version: ' + service.name)
92                 continue
93
94             if not rpcConf.services.has_key(name):
95                 log.msg('Unknown RPC service: ' + repr(service.name))
96                 continue
97
98             try:
99                 if '-' in rpcVersions:
100                     start, end = map(int, rpcVersions.split('-'))
101                     rpcVersions = range(start, end+1)
102                 else:
103                     rpcVersions = [int(rpcVersions)]
104             except ValueError:
105                 log.msg('Bad RPC versions: ' + str(rpcVersions))
106                 continue
107            
108         if (protocol, service.socketType) not in [('tcp', 'stream'),
109                                                   ('udp', 'dgram')]:
110             log.msg('Skipping unsupported type/protocol: %s/%s'
111                     % (service.socketType, service.protocol))
112             continue
113
114         # Convert the username into a uid (if necessary)
115         try:
116             service.user = int(service.user)
117         except ValueError:
118             try:
119                 service.user = pwd.getpwnam(service.user)[2]
120             except KeyError:
121                 log.msg('Unknown user: ' + service.user)
122                 continue
123
124         # Convert the group name into a gid (if necessary)
125         if service.group is None:
126             # If no group was specified, use the user's primary group
127             service.group = pwd.getpwuid(service.user)[3]
128         else:
129             try:
130                 service.group = int(service.group)
131             except ValueError:
132                 try:
133                     service.group = grp.getgrnam(service.group)[2]
134                 except KeyError:
135                     log.msg('Unknown group: ' + service.group)
136                     continue
137
138         if service.program == 'internal':
139             if config['nointernal']:
140                 continue
141
142             # Internal services can use a standard ServerFactory
143             if not inetd.internalProtocols.has_key(service.name):
144                 log.msg('Unknown internal service: ' + service.name)
145                 continue
146             factory = ServerFactory()
147             factory.protocol = inetd.internalProtocols[service.name]
148         elif rpc:
149             i = RPCServer(rpcVersions, rpcConf, proto, service)
150             i.setServiceParent(s)
151             continue
152         else:
153             # Non-internal non-rpc services use InetdFactory
154             factory = inetd.InetdFactory(service)
155
156         if protocol == 'tcp':
157             internet.TCPServer(service.port, factory).setServiceParent(s)
158         elif protocol == 'udp':
159             raise RuntimeError("not supporting UDP")
160     return s
Note: See TracBrowser for help on using the browser.