X-Git-Url: http://git.steven-mcdonald.id.au/?p=aids.git;a=blobdiff_plain;f=lib%2Faids.rb;h=ab3e4a50b2e59dbbb6df7a0e786c72a457924a7a;hp=c2a7e66c020df30a629c59db8c9609c22fcbe1bd;hb=e0f5c5f1767ed0e441e25204ad237f338f05f001;hpb=16da2ea2a6c6d9b70ea3b3424d80b0f8a68b6cec diff --git a/lib/aids.rb b/lib/aids.rb index c2a7e66..ab3e4a5 100644 --- a/lib/aids.rb +++ b/lib/aids.rb @@ -1,33 +1,45 @@ +# Copyright (C) 2012 Steven McDonald +# +# This program is free software. It comes without any warranty, to the +# extent permitted by applicable law. You can redistribute it and/or +# modify it under the terms of the Do What The Fuck You Want To Public +# License, Version 2, as published by Sam Hocevar. See the file COPYING +# in the root of this program's source distribution for details, or: +# +# http://sam.zoy.org/wtfpl/COPYING + module AIDS - RUNLEVEL_SINGLE = 'S' - RUNLEVEL_MULTI_TO_SINGLE = '1' - RUNLEVEL_MULTI = '2' - RUNLEVEL_HALT = '0' - RUNLEVEL_REBOOT = '6' + RUNLEVEL_SINGLE = :'S' + RUNLEVEL_MULTI_TO_SINGLE = :'1' + RUNLEVEL_MULTI = :'2' + RUNLEVEL_MULTI_ALL = [:'2',:'3',:'4',:'5'] + RUNLEVEL_HALT = :'0' + RUNLEVEL_REBOOT = :'6' + RUNLEVEL_ALL = [:'0',:'1',:'2',:'3',:'4',:'5',:'6',:'S'] class Service attr_reader :name def initialize(name) if name.nil? or name.empty? or not name.is_a?(String) - raise Exception.new("Service name must be a non-empty string, got #{name.inspect}.") + raise AIDS::Infection.new("Service name must be a non-empty string, got #{name.inspect}.") end name = $1 if name =~ %r{^/etc/init\.d/(.+)$} - if name =~ /[^[:alnum:]\-.]/ - raise Exception.new("Invalid init script name: #{name}.") + if name =~ /[^[:alnum:]\-._]/ + raise AIDS::Infection.new("Invalid init script name: #{name}.") end unless File.exist?("/etc/init.d/#{name}") - raise Exception.new("Unknown service: #{name}.") + raise AIDS::Infection.new("Unknown service: #{name}.") end @name = name end def enable! - start_on_runlevel!(RUNLEVEL_MULTI) + start_on_runlevels!(RUNLEVEL_MULTI_ALL) end def disable! - stop_on_runlevel!(RUNLEVEL_MULTI) + stop_on_runlevels!(RUNLEVEL_MULTI_ALL) end def enabled? @@ -35,13 +47,17 @@ module AIDS end def status - if started_on_runlevel?(RUNLEVEL_MULTI) - :enabled - elsif stopped_on_runlevel?(RUNLEVEL_MULTI) - :disabled - else - :unknown + status = {} + RUNLEVEL_ALL.each do |r| + if started_on_runlevel?(r) + status[r] = :start + elsif stopped_on_runlevel?(r) + status[r] = :stop + else + status[r] = :none + end end + status end private @@ -56,16 +72,20 @@ module AIDS not Dir.glob("/etc/rc#{runlevel}.d/K[0-9][0-9]#{@name}").empty? end - def start_on_runlevel!(runlevel) - AIDS.validate_runlevel(runlevel) - return true if started_on_runlevel?(runlevel) - updatercd(:enable, runlevel) + def start_on_runlevels!(runlevels) + [runlevels].flatten.each do |r| + AIDS.validate_runlevel(r) + next if started_on_runlevel?(r) + updatercd(:enable, r) + end end - def stop_on_runlevel!(runlevel) - AIDS.validate_runlevel(runlevel) - return true if stopped_on_runlevel?(runlevel) - updatercd(:disable, runlevel) + def stop_on_runlevels!(runlevels) + [runlevels].flatten.each do |r| + AIDS.validate_runlevel(r) + next if stopped_on_runlevel?(r) + updatercd(:disable, r) + end end def set_default_runlevels! @@ -75,13 +95,13 @@ module AIDS def updatercd(action, runlevel=nil) unless [:enable, :disable, :remove, :defaults].include?(action) - raise Exception.new("Invalid action for updatercd: #{action}.") + raise AIDS::Infection.new("Invalid action for updatercd: #{action}.") end AIDS.validate_runlevel(runlevel) if runlevel # update-rc.d will baulk at being told to do anything with # these runlevels. - if ['0', '1', '6'].include?(runlevel.to_s) - raise Exception.new("Unable to comply: update-rc.d is balls.") + if [:'0',:'1',:'6'].include?(runlevel) + raise AIDS::Infection.new("Unable to comply: update-rc.d is balls.") end pid = Process.fork do $stdout.close @@ -95,11 +115,14 @@ module AIDS end Process.wait(pid) if (rc = $?.exitstatus) != 0 - raise Exception.new("update-rc.d returned #{rc}") + raise AIDS::Infection.new("update-rc.d returned #{rc}") end end end + class Infection < Exception + end + def self.get_all_services Dir.glob("/etc/init.d/*").map do |f| next unless File.executable?(f) @@ -107,9 +130,11 @@ module AIDS end.compact end + private + def self.validate_runlevel(runlevel) - unless ['0', '1', '2', '3', '4', '5', '6', 'S'].include?(runlevel.to_s) - raise Exception.new("Invalid runlevel: #{runlevel}.") + unless RUNLEVEL_ALL.include?(runlevel) + raise AIDS::Infection.new("Invalid runlevel: #{runlevel}.") end end end