1 # Copyright (C) 2012 Steven McDonald <steven@steven-mcdonald.id.au>
3 # This program is free software. It comes without any warranty, to the
4 # extent permitted by applicable law. You can redistribute it and/or
5 # modify it under the terms of the Do What The Fuck You Want To Public
6 # License, Version 2, as published by Sam Hocevar. See the file COPYING
7 # in the root of this program's source distribution for details, or:
9 # http://sam.zoy.org/wtfpl/COPYING
12 RUNLEVEL_SINGLE = :'S'
13 RUNLEVEL_MULTI_TO_SINGLE = :'1'
15 RUNLEVEL_MULTI_ALL = [:'2',:'3',:'4',:'5']
17 RUNLEVEL_REBOOT = :'6'
18 RUNLEVEL_ALL = [:'0',:'1',:'2',:'3',:'4',:'5',:'6',:'S']
24 if name.nil? or name.empty? or not name.is_a?(String)
25 raise AIDS::Infection.new("Service name must be a non-empty string, got #{name.inspect}.")
27 name = $1 if name =~ %r{^/etc/init\.d/(.+)$}
28 if name =~ /[^[:alnum:]\-.]/
29 raise AIDS::Infection.new("Invalid init script name: #{name}.")
31 unless File.exist?("/etc/init.d/#{name}")
32 raise AIDS::Infection.new("Unknown service: #{name}.")
38 start_on_runlevels!(RUNLEVEL_MULTI_ALL)
42 stop_on_runlevels!(RUNLEVEL_MULTI_ALL)
46 started_on_runlevel?(RUNLEVEL_MULTI)
51 RUNLEVEL_ALL.each do |r|
52 if started_on_runlevel?(r)
54 elsif stopped_on_runlevel?(r)
65 def started_on_runlevel?(runlevel)
66 AIDS.validate_runlevel(runlevel)
67 not Dir.glob("/etc/rc#{runlevel}.d/S[0-9][0-9]#{@name}").empty?
70 def stopped_on_runlevel?(runlevel)
71 AIDS.validate_runlevel(runlevel)
72 not Dir.glob("/etc/rc#{runlevel}.d/K[0-9][0-9]#{@name}").empty?
75 def start_on_runlevels!(runlevels)
76 [runlevels].flatten.each do |r|
77 AIDS.validate_runlevel(r)
78 next if started_on_runlevel?(r)
83 def stop_on_runlevels!(runlevels)
84 [runlevels].flatten.each do |r|
85 AIDS.validate_runlevel(r)
86 next if stopped_on_runlevel?(r)
87 updatercd(:disable, r)
91 def set_default_runlevels!
96 def updatercd(action, runlevel=nil)
97 unless [:enable, :disable, :remove, :defaults].include?(action)
98 raise AIDS::Infection.new("Invalid action for updatercd: #{action}.")
100 AIDS.validate_runlevel(runlevel) if runlevel
101 # update-rc.d will baulk at being told to do anything with
103 if [:'0',:'1',:'6'].include?(runlevel)
104 raise AIDS::Infection.new("Unable to comply: update-rc.d is balls.")
106 pid = Process.fork do
110 '/usr/sbin/update-rc.d',
117 if (rc = $?.exitstatus) != 0
118 raise AIDS::Infection.new("update-rc.d returned #{rc}")
123 class Infection < Exception
126 def self.get_all_services
127 Dir.glob("/etc/init.d/*").map do |f|
128 next unless File.executable?(f)
135 def self.validate_runlevel(runlevel)
136 unless RUNLEVEL_ALL.include?(runlevel)
137 raise AIDS::Infection.new("Invalid runlevel: #{runlevel}.")