1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
6
"""Twisted inetd TAP support
10
Maintainer: U{Andrew Bennetts<mailto:spiv@twistedmatrix.com>}
12
Future Plans: more configurability.
15
import os, pwd, grp, socket
17
from twisted.runner import inetd, inetdconf
18
from twisted.python import log, usage
19
from twisted.internet.protocol import ServerFactory
20
from twisted.application import internet, service as appservice
30
protocolDict = {'tcp': socket.IPPROTO_TCP, 'udp': socket.IPPROTO_UDP}
33
class Options(usage.Options):
36
['rpc', 'r', '/etc/rpc', 'RPC procedure table file'],
37
['file', 'f', '/etc/inetd.conf', 'Service configuration file']
40
optFlags = [['nointernal', 'i', "Don't run internal services"]]
41
zsh_actions = {"file" : "_files -g '*.conf'"}
43
class RPCServer(internet.TCPServer):
45
def __init__(self, rpcVersions, rpcConf, proto, service):
46
internet.TCPServer.__init__(0, ServerFactory())
47
self.rpcConf = rpcConf
49
self.service = service
51
def startService(self):
52
internet.TCPServer.startService(self)
54
portNo = self._port.getHost()[2]
55
service = self.service
56
for version in rpcVersions:
57
portmap.set(self.rpcConf.services[name], version, self.proto,
59
inetd.forkPassingFD(service.program, service.programArgs,
60
os.environ, service.user, service.group, p)
62
def makeService(config):
63
s = appservice.MultiService()
64
conf = inetdconf.InetdConf()
65
conf.parseFile(open(config['file']))
67
rpcConf = inetdconf.RPCServicesConf()
69
rpcConf.parseFile(open(config['rpc']))
71
# We'll survive even if we can't read /etc/rpc
74
for service in conf.services:
75
rpc = service.protocol.startswith('rpc/')
76
protocol = service.protocol
79
log.msg('Skipping rpc service due to lack of rpc support')
83
# RPC has extra options, so extract that
84
protocol = protocol[4:] # trim 'rpc/'
85
if not protocolDict.has_key(protocol):
86
log.msg('Bad protocol: ' + protocol)
90
name, rpcVersions = service.name.split('/')
92
log.msg('Bad RPC service/version: ' + service.name)
95
if not rpcConf.services.has_key(name):
96
log.msg('Unknown RPC service: ' + repr(service.name))
100
if '-' in rpcVersions:
101
start, end = map(int, rpcVersions.split('-'))
102
rpcVersions = range(start, end+1)
104
rpcVersions = [int(rpcVersions)]
106
log.msg('Bad RPC versions: ' + str(rpcVersions))
109
if (protocol, service.socketType) not in [('tcp', 'stream'),
111
log.msg('Skipping unsupported type/protocol: %s/%s'
112
% (service.socketType, service.protocol))
115
# Convert the username into a uid (if necessary)
117
service.user = int(service.user)
120
service.user = pwd.getpwnam(service.user)[2]
122
log.msg('Unknown user: ' + service.user)
125
# Convert the group name into a gid (if necessary)
126
if service.group is None:
127
# If no group was specified, use the user's primary group
128
service.group = pwd.getpwuid(service.user)[3]
131
service.group = int(service.group)
134
service.group = grp.getgrnam(service.group)[2]
136
log.msg('Unknown group: ' + service.group)
139
if service.program == 'internal':
140
if config['nointernal']:
143
# Internal services can use a standard ServerFactory
144
if not inetd.internalProtocols.has_key(service.name):
145
log.msg('Unknown internal service: ' + service.name)
147
factory = ServerFactory()
148
factory.protocol = inetd.internalProtocols[service.name]
150
i = RPCServer(rpcVersions, rpcConf, proto, service)
151
i.setServiceParent(s)
154
# Non-internal non-rpc services use InetdFactory
155
factory = inetd.InetdFactory(service)
157
if protocol == 'tcp':
158
internet.TCPServer(service.port, factory).setServiceParent(s)
159
elif protocol == 'udp':
160
raise RuntimeError("not supporting UDP")