Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / runner / inetdconf.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4
5 """
6 Parser for inetd.conf files
7
8 Maintainer: Andrew Bennetts
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