godfat-rubycas-server 0.8.0.20090918

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. data/CHANGELOG.txt +1 -0
  2. data/History.txt +273 -0
  3. data/LICENSE.txt +504 -0
  4. data/Manifest.txt +83 -0
  5. data/PostInstall.txt +3 -0
  6. data/README.rdoc +26 -0
  7. data/Rakefile +115 -0
  8. data/bin/rubycas-server +13 -0
  9. data/bin/rubycas-server-ctl +9 -0
  10. data/config.example.yml +555 -0
  11. data/config.ru +38 -0
  12. data/config/hoe.rb +78 -0
  13. data/config/requirements.rb +15 -0
  14. data/custom_views.example.rb +11 -0
  15. data/lib/casserver.rb +58 -0
  16. data/lib/casserver/authenticators/active_directory_ldap.rb +11 -0
  17. data/lib/casserver/authenticators/authlogic_crypto_providers/aes256.rb +43 -0
  18. data/lib/casserver/authenticators/authlogic_crypto_providers/bcrypt.rb +92 -0
  19. data/lib/casserver/authenticators/authlogic_crypto_providers/md5.rb +34 -0
  20. data/lib/casserver/authenticators/authlogic_crypto_providers/sha1.rb +35 -0
  21. data/lib/casserver/authenticators/authlogic_crypto_providers/sha512.rb +50 -0
  22. data/lib/casserver/authenticators/base.rb +48 -0
  23. data/lib/casserver/authenticators/client_certificate.rb +46 -0
  24. data/lib/casserver/authenticators/google.rb +54 -0
  25. data/lib/casserver/authenticators/ldap.rb +147 -0
  26. data/lib/casserver/authenticators/ntlm.rb +88 -0
  27. data/lib/casserver/authenticators/open_id.rb +22 -0
  28. data/lib/casserver/authenticators/sql.rb +119 -0
  29. data/lib/casserver/authenticators/sql_authlogic.rb +92 -0
  30. data/lib/casserver/authenticators/sql_encrypted.rb +92 -0
  31. data/lib/casserver/authenticators/sql_md5.rb +19 -0
  32. data/lib/casserver/authenticators/sql_rest_auth.rb +71 -0
  33. data/lib/casserver/authenticators/test.rb +19 -0
  34. data/lib/casserver/cas.rb +322 -0
  35. data/lib/casserver/conf.rb +75 -0
  36. data/lib/casserver/controllers.rb +463 -0
  37. data/lib/casserver/load_picnic.rb +19 -0
  38. data/lib/casserver/localization.rb +82 -0
  39. data/lib/casserver/models.rb +265 -0
  40. data/lib/casserver/postambles.rb +174 -0
  41. data/lib/casserver/utils.rb +30 -0
  42. data/lib/casserver/version.rb +9 -0
  43. data/lib/casserver/views.rb +249 -0
  44. data/lib/rubycas-server.rb +1 -0
  45. data/lib/rubycas-server/version.rb +1 -0
  46. data/po/de_DE/rubycas-server.po +119 -0
  47. data/po/es_ES/rubycas-server.po +115 -0
  48. data/po/fr_FR/rubycas-server.po +116 -0
  49. data/po/ja_JP/rubycas-server.po +118 -0
  50. data/po/pl_PL/rubycas-server.po +115 -0
  51. data/po/pt_BR/rubycas-server.po +115 -0
  52. data/po/ru_RU/rubycas-server.po +110 -0
  53. data/po/rubycas-server.pot +104 -0
  54. data/public/themes/cas.css +121 -0
  55. data/public/themes/notice.png +0 -0
  56. data/public/themes/ok.png +0 -0
  57. data/public/themes/simple/bg.png +0 -0
  58. data/public/themes/simple/login_box_bg.png +0 -0
  59. data/public/themes/simple/logo.png +0 -0
  60. data/public/themes/simple/theme.css +28 -0
  61. data/public/themes/urbacon/bg.png +0 -0
  62. data/public/themes/urbacon/login_box_bg.png +0 -0
  63. data/public/themes/urbacon/logo.png +0 -0
  64. data/public/themes/urbacon/theme.css +33 -0
  65. data/public/themes/warning.png +0 -0
  66. data/resources/init.d.sh +58 -0
  67. data/script/console +10 -0
  68. data/script/destroy +14 -0
  69. data/script/generate +14 -0
  70. data/script/txt2html +82 -0
  71. data/setup.rb +1585 -0
  72. data/tasks/deployment.rake +34 -0
  73. data/tasks/environment.rake +7 -0
  74. data/tasks/localization.rake +11 -0
  75. data/tasks/website.rake +17 -0
  76. data/vendor/isaac_0.9.1/LICENSE +26 -0
  77. data/vendor/isaac_0.9.1/README +78 -0
  78. data/vendor/isaac_0.9.1/TODO +3 -0
  79. data/vendor/isaac_0.9.1/VERSIONS +3 -0
  80. data/vendor/isaac_0.9.1/crypt/ISAAC.rb +171 -0
  81. data/vendor/isaac_0.9.1/isaac.gemspec +39 -0
  82. data/vendor/isaac_0.9.1/setup.rb +596 -0
  83. data/vendor/isaac_0.9.1/test/TC_ISAAC.rb +76 -0
  84. metadata +200 -0
@@ -0,0 +1,19 @@
1
+ if File.exists?(picnic = File.expand_path(File.dirname(File.expand_path(__FILE__))+'/../../vendor/picnic/lib'))
2
+ puts "Loading picnic from #{picnic.inspect}..."
3
+ $: << picnic
4
+ elsif File.exists?(picnic = File.expand_path(File.dirname(File.expand_path(__FILE__))+'/../../../picnic/lib'))
5
+ puts "Loading picnic from #{picnic.inspect}..."
6
+ $: << picnic
7
+ else
8
+ puts "Loading picnic from rubygems..."
9
+ require 'rubygems'
10
+
11
+ begin
12
+ # Try to load dev version of picnic if available (for example 'zuk-picnic' from Github)
13
+ gem /^.*?-picnic$/
14
+ rescue Gem::LoadError
15
+ gem 'picnic'
16
+ end
17
+ end
18
+
19
+
@@ -0,0 +1,82 @@
1
+ require "gettext"
2
+ require "gettext/cgi"
3
+
4
+ module CASServer
5
+ include GetText
6
+ bindtextdomain("rubycas-server", :path => File.join(File.dirname(File.expand_path(__FILE__)), "../../locale"))
7
+
8
+ def service(*a)
9
+ GetText.locale = determine_locale
10
+ #puts GetText.locale.inspect
11
+ super(*a)
12
+ end
13
+
14
+ def determine_locale
15
+
16
+ source = nil
17
+ lang = case
18
+ when !input['lang'].blank?
19
+ source = "'lang' request variable"
20
+ cookies['lang'] = input['lang']
21
+ input['lang']
22
+ when !cookies['lang'].blank?
23
+ source = "'lang' cookie"
24
+ cookies['lang']
25
+ when !@env['HTTP_ACCEPT_LANGUAGE'].blank?
26
+ source = "'HTTP_ACCEPT_LANGUAGE' header"
27
+ lang = @env['HTTP_ACCEPT_LANGUAGE']
28
+ when !@env['HTTP_USER_AGENT'].blank? && @env['HTTP_USER_AGENT'] =~ /[^a-z]([a-z]{2}(-[a-z]{2})?)[^a-z]/i
29
+ source = "'HTTP_USER_AGENT' header"
30
+ $~[1]
31
+ when !$CONF['default_locale'].blank?
32
+ source = "'default_locale' config option"
33
+ $CONF[:default_locale]
34
+ else
35
+ source = "default"
36
+ "en"
37
+ end
38
+
39
+ $LOG.debug "Detected locale is #{lang.inspect} (from #{source})"
40
+
41
+ lang.gsub!('_','-')
42
+
43
+ # TODO: Need to confirm that this method of splitting the accepted
44
+ # language string is correct.
45
+ if lang =~ /[,;\|]/
46
+ langs = lang.split(/[,;\|]/)
47
+ else
48
+ langs = [lang]
49
+ end
50
+
51
+ # TODO: This method of selecting the desired language might not be
52
+ # standards-compliant. For example, http://www.w3.org/TR/ltli/
53
+ # suggests that de-de and de-*-DE might be acceptable identifiers
54
+ # for selecting various wildcards. The algorithm below does not
55
+ # currently support anything like this.
56
+
57
+ available = available_locales
58
+
59
+ # Try to pick a locale exactly matching the desired identifier, otherwise
60
+ # fall back to locale without region (i.e. given "en-US; de-DE", we would
61
+ # first look for "en-US", then "en", then "de-DE", then "de").
62
+
63
+ chosen_lang = nil
64
+ langs.each do |l|
65
+ a = available.find{|a| a == l || a =~ Regexp.new("#{l}-\w*")}
66
+ if a
67
+ chosen_lang = a
68
+ break
69
+ end
70
+ end
71
+
72
+ chosen_lang = "en" if chosen_lang.blank?
73
+
74
+ $LOG.debug "Chosen locale is #{chosen_lang.inspect}"
75
+
76
+ return chosen_lang
77
+ end
78
+
79
+ def available_locales
80
+ (Dir.glob(File.join(File.dirname(File.expand_path(__FILE__)), "../../locale/[a-z]*")).map{|path| File.basename(path)} << "en").uniq.collect{|l| l.gsub('_','-')}
81
+ end
82
+ end
@@ -0,0 +1,265 @@
1
+ require 'camping/ar'
2
+
3
+ module CASServer::Models
4
+
5
+ module Consumable
6
+ def consume!
7
+ self.consumed = Time.now
8
+ self.save!
9
+ end
10
+
11
+ def self.included(mod)
12
+ mod.extend(ClassMethods)
13
+ end
14
+
15
+ module ClassMethods
16
+ def cleanup(max_lifetime, max_unconsumed_lifetime)
17
+ transaction do
18
+ conditions = ["created_on < ? OR (consumed IS NULL AND created_on < ?)",
19
+ Time.now - max_lifetime,
20
+ Time.now - max_unconsumed_lifetime]
21
+ expired_tickets_count = count(:conditions => conditions)
22
+
23
+ $LOG.debug("Destroying #{expired_tickets_count} expired #{self.name.demodulize}"+
24
+ "#{'s' if expired_tickets_count > 1}.") if expired_tickets_count > 0
25
+
26
+ destroy_all(conditions)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ class Ticket < Base
33
+ def to_s
34
+ ticket
35
+ end
36
+
37
+ def self.cleanup(max_lifetime)
38
+ transaction do
39
+ conditions = ["created_on < ?", Time.now - max_lifetime]
40
+ expired_tickets_count = count(:conditions => conditions)
41
+
42
+ $LOG.debug("Destroying #{expired_tickets_count} expired #{self.name.demodulize}"+
43
+ "#{'s' if expired_tickets_count > 1}.") if expired_tickets_count > 0
44
+
45
+ destroy_all(conditions)
46
+ end
47
+ end
48
+ end
49
+
50
+ class LoginTicket < Ticket
51
+ set_table_name 'casserver_lt'
52
+ include Consumable
53
+ end
54
+
55
+ class ServiceTicket < Ticket
56
+ set_table_name 'casserver_st'
57
+ include Consumable
58
+
59
+ belongs_to :granted_by_tgt,
60
+ :class_name => 'CASServer::Models::TicketGrantingTicket',
61
+ :foreign_key => :granted_by_tgt_id
62
+ has_one :proxy_granting_ticket,
63
+ :foreign_key => :created_by_st_id
64
+
65
+ def matches_service?(service)
66
+ CASServer::CAS.clean_service_url(self.service) ==
67
+ CASServer::CAS.clean_service_url(service)
68
+ end
69
+ end
70
+
71
+ class ProxyTicket < ServiceTicket
72
+ belongs_to :granted_by_pgt,
73
+ :class_name => 'CASServer::Models::ProxyGrantingTicket',
74
+ :foreign_key => :granted_by_pgt_id
75
+ end
76
+
77
+ class TicketGrantingTicket < Ticket
78
+ set_table_name 'casserver_tgt'
79
+
80
+ serialize :extra_attributes
81
+
82
+ has_many :granted_service_tickets,
83
+ :class_name => 'CASServer::Models::ServiceTicket',
84
+ :foreign_key => :granted_by_tgt_id
85
+ end
86
+
87
+ class ProxyGrantingTicket < Ticket
88
+ set_table_name 'casserver_pgt'
89
+ belongs_to :service_ticket
90
+ has_many :granted_proxy_tickets,
91
+ :class_name => 'CASServer::Models::ProxyTicket',
92
+ :foreign_key => :granted_by_pgt_id
93
+ end
94
+
95
+ class Error
96
+ attr_reader :code, :message
97
+
98
+ def initialize(code, message)
99
+ @code = code
100
+ @message = message
101
+ end
102
+
103
+ def to_s
104
+ message
105
+ end
106
+ end
107
+
108
+ class CreateCASServer < V 0.1
109
+ def self.up
110
+ if ActiveRecord::Base.connection.table_alias_length > 30
111
+ $LOG.info("Creating database with long table names...")
112
+
113
+ create_table :casserver_login_tickets, :force => true do |t|
114
+ t.column :ticket, :string, :null => false
115
+ t.column :created_on, :timestamp, :null => false
116
+ t.column :consumed, :datetime, :null => true
117
+ t.column :client_hostname, :string, :null => false
118
+ end
119
+
120
+ create_table :casserver_service_tickets, :force => true do |t|
121
+ t.column :ticket, :string, :null => false
122
+ t.column :service, :string, :null => false
123
+ t.column :created_on, :timestamp, :null => false
124
+ t.column :consumed, :datetime, :null => true
125
+ t.column :client_hostname, :string, :null => false
126
+ t.column :username, :string, :null => false
127
+ t.column :type, :string, :null => false
128
+ t.column :proxy_granting_ticket_id, :integer, :null => true
129
+ end
130
+
131
+ create_table :casserver_ticket_granting_tickets, :force => true do |t|
132
+ t.column :ticket, :string, :null => false
133
+ t.column :created_on, :timestamp, :null => false
134
+ t.column :client_hostname, :string, :null => false
135
+ t.column :username, :string, :null => false
136
+ end
137
+
138
+ create_table :casserver_proxy_granting_tickets, :force => true do |t|
139
+ t.column :ticket, :string, :null => false
140
+ t.column :created_on, :timestamp, :null => false
141
+ t.column :client_hostname, :string, :null => false
142
+ t.column :iou, :string, :null => false
143
+ t.column :service_ticket_id, :integer, :null => false
144
+ end
145
+ end
146
+ end
147
+
148
+ def self.down
149
+ if ActiveRecord::Base.connection.table_alias_length > 30
150
+ drop_table :casserver_proxy_granting_tickets
151
+ drop_table :casserver_ticket_granting_tickets
152
+ drop_table :casserver_service_tickets
153
+ drop_table :casserver_login_tickets
154
+ end
155
+ end
156
+ end
157
+
158
+ # Oracle table names cannot exceed 30 chars...
159
+ # See http://code.google.com/p/rubycas-server/issues/detail?id=15
160
+ class ShortenTableNames < V 0.5
161
+ def self.up
162
+ if ActiveRecord::Base.connection.table_alias_length > 30
163
+ $LOG.info("Shortening table names")
164
+ rename_table :casserver_login_tickets, :casserver_lt
165
+ rename_table :casserver_service_tickets, :casserver_st
166
+ rename_table :casserver_ticket_granting_tickets, :casserver_tgt
167
+ rename_table :casserver_proxy_granting_tickets, :casserver_pgt
168
+ else
169
+ create_table :casserver_lt, :force => true do |t|
170
+ t.column :ticket, :string, :null => false
171
+ t.column :created_on, :timestamp, :null => false
172
+ t.column :consumed, :datetime, :null => true
173
+ t.column :client_hostname, :string, :null => false
174
+ end
175
+
176
+ create_table :casserver_st, :force => true do |t|
177
+ t.column :ticket, :string, :null => false
178
+ t.column :service, :string, :null => false
179
+ t.column :created_on, :timestamp, :null => false
180
+ t.column :consumed, :datetime, :null => true
181
+ t.column :client_hostname, :string, :null => false
182
+ t.column :username, :string, :null => false
183
+ t.column :type, :string, :null => false
184
+ t.column :proxy_granting_ticket_id, :integer, :null => true
185
+ end
186
+
187
+ create_table :casserver_tgt, :force => true do |t|
188
+ t.column :ticket, :string, :null => false
189
+ t.column :created_on, :timestamp, :null => false
190
+ t.column :client_hostname, :string, :null => false
191
+ t.column :username, :string, :null => false
192
+ end
193
+
194
+ create_table :casserver_pgt, :force => true do |t|
195
+ t.column :ticket, :string, :null => false
196
+ t.column :created_on, :timestamp, :null => false
197
+ t.column :client_hostname, :string, :null => false
198
+ t.column :iou, :string, :null => false
199
+ t.column :service_ticket_id, :integer, :null => false
200
+ end
201
+ end
202
+ end
203
+
204
+ def self.down
205
+ if ActiveRecord::Base.connection.table_alias_length > 30
206
+ rename_table :casserver_lt, :cassserver_login_tickets
207
+ rename_table :casserver_st, :casserver_service_tickets
208
+ rename_table :casserver_tgt, :casserver_ticket_granting_tickets
209
+ rename_table :casserver_pgt, :casserver_proxy_granting_tickets
210
+ else
211
+ drop_table :casserver_pgt
212
+ drop_table :casserver_tgt
213
+ drop_table :casserver_st
214
+ drop_table :casserver_lt
215
+ end
216
+ end
217
+ end
218
+
219
+ class AddTgtToSt < V 0.7
220
+ def self.up
221
+ add_column :casserver_st, :tgt_id, :integer, :null => true
222
+ end
223
+
224
+ def self.down
225
+ remove_column :casserver_st, :tgt_id, :integer
226
+ end
227
+ end
228
+
229
+ class ChangeServiceToText < V 0.71
230
+ def self.up
231
+ # using change_column to change the column type from :string to :text
232
+ # doesn't seem to work, at least under MySQL, so we drop and re-create
233
+ # the column instead
234
+ remove_column :casserver_st, :service
235
+ say "WARNING: All existing service tickets are being deleted."
236
+ add_column :casserver_st, :service, :text
237
+ end
238
+
239
+ def self.down
240
+ change_column :casserver_st, :service, :string
241
+ end
242
+ end
243
+
244
+ class AddExtraAttributes < V 0.72
245
+ def self.up
246
+ add_column :casserver_tgt, :extra_attributes, :text
247
+ end
248
+
249
+ def self.down
250
+ remove_column :casserver_tgt, :extra_attributes
251
+ end
252
+ end
253
+
254
+ class RenamePgtForeignKeys < V 0.80
255
+ def self.up
256
+ rename_column :casserver_st, :proxy_granting_ticket_id, :granted_by_pgt_id
257
+ rename_column :casserver_st, :tgt_id, :granted_by_tgt_id
258
+ end
259
+
260
+ def self.down
261
+ rename_column :casserver_st, :granted_by_pgt_id, :proxy_granting_ticket_id
262
+ rename_column :casserver_st, :granted_by_tgt_id, :tgt_id
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,174 @@
1
+ module CASServer
2
+ module Postambles
3
+
4
+ def webrick
5
+ require 'webrick/httpserver'
6
+ require 'webrick/https'
7
+ require 'camping/webrick'
8
+
9
+ # TODO: verify the certificate's validity
10
+ # example of how to do this is here: http://pablotron.org/download/ruri-20050331.rb
11
+
12
+ cert_path = $CONF.ssl_cert
13
+ key_path = $CONF.ssl_key || $CONF.ssl_cert
14
+ # look for the key in the ssl_cert if no ssl_key is specified
15
+
16
+ webrick_options = {:BindAddress => "0.0.0.0", :Port => $CONF.port}
17
+
18
+ unless cert_path.nil? && key_path.nil?
19
+ raise "'#{cert_path}' is not a valid ssl certificate. Your 'ssl_cert' configuration" +
20
+ " setting must be a path to a valid ssl certificate file." unless
21
+ File.exists? cert_path
22
+
23
+ raise "'#{key_path}' is not a valid ssl private key. Your 'ssl_key' configuration" +
24
+ " setting must be a path to a valid ssl private key file." unless
25
+ File.exists? key_path
26
+
27
+ cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
28
+ key = OpenSSL::PKey::RSA.new(File.read(key_path))
29
+
30
+ webrick_options[:SSLEnable] = true
31
+ webrick_options[:SSLVerifyClient] = ::OpenSSL::SSL::VERIFY_NONE
32
+ webrick_options[:SSLCertificate] = cert
33
+ webrick_options[:SSLPrivateKey] = key
34
+ end
35
+
36
+ begin
37
+ s = WEBrick::HTTPServer.new(webrick_options)
38
+ rescue Errno::EACCES
39
+ puts "\nThe server could not launch. Are you running on a privileged port? (e.g. port 443) If so, you must run the server as root."
40
+ exit 2
41
+ end
42
+
43
+ CASServer.create
44
+ s.mount "#{$CONF.uri_path}", WEBrick::CampingHandler, CASServer
45
+
46
+ puts "\n** CASServer is running at http#{webrick_options[:SSLEnable] ? 's' : ''}://#{Socket.gethostname}:#{$CONF.port}#{$CONF.uri_path} and logging to '#{$CONF.log[:file]}'\n\n"
47
+
48
+ # This lets Ctrl+C shut down your server
49
+ trap(:INT) do
50
+ s.shutdown
51
+ end
52
+ trap(:TERM) do
53
+ s.shutdown
54
+ end
55
+
56
+ if $DAEMONIZE
57
+ WEBrick::Daemon.start do
58
+ write_pid_file if $PID_FILE
59
+ s.start
60
+ clear_pid_file
61
+ end
62
+ else
63
+ s.start
64
+ end
65
+ end
66
+
67
+
68
+
69
+ def mongrel
70
+ require 'rubygems'
71
+ require 'mongrel/camping'
72
+
73
+ if $DAEMONIZE
74
+ # check if log and pid are writable before daemonizing, otherwise we won't be able to notify
75
+ # the user if we run into trouble later (since once daemonized, we can't write to stdout/stderr)
76
+ check_pid_writable if $PID_FILE
77
+ check_log_writable
78
+ end
79
+
80
+ CASServer.create
81
+
82
+ puts "\n** CASServer is starting. Look in '#{$CONF.log[:file]}' for further notices."
83
+
84
+ settings = {:host => "0.0.0.0", :log_file => $CONF.log[:file], :cwd => $CASSERVER_HOME}
85
+
86
+ # need to close all IOs before daemonizing
87
+ $LOG.close if $DAEMONIZE
88
+
89
+ begin
90
+ config = Mongrel::Configurator.new settings do
91
+ daemonize :log_file => $CONF.log[:file], :cwd => $CASSERVER_HOME if $DAEMONIZE
92
+
93
+ listener :port => $CONF.port do
94
+ uri $CONF.uri_path, :handler => Mongrel::Camping::CampingHandler.new(CASServer)
95
+ setup_signals
96
+ end
97
+ end
98
+ rescue Errno::EADDRINUSE
99
+ exit 1
100
+ end
101
+
102
+ config.run
103
+
104
+ CASServer.init_logger
105
+ CASServer.init_db_logger
106
+
107
+ if $DAEMONIZE && $PID_FILE
108
+ write_pid_file
109
+ unless File.exists? $PID_FILE
110
+ $LOG.error "CASServer could not start because pid file '#{$PID_FILE}' could not be created."
111
+ exit 1
112
+ end
113
+ end
114
+
115
+ puts "\n** CASServer is running at http://localhost:#{$CONF.port}#{$CONF.uri_path} and logging to '#{$CONF.log[:file]}'"
116
+ config.join
117
+
118
+ clear_pid_file
119
+
120
+ puts "\n** CASServer is stopped (#{Time.now})"
121
+ end
122
+
123
+
124
+ def fastcgi
125
+ require 'camping/fastcgi'
126
+ Dir.chdir('/srv/www/camping/casserver/')
127
+
128
+ CASServer.create
129
+ Camping::FastCGI.start(CASServer)
130
+ end
131
+
132
+
133
+ def cgi
134
+ CASServer.create
135
+ puts CASServer.run
136
+ end
137
+
138
+ private
139
+ def check_log_writable
140
+ log_file = $CONF.log['file']
141
+ begin
142
+ f = open(log_file, 'w')
143
+ rescue
144
+ $stderr.puts "Couldn't write to log file at '#{log_file}' (#{$!})."
145
+ exit 1
146
+ end
147
+ f.close
148
+ end
149
+
150
+ def check_pid_writable
151
+ $LOG.debug "Checking if pid file '#{$PID_FILE}' is writable"
152
+ begin
153
+ f = open($PID_FILE, 'w')
154
+ rescue
155
+ $stderr.puts "Couldn't write to log at '#{$PID_FILE}' (#{$!})."
156
+ exit 1
157
+ end
158
+ f.close
159
+ end
160
+
161
+ def write_pid_file
162
+ $LOG.debug "Writing pid '#{Process.pid}' to pid file '#{$PID_FILE}'"
163
+ open($PID_FILE, "w") { |file| file.write(Process.pid) }
164
+ end
165
+
166
+ def clear_pid_file
167
+ if $PID_FILE && File.exists?($PID_FILE)
168
+ $LOG.debug "Clearing pid file '#{$PID_FILE}'"
169
+ File.unlink $PID_FILE
170
+ end
171
+ end
172
+
173
+ end
174
+ end