8 from tempfile import NamedTemporaryFile
9 from initdutils import load_lsbinstall_info, save_lsbinstall_info
11 # These keep getting revised... *sigh*
16 'inet', # XXX - reenable when implemented
21 def installed_message(objectname):
22 print objectname, 'is installed'
24 def handle_generic_install(options, args, location, showinstloc=False):
26 basename = os.path.basename(filename)
27 instloc = os.path.join(location, basename)
28 package = args.package
30 filemap = load_lsbinstall_info()
31 fileinfo = filemap.get((package, filename))
34 if fileinfo and os.path.exists(fileinfo):
35 installed_message(fileinfo)
40 if os.path.exists(fileinfo):
43 except (IOError, OSError, os.error), why:
44 print >> sys.stderr, 'Removal of %s failed: %s' % (
48 # Remove it from the database, even if it was previously removed
49 del filemap[(package, filename)]
50 save_lsbinstall_info(filemap)
53 if os.path.exists(instloc) and options.package:
54 instloc = os.path.join(location, '%s.%s' % (options.package, basename))
56 if os.path.exists(instloc):
57 print >> sys.stderr, 'Unable to install %s: %s exists' % (
61 if not os.path.exists(location):
64 except (IOError, OSError, os.error), why:
65 print >> sys.stderr, 'Unable to create %s to install %s: %s' % (
66 location, filename, str(why))
70 shutil.copy2(filename, instloc)
71 except (IOError, os.error), why:
72 print >> sys.stderr, 'Installation of %s as %s failed: %s' % (
73 filename, instloc, str(why))
79 filemap[(package, filename)] = instloc
80 save_lsbinstall_info(filemap)
82 def handle_service(options, args):
83 # LSB says we don't actually have to remove these things...
87 pkg = options.package or '<unknown package>'
91 port, proto = pproto.split('/', 1)
94 print >> sys.stderr, 'You must specify a port/protocol pair as the first argument.'
99 serv = socket.getservbyport(port, proto)
103 print '%d/%s corresponds to service %s' % (port, proto, serv)
110 serv = socket.getservbyport(port, proto)
115 # Editing existing service
116 fpin = open('/etc/services')
117 fpout = NamedTemporaryFile('w', prefix='services-', dir='/etc')
118 newfname = fpout.name
122 if not line.startswith('#'):
125 line, lcomment = line.split('#', 1)
127 bits = line.split(None, 2)
128 lname, lpproto = bits[:2]
131 laliases = bits[2].split()
133 lport, lproto = lpproto.split('/')
136 if lport == port and lproto == proto:
137 # We've found the right line
142 if a != lname and a not in laliases:
144 elif name == lname or name in laliases:
145 # name shows up, but in wrong protocol/port
146 print >> sys.stderr, 'Conflict between specified addition and /etc/services; aborting.'
153 endbits = ' '.join(laliases) + ' '
155 endbits += '#'+lcomment
157 line = '%15s %15s %s' % lname, lpproto, endbits
164 # Make sure /etc/services is always available
165 shutil.copy2('/etc/services', '/etc/services~')
166 os.rename(newfname, '/etc/services')
169 fp = open('/etc/services', 'a')
170 print >> fp, '%15s %15s %s # Added by lsbinstall for %s' % (
171 sname, pproto, ' '.join(saliases), pkg)
174 def handle_inet(options, args, parser):
175 cmd = 'update-inetd --group LSB '
177 alist = list(args[0].split(':'))
179 parser.error("The operand must include a service and protocol.")
186 parts = r'%s\s+.*\s+%s\s+.*' % (re.escape(alist[0], alist[1]))
187 cmd += '--remove '+commands.mkarg(parts)
192 parser.error('The operand must have six colon-separated arguments.')
194 newalist = [alist[0], alist[2], alist[1]] + alist[3:]
195 cmd += '--add '+commands.mkarg('\t'.join(newalist))
200 def handle_man(options, args):
201 # Try to figure out the man page section
204 location = '/usr/local/share/man/man%d/' % section
206 handle_generic_install(options, args, location)
210 from optparse import OptionParser
212 parser = OptionParser('usage: %prog [-r|-c] -t TYPE arguments...')
213 parser.add_option('-c', '--check', dest="check", default=False,
214 action="store_true", help='check whether or not an '
215 'object of this type is already installed')
216 parser.add_option('-r', '--remove', action="store_true",
217 dest="remove", default=False,
218 help='remove the named object')
219 parser.add_option('-t', '--type', dest="type", type='choice',
220 default=None, choices=objecttypes,
221 help='type of object to be '
222 'installed: one of %s' % ', '.join(objecttypes) )
223 parser.add_option('-p', '--package', dest="package", default=None,
224 help='LSB package to operate on')
226 (options, args) = parser.parse_args()
229 parser.error('You must specify at least one argument.')
230 elif (options.remove or options.check) and len(args) > 1:
231 parser.error('You may only specify one argument with --check or '
235 parser.error('You must specify an object type.')
237 if not options.package and options.type not in ['service']:
238 parser.error('You must specify a package with %s objects.' %
241 if options.type == 'init':
243 parser.error('Only one argument supported for %s' % options.type)
244 handle_generic_install(options, args, '/etc/init.d', showinstloc=True)
245 elif options.type == 'profile':
247 parser.error('Only one argument supported for %s' % options.type)
248 # profile.d does nothing on Debian... sigh
249 handle_generic_install(options, args, '/etc/profile.d')
250 elif options.type == 'service':
251 if len(args) < 2 and not (options.remove or options.check):
252 parser.error('You must specify at least two arguments when adding a service entry.')
253 elif len(args) != 1 and (options.remove or options.check):
254 parser.error('You must specify one argument when removing or checking a service entry.')
255 handle_service(options, args)
256 elif options.type == 'inet':
257 handle_inet(options, args, parser)
258 elif options.type == 'crontab':
260 parser.error('Only one argument supported for %s' % options.type)
261 handle_generic_install(options, args, '/etc/cron.d')
262 elif options.type == 'man':
264 parser.error('Only one argument supported for %s' % options.type)
265 handle_man(options, args)
267 print >> sys.stderr, 'Unsupported type %s' % options.type
270 if __name__ == '__main__':