1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
6 Parser for inetd.conf files
8 Maintainer: Andrew Bennetts
10 Future Plans: xinetd configuration file support?
14 class InvalidConfError(Exception):
15 """Invalid configuration file"""
18 class InvalidInetdConfError(InvalidConfError):
19 """Invalid inetd.conf file"""
22 class InvalidServicesConfError(InvalidConfError):
23 """Invalid services file"""
26 class InvalidRPCServicesConfError(InvalidConfError):
27 """Invalid rpc services file"""
30 class UnknownService(Exception):
31 """Unknown service name"""
35 """Simple configuration file parser superclass.
37 Filters out comments and empty lines (which includes lines that only
40 To use this class, override parseLine or parseFields.
44 defaultFilename = None
46 def parseFile(self, file=None):
47 """Parse a configuration file
49 If file is None and self.defaultFilename is set, it will open
50 defaultFilename and use it.
52 if file is None and self.defaultFilename:
53 file = open(self.defaultFilename,'r')
55 for line in file.readlines():
57 comment = line.find(self.commentChar)
64 # Skip empty lines (and lines which only contain comments)
70 def parseLine(self, line):
73 By default, this will split the line on whitespace and call
74 self.parseFields (catching any errors).
77 self.parseFields(*line.split())
79 raise InvalidInetdConfError, 'Invalid line: ' + repr(line)
81 def parseFields(self, *fields):
86 """A simple description of an inetd service."""
97 def __init__(self, name, port, socketType, protocol, wait, user, group,
98 program, programArgs):
101 self.socketType = socketType
102 self.protocol = protocol
106 self.program = program
107 self.programArgs = programArgs
110 class InetdConf(SimpleConfFile):
111 """Configuration parser for a traditional UNIX inetd(8)"""
113 defaultFilename = '/etc/inetd.conf'
115 def __init__(self, knownServices=None):
118 if knownServices is None:
119 knownServices = ServicesConf()
120 knownServices.parseFile()
121 self.knownServices = knownServices
123 def parseFields(self, serviceName, socketType, protocol, wait, user,
124 program, *programArgs):
125 """Parse an inetd.conf file.
127 Implemented from the description in the Debian inetd.conf man page.
129 # Extract user (and optional group)
130 user, group = (user.split('.') + [None])[:2]
132 # Find the port for a service
133 port = self.knownServices.services.get((serviceName, protocol), None)
134 if not port and not protocol.startswith('rpc/'):
135 # FIXME: Should this be discarded/ignored, rather than throwing
138 port = int(serviceName)
139 serviceName = 'unknown'
141 raise UnknownService, "Unknown service: %s (%s)" \
142 % (serviceName, protocol)
144 self.services.append(InetdService(serviceName, port, socketType,
145 protocol, wait, user, group, program,
149 class ServicesConf(SimpleConfFile):
150 """/etc/services parser
152 @ivar services: dict mapping service names to (port, protocol) tuples.
155 defaultFilename = '/etc/services'
160 def parseFields(self, name, portAndProtocol, *aliases):
162 port, protocol = portAndProtocol.split('/')
165 raise InvalidServicesConfError, 'Invalid port/protocol:' + \
166 repr(portAndProtocol)
168 self.services[(name, protocol)] = port
169 for alias in aliases:
170 self.services[(alias, protocol)] = port
173 class RPCServicesConf(SimpleConfFile):
176 @ivar self.services: dict mapping rpc service names to rpc ports.
179 defaultFilename = '/etc/rpc'
184 def parseFields(self, name, port, *aliases):
188 raise InvalidRPCServicesConfError, 'Invalid port:' + repr(port)
190 self.services[name] = port
191 for alias in aliases:
192 self.services[alias] = port