1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
7
Twisted inetd TAP support
9
Maintainer: Andrew Bennetts
11
Future Plans: more configurability.
14
import os, pwd, grp, socket
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
29
protocolDict = {'tcp': socket.IPPROTO_TCP, 'udp': socket.IPPROTO_UDP}
32
class Options(usage.Options):
35
['rpc', 'r', '/etc/rpc', 'RPC procedure table file'],
36
['file', 'f', '/etc/inetd.conf', 'Service configuration file']
39
optFlags = [['nointernal', 'i', "Don't run internal services"]]
40
zsh_actions = {"file" : "_files -g '*.conf'"}
42
class RPCServer(internet.TCPServer):
44
def __init__(self, rpcVersions, rpcConf, proto, service):
45
internet.TCPServer.__init__(0, ServerFactory())
46
self.rpcConf = rpcConf
48
self.service = service
50
def startService(self):
51
internet.TCPServer.startService(self)
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,
58
inetd.forkPassingFD(service.program, service.programArgs,
59
os.environ, service.user, service.group, p)
61
def makeService(config):
62
s = appservice.MultiService()
63
conf = inetdconf.InetdConf()
64
conf.parseFile(open(config['file']))
66
rpcConf = inetdconf.RPCServicesConf()
68
rpcConf.parseFile(open(config['rpc']))
70
# We'll survive even if we can't read /etc/rpc
73
for service in conf.services:
74
rpc = service.protocol.startswith('rpc/')
75
protocol = service.protocol
78
log.msg('Skipping rpc service due to lack of rpc support')
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)
89
name, rpcVersions = service.name.split('/')
91
log.msg('Bad RPC service/version: ' + service.name)
94
if not rpcConf.services.has_key(name):
95
log.msg('Unknown RPC service: ' + repr(service.name))
99
if '-' in rpcVersions:
100
start, end = map(int, rpcVersions.split('-'))
101
rpcVersions = range(start, end+1)
103
rpcVersions = [int(rpcVersions)]
105
log.msg('Bad RPC versions: ' + str(rpcVersions))
108
if (protocol, service.socketType) not in [('tcp', 'stream'),
110
log.msg('Skipping unsupported type/protocol: %s/%s'
111
% (service.socketType, service.protocol))
114
# Convert the username into a uid (if necessary)
116
service.user = int(service.user)
119
service.user = pwd.getpwnam(service.user)[2]
121
log.msg('Unknown user: ' + service.user)
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]
130
service.group = int(service.group)
133
service.group = grp.getgrnam(service.group)[2]
135
log.msg('Unknown group: ' + service.group)
138
if service.program == 'internal':
139
if config['nointernal']:
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)
146
factory = ServerFactory()
147
factory.protocol = inetd.internalProtocols[service.name]
149
i = RPCServer(rpcVersions, rpcConf, proto, service)
150
i.setServiceParent(s)
153
# Non-internal non-rpc services use InetdFactory
154
factory = inetd.InetdFactory(service)
156
if protocol == 'tcp':
157
internet.TCPServer(service.port, factory).setServiceParent(s)
158
elif protocol == 'udp':
159
raise RuntimeError("not supporting UDP")