OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 # | |
5 """ | |
6 Parser for inetd.conf files | |
7 | |
8 Maintainer: U{Andrew Bennetts<mailto:spiv@twistedmatrix.com>} | |
9 | |
10 Future Plans: xinetd configuration file support? | |
11 """ | |
12 | |
13 # Various exceptions | |
14 class InvalidConfError(Exception): | |
15 """Invalid configuration file""" | |
16 | |
17 | |
18 class InvalidInetdConfError(InvalidConfError): | |
19 """Invalid inetd.conf file""" | |
20 | |
21 | |
22 class InvalidServicesConfError(InvalidConfError): | |
23 """Invalid services file""" | |
24 | |
25 | |
26 class InvalidRPCServicesConfError(InvalidConfError): | |
27 """Invalid rpc services file""" | |
28 | |
29 | |
30 class UnknownService(Exception): | |
31 """Unknown service name""" | |
32 | |
33 | |
34 class SimpleConfFile: | |
35 """Simple configuration file parser superclass. | |
36 | |
37 Filters out comments and empty lines (which includes lines that only | |
38 contain comments). | |
39 | |
40 To use this class, override parseLine or parseFields. | |
41 """ | |
42 | |
43 commentChar = '#' | |
44 defaultFilename = None | |
45 | |
46 def parseFile(self, file=None): | |
47 """Parse a configuration file | |
48 | |
49 If file is None and self.defaultFilename is set, it will open | |
50 defaultFilename and use it. | |
51 """ | |
52 if file is None and self.defaultFilename: | |
53 file = open(self.defaultFilename,'r') | |
54 | |
55 for line in file.readlines(): | |
56 # Strip out comments | |
57 comment = line.find(self.commentChar) | |
58 if comment != -1: | |
59 line = line[:comment] | |
60 | |
61 # Strip whitespace | |
62 line = line.strip() | |
63 | |
64 # Skip empty lines (and lines which only contain comments) | |
65 if not line: | |
66 continue | |
67 | |
68 self.parseLine(line) | |
69 | |
70 def parseLine(self, line): | |
71 """Override this. | |
72 | |
73 By default, this will split the line on whitespace and call | |
74 self.parseFields (catching any errors). | |
75 """ | |
76 try: | |
77 self.parseFields(*line.split()) | |
78 except ValueError: | |
79 raise InvalidInetdConfError, 'Invalid line: ' + repr(line) | |
80 | |
81 def parseFields(self, *fields): | |
82 """Override this.""" | |
83 | |
84 | |
85 class InetdService: | |
86 """A simple description of an inetd service.""" | |
87 name = None | |
88 port = None | |
89 socketType = None | |
90 protocol = None | |
91 wait = None | |
92 user = None | |
93 group = None | |
94 program = None | |
95 programArgs = None | |
96 | |
97 def __init__(self, name, port, socketType, protocol, wait, user, group, | |
98 program, programArgs): | |
99 self.name = name | |
100 self.port = port | |
101 self.socketType = socketType | |
102 self.protocol = protocol | |
103 self.wait = wait | |
104 self.user = user | |
105 self.group = group | |
106 self.program = program | |
107 self.programArgs = programArgs | |
108 | |
109 | |
110 class InetdConf(SimpleConfFile): | |
111 """Configuration parser for a traditional UNIX inetd(8)""" | |
112 | |
113 defaultFilename = '/etc/inetd.conf' | |
114 | |
115 def __init__(self, knownServices=None): | |
116 self.services = [] | |
117 | |
118 if knownServices is None: | |
119 knownServices = ServicesConf() | |
120 knownServices.parseFile() | |
121 self.knownServices = knownServices | |
122 | |
123 def parseFields(self, serviceName, socketType, protocol, wait, user, | |
124 program, *programArgs): | |
125 """Parse an inetd.conf file. | |
126 | |
127 Implemented from the description in the Debian inetd.conf man page. | |
128 """ | |
129 # Extract user (and optional group) | |
130 user, group = (user.split('.') + [None])[:2] | |
131 | |
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 | |
136 # an exception? | |
137 try: | |
138 port = int(serviceName) | |
139 serviceName = 'unknown' | |
140 except: | |
141 raise UnknownService, "Unknown service: %s (%s)" \ | |
142 % (serviceName, protocol) | |
143 | |
144 self.services.append(InetdService(serviceName, port, socketType, | |
145 protocol, wait, user, group, program, | |
146 programArgs)) | |
147 | |
148 | |
149 class ServicesConf(SimpleConfFile): | |
150 """/etc/services parser | |
151 | |
152 @ivar services: dict mapping service names to (port, protocol) tuples. | |
153 """ | |
154 | |
155 defaultFilename = '/etc/services' | |
156 | |
157 def __init__(self): | |
158 self.services = {} | |
159 | |
160 def parseFields(self, name, portAndProtocol, *aliases): | |
161 try: | |
162 port, protocol = portAndProtocol.split('/') | |
163 port = long(port) | |
164 except: | |
165 raise InvalidServicesConfError, 'Invalid port/protocol:' + \ | |
166 repr(portAndProtocol) | |
167 | |
168 self.services[(name, protocol)] = port | |
169 for alias in aliases: | |
170 self.services[(alias, protocol)] = port | |
171 | |
172 | |
173 class RPCServicesConf(SimpleConfFile): | |
174 """/etc/rpc parser | |
175 | |
176 @ivar self.services: dict mapping rpc service names to rpc ports. | |
177 """ | |
178 | |
179 defaultFilename = '/etc/rpc' | |
180 | |
181 def __init__(self): | |
182 self.services = {} | |
183 | |
184 def parseFields(self, name, port, *aliases): | |
185 try: | |
186 port = long(port) | |
187 except: | |
188 raise InvalidRPCServicesConfError, 'Invalid port:' + repr(port) | |
189 | |
190 self.services[name] = port | |
191 for alias in aliases: | |
192 self.services[alias] = port | |
193 | |
194 | |
OLD | NEW |