daemon-kit 0.1.7 → 0.1.7.4

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 (80) hide show
  1. data/Configuration.txt +58 -0
  2. data/History.txt +24 -0
  3. data/Manifest.txt +50 -2
  4. data/PostInstall.txt +1 -1
  5. data/README.rdoc +7 -9
  6. data/Rakefile +2 -4
  7. data/TODO.txt +6 -5
  8. data/app_generators/daemon_kit/daemon_kit_generator.rb +5 -0
  9. data/app_generators/daemon_kit/templates/Rakefile +3 -1
  10. data/app_generators/daemon_kit/templates/bin/daemon.erb +1 -1
  11. data/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
  12. data/app_generators/daemon_kit/templates/config/boot.rb +2 -2
  13. data/app_generators/daemon_kit/templates/script/console +3 -0
  14. data/app_generators/daemon_kit/templates/script/destroy +14 -0
  15. data/app_generators/daemon_kit/templates/script/generate +14 -0
  16. data/daemon_generators/amqp/templates/config/amqp.yml +5 -5
  17. data/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +4 -23
  18. data/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
  19. data/daemon_generators/deploy_capistrano/templates/config/deploy.rb +3 -1
  20. data/lib/daemon_kit.rb +33 -5
  21. data/lib/daemon_kit/amqp.rb +2 -1
  22. data/lib/daemon_kit/application.rb +136 -11
  23. data/lib/daemon_kit/arguments.rb +151 -0
  24. data/lib/daemon_kit/commands/console.rb +38 -0
  25. data/lib/daemon_kit/config.rb +1 -0
  26. data/lib/daemon_kit/console_daemon.rb +2 -0
  27. data/lib/daemon_kit/core_ext.rb +1 -0
  28. data/lib/daemon_kit/core_ext/string.rb +22 -0
  29. data/lib/daemon_kit/deployment/capistrano.rb +6 -9
  30. data/lib/daemon_kit/error_handlers/mail.rb +52 -15
  31. data/lib/daemon_kit/initializer.rb +95 -41
  32. data/lib/daemon_kit/pid_file.rb +61 -0
  33. data/lib/daemon_kit/tasks/environment.rake +5 -4
  34. data/lib/daemon_kit/tasks/framework.rake +15 -1
  35. data/lib/daemon_kit/tasks/god.rake +62 -0
  36. data/lib/daemon_kit/tasks/log.rake +8 -0
  37. data/lib/daemon_kit/tasks/monit.rake +29 -0
  38. data/spec/argument_spec.rb +51 -0
  39. data/spec/config_spec.rb +77 -0
  40. data/spec/daemon_kit_spec.rb +2 -2
  41. data/spec/error_handlers_spec.rb +23 -0
  42. data/spec/fixtures/env.yml +15 -0
  43. data/spec/fixtures/noenv.yml +4 -0
  44. data/spec/initializer_spec.rb +4 -3
  45. data/spec/spec_helper.rb +8 -11
  46. data/templates/god/god.erb +69 -0
  47. data/templates/monit/monit.erb +14 -0
  48. data/test/test_daemon-kit_generator.rb +6 -1
  49. data/test/test_deploy_capistrano_generator.rb +1 -2
  50. data/vendor/tmail-1.2.3/tmail.rb +5 -0
  51. data/vendor/tmail-1.2.3/tmail/address.rb +426 -0
  52. data/vendor/tmail-1.2.3/tmail/attachments.rb +46 -0
  53. data/vendor/tmail-1.2.3/tmail/base64.rb +46 -0
  54. data/vendor/tmail-1.2.3/tmail/compat.rb +41 -0
  55. data/vendor/tmail-1.2.3/tmail/config.rb +67 -0
  56. data/vendor/tmail-1.2.3/tmail/core_extensions.rb +63 -0
  57. data/vendor/tmail-1.2.3/tmail/encode.rb +581 -0
  58. data/vendor/tmail-1.2.3/tmail/header.rb +960 -0
  59. data/vendor/tmail-1.2.3/tmail/index.rb +9 -0
  60. data/vendor/tmail-1.2.3/tmail/interface.rb +1130 -0
  61. data/vendor/tmail-1.2.3/tmail/loader.rb +3 -0
  62. data/vendor/tmail-1.2.3/tmail/mail.rb +578 -0
  63. data/vendor/tmail-1.2.3/tmail/mailbox.rb +495 -0
  64. data/vendor/tmail-1.2.3/tmail/main.rb +6 -0
  65. data/vendor/tmail-1.2.3/tmail/mbox.rb +3 -0
  66. data/vendor/tmail-1.2.3/tmail/net.rb +248 -0
  67. data/vendor/tmail-1.2.3/tmail/obsolete.rb +132 -0
  68. data/vendor/tmail-1.2.3/tmail/parser.rb +1476 -0
  69. data/vendor/tmail-1.2.3/tmail/port.rb +379 -0
  70. data/vendor/tmail-1.2.3/tmail/quoting.rb +118 -0
  71. data/vendor/tmail-1.2.3/tmail/require_arch.rb +58 -0
  72. data/vendor/tmail-1.2.3/tmail/scanner.rb +49 -0
  73. data/vendor/tmail-1.2.3/tmail/scanner_r.rb +261 -0
  74. data/vendor/tmail-1.2.3/tmail/stringio.rb +280 -0
  75. data/vendor/tmail-1.2.3/tmail/utils.rb +337 -0
  76. data/vendor/tmail-1.2.3/tmail/version.rb +39 -0
  77. data/vendor/tmail.rb +13 -0
  78. metadata +57 -18
  79. data/daemon_generators/deploy_capistrano/USAGE +0 -5
  80. data/lib/daemon_kit/patches/force_kill_wait.rb +0 -120
@@ -0,0 +1,58 @@
1
+ #:stopdoc:
2
+ require 'rbconfig'
3
+
4
+ # Attempts to require anative extension.
5
+ # Falls back to pure-ruby version, if it fails.
6
+ #
7
+ # This uses Config::CONFIG['arch'] from rbconfig.
8
+
9
+ def require_arch(fname)
10
+ arch = Config::CONFIG['arch']
11
+ begin
12
+ path = File.join("tmail", arch, fname)
13
+ require path
14
+ rescue LoadError => e
15
+ # try pre-built Windows binaries
16
+ if arch =~ /mswin/
17
+ require File.join("tmail", 'mswin32', fname)
18
+ else
19
+ raise e
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ # def require_arch(fname)
26
+ # dext = Config::CONFIG['DLEXT']
27
+ # begin
28
+ # if File.extname(fname) == dext
29
+ # path = fname
30
+ # else
31
+ # path = File.join("tmail","#{fname}.#{dext}")
32
+ # end
33
+ # require path
34
+ # rescue LoadError => e
35
+ # begin
36
+ # arch = Config::CONFIG['arch']
37
+ # path = File.join("tmail", arch, "#{fname}.#{dext}")
38
+ # require path
39
+ # rescue LoadError
40
+ # case path
41
+ # when /i686/
42
+ # path.sub!('i686', 'i586')
43
+ # when /i586/
44
+ # path.sub!('i586', 'i486')
45
+ # when /i486/
46
+ # path.sub!('i486', 'i386')
47
+ # else
48
+ # begin
49
+ # require fname + '.rb'
50
+ # rescue LoadError
51
+ # raise e
52
+ # end
53
+ # end
54
+ # retry
55
+ # end
56
+ # end
57
+ # end
58
+ #:startdoc:
@@ -0,0 +1,49 @@
1
+ =begin rdoc
2
+
3
+ = Scanner for TMail
4
+
5
+ =end
6
+ #--
7
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
29
+ # with permission of Minero Aoki.
30
+ #++
31
+ #:stopdoc:
32
+ #require 'tmail/require_arch'
33
+ require 'tmail/utils'
34
+ require 'tmail/config'
35
+
36
+ module TMail
37
+ # NOTE: It woiuld be nice if these two libs could boith be called "tmailscanner", and
38
+ # the native extension would have precedence. However RubyGems boffs that up b/c
39
+ # it does not gaurantee load_path order.
40
+ begin
41
+ raise LoadError, 'Turned off native extentions by user choice' if ENV['NORUBYEXT']
42
+ require('tmail/tmailscanner') # c extension
43
+ Scanner = TMailScanner
44
+ rescue LoadError
45
+ require 'tmail/scanner_r'
46
+ Scanner = TMailScanner
47
+ end
48
+ end
49
+ #:stopdoc:
@@ -0,0 +1,261 @@
1
+ # scanner_r.rb
2
+ #
3
+ #--
4
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
26
+ # with permission of Minero Aoki.
27
+ #++
28
+ #:stopdoc:
29
+ require 'tmail/config'
30
+
31
+ module TMail
32
+
33
+ class TMailScanner
34
+
35
+ Version = '1.2.3'
36
+ Version.freeze
37
+
38
+ MIME_HEADERS = {
39
+ :CTYPE => true,
40
+ :CENCODING => true,
41
+ :CDISPOSITION => true
42
+ }
43
+
44
+ alnum = 'a-zA-Z0-9'
45
+ atomsyms = %q[ _#!$%&`'*+-{|}~^/=? ].strip
46
+ tokensyms = %q[ _#!$%&`'*+-{|}~^@. ].strip
47
+ atomchars = alnum + Regexp.quote(atomsyms)
48
+ tokenchars = alnum + Regexp.quote(tokensyms)
49
+ iso2022str = '\e(?!\(B)..(?:[^\e]+|\e(?!\(B)..)*\e\(B'
50
+
51
+ eucstr = "(?:[\xa1-\xfe][\xa1-\xfe])+"
52
+ sjisstr = "(?:[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+"
53
+ utf8str = "(?:[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf])+"
54
+
55
+ quoted_with_iso2022 = /\A(?:[^\\\e"]+|#{iso2022str})+/n
56
+ domlit_with_iso2022 = /\A(?:[^\\\e\]]+|#{iso2022str})+/n
57
+ comment_with_iso2022 = /\A(?:[^\\\e()]+|#{iso2022str})+/n
58
+
59
+ quoted_without_iso2022 = /\A[^\\"]+/n
60
+ domlit_without_iso2022 = /\A[^\\\]]+/n
61
+ comment_without_iso2022 = /\A[^\\()]+/n
62
+
63
+ PATTERN_TABLE = {}
64
+ PATTERN_TABLE['EUC'] =
65
+ [
66
+ /\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+/n,
67
+ /\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+/n,
68
+ quoted_with_iso2022,
69
+ domlit_with_iso2022,
70
+ comment_with_iso2022
71
+ ]
72
+ PATTERN_TABLE['SJIS'] =
73
+ [
74
+ /\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+/n,
75
+ /\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+/n,
76
+ quoted_with_iso2022,
77
+ domlit_with_iso2022,
78
+ comment_with_iso2022
79
+ ]
80
+ PATTERN_TABLE['UTF8'] =
81
+ [
82
+ /\A(?:[#{atomchars}]+|#{utf8str})+/n,
83
+ /\A(?:[#{tokenchars}]+|#{utf8str})+/n,
84
+ quoted_without_iso2022,
85
+ domlit_without_iso2022,
86
+ comment_without_iso2022
87
+ ]
88
+ PATTERN_TABLE['NONE'] =
89
+ [
90
+ /\A[#{atomchars}]+/n,
91
+ /\A[#{tokenchars}]+/n,
92
+ quoted_without_iso2022,
93
+ domlit_without_iso2022,
94
+ comment_without_iso2022
95
+ ]
96
+
97
+
98
+ def initialize( str, scantype, comments )
99
+ init_scanner str
100
+ @comments = comments || []
101
+ @debug = false
102
+
103
+ # fix scanner mode
104
+ @received = (scantype == :RECEIVED)
105
+ @is_mime_header = MIME_HEADERS[scantype]
106
+
107
+ atom, token, @quoted_re, @domlit_re, @comment_re = PATTERN_TABLE[TMail.KCODE]
108
+ @word_re = (MIME_HEADERS[scantype] ? token : atom)
109
+ end
110
+
111
+ attr_accessor :debug
112
+
113
+ def scan( &block )
114
+ if @debug
115
+ scan_main do |arr|
116
+ s, v = arr
117
+ printf "%7d %-10s %s\n",
118
+ rest_size(),
119
+ s.respond_to?(:id2name) ? s.id2name : s.inspect,
120
+ v.inspect
121
+ yield arr
122
+ end
123
+ else
124
+ scan_main(&block)
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ RECV_TOKEN = {
131
+ 'from' => :FROM,
132
+ 'by' => :BY,
133
+ 'via' => :VIA,
134
+ 'with' => :WITH,
135
+ 'id' => :ID,
136
+ 'for' => :FOR
137
+ }
138
+
139
+ def scan_main
140
+ until eof?
141
+ if skip(/\A[\n\r\t ]+/n) # LWSP
142
+ break if eof?
143
+ end
144
+
145
+ if s = readstr(@word_re)
146
+ if @is_mime_header
147
+ yield [:TOKEN, s]
148
+ else
149
+ # atom
150
+ if /\A\d+\z/ === s
151
+ yield [:DIGIT, s]
152
+ elsif @received
153
+ yield [RECV_TOKEN[s.downcase] || :ATOM, s]
154
+ else
155
+ yield [:ATOM, s]
156
+ end
157
+ end
158
+
159
+ elsif skip(/\A"/)
160
+ yield [:QUOTED, scan_quoted_word()]
161
+
162
+ elsif skip(/\A\[/)
163
+ yield [:DOMLIT, scan_domain_literal()]
164
+
165
+ elsif skip(/\A\(/)
166
+ @comments.push scan_comment()
167
+
168
+ else
169
+ c = readchar()
170
+ yield [c, c]
171
+ end
172
+ end
173
+
174
+ yield [false, '$']
175
+ end
176
+
177
+ def scan_quoted_word
178
+ scan_qstr(@quoted_re, /\A"/, 'quoted-word')
179
+ end
180
+
181
+ def scan_domain_literal
182
+ '[' + scan_qstr(@domlit_re, /\A\]/, 'domain-literal') + ']'
183
+ end
184
+
185
+ def scan_qstr( pattern, terminal, type )
186
+ result = ''
187
+ until eof?
188
+ if s = readstr(pattern) then result << s
189
+ elsif skip(terminal) then return result
190
+ elsif skip(/\A\\/) then result << readchar()
191
+ else
192
+ raise "TMail FATAL: not match in #{type}"
193
+ end
194
+ end
195
+ scan_error! "found unterminated #{type}"
196
+ end
197
+
198
+ def scan_comment
199
+ result = ''
200
+ nest = 1
201
+ content = @comment_re
202
+
203
+ until eof?
204
+ if s = readstr(content) then result << s
205
+ elsif skip(/\A\)/) then nest -= 1
206
+ return result if nest == 0
207
+ result << ')'
208
+ elsif skip(/\A\(/) then nest += 1
209
+ result << '('
210
+ elsif skip(/\A\\/) then result << readchar()
211
+ else
212
+ raise 'TMail FATAL: not match in comment'
213
+ end
214
+ end
215
+ scan_error! 'found unterminated comment'
216
+ end
217
+
218
+ # string scanner
219
+
220
+ def init_scanner( str )
221
+ @src = str
222
+ end
223
+
224
+ def eof?
225
+ @src.empty?
226
+ end
227
+
228
+ def rest_size
229
+ @src.size
230
+ end
231
+
232
+ def readstr( re )
233
+ if m = re.match(@src)
234
+ @src = m.post_match
235
+ m[0]
236
+ else
237
+ nil
238
+ end
239
+ end
240
+
241
+ def readchar
242
+ readstr(/\A./)
243
+ end
244
+
245
+ def skip( re )
246
+ if m = re.match(@src)
247
+ @src = m.post_match
248
+ true
249
+ else
250
+ false
251
+ end
252
+ end
253
+
254
+ def scan_error!( msg )
255
+ raise SyntaxError, msg
256
+ end
257
+
258
+ end
259
+
260
+ end # module TMail
261
+ #:startdoc:
@@ -0,0 +1,280 @@
1
+ # encoding: utf-8
2
+ =begin rdoc
3
+
4
+ = String handling class
5
+
6
+ =end
7
+ #--
8
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
9
+ #
10
+ # Permission is hereby granted, free of charge, to any person obtaining
11
+ # a copy of this software and associated documentation files (the
12
+ # "Software"), to deal in the Software without restriction, including
13
+ # without limitation the rights to use, copy, modify, merge, publish,
14
+ # distribute, sublicense, and/or sell copies of the Software, and to
15
+ # permit persons to whom the Software is furnished to do so, subject to
16
+ # the following conditions:
17
+ #
18
+ # The above copyright notice and this permission notice shall be
19
+ # included in all copies or substantial portions of the Software.
20
+ #
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ #
29
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
30
+ # with permission of Minero Aoki.
31
+ #++
32
+
33
+ class StringInput#:nodoc:
34
+
35
+ include Enumerable
36
+
37
+ class << self
38
+
39
+ def new( str )
40
+ if block_given?
41
+ begin
42
+ f = super
43
+ yield f
44
+ ensure
45
+ f.close if f
46
+ end
47
+ else
48
+ super
49
+ end
50
+ end
51
+
52
+ alias open new
53
+
54
+ end
55
+
56
+ def initialize( str )
57
+ @src = str
58
+ @pos = 0
59
+ @closed = false
60
+ @lineno = 0
61
+ end
62
+
63
+ attr_reader :lineno
64
+
65
+ def string
66
+ @src
67
+ end
68
+
69
+ def inspect
70
+ "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@src[0,30].inspect}>"
71
+ end
72
+
73
+ def close
74
+ stream_check!
75
+ @pos = nil
76
+ @closed = true
77
+ end
78
+
79
+ def closed?
80
+ @closed
81
+ end
82
+
83
+ def pos
84
+ stream_check!
85
+ [@pos, @src.size].min
86
+ end
87
+
88
+ alias tell pos
89
+
90
+ def seek( offset, whence = IO::SEEK_SET )
91
+ stream_check!
92
+ case whence
93
+ when IO::SEEK_SET
94
+ @pos = offset
95
+ when IO::SEEK_CUR
96
+ @pos += offset
97
+ when IO::SEEK_END
98
+ @pos = @src.size - offset
99
+ else
100
+ raise ArgumentError, "unknown seek flag: #{whence}"
101
+ end
102
+ @pos = 0 if @pos < 0
103
+ @pos = [@pos, @src.size + 1].min
104
+ offset
105
+ end
106
+
107
+ def rewind
108
+ stream_check!
109
+ @pos = 0
110
+ end
111
+
112
+ def eof?
113
+ stream_check!
114
+ @pos > @src.size
115
+ end
116
+
117
+ def each( &block )
118
+ stream_check!
119
+ begin
120
+ @src.each(&block)
121
+ ensure
122
+ @pos = 0
123
+ end
124
+ end
125
+
126
+ def gets
127
+ stream_check!
128
+ if idx = @src.index(?\n, @pos)
129
+ idx += 1 # "\n".size
130
+ line = @src[ @pos ... idx ]
131
+ @pos = idx
132
+ @pos += 1 if @pos == @src.size
133
+ else
134
+ line = @src[ @pos .. -1 ]
135
+ @pos = @src.size + 1
136
+ end
137
+ @lineno += 1
138
+
139
+ line
140
+ end
141
+
142
+ def getc
143
+ stream_check!
144
+ ch = @src[@pos]
145
+ @pos += 1
146
+ @pos += 1 if @pos == @src.size
147
+ ch
148
+ end
149
+
150
+ def read( len = nil )
151
+ stream_check!
152
+ return read_all unless len
153
+ str = @src[@pos, len]
154
+ @pos += len
155
+ @pos += 1 if @pos == @src.size
156
+ str
157
+ end
158
+
159
+ alias sysread read
160
+
161
+ def read_all
162
+ stream_check!
163
+ return nil if eof?
164
+ rest = @src[@pos ... @src.size]
165
+ @pos = @src.size + 1
166
+ rest
167
+ end
168
+
169
+ def stream_check!
170
+ @closed and raise IOError, 'closed stream'
171
+ end
172
+
173
+ end
174
+
175
+
176
+ class StringOutput#:nodoc:
177
+
178
+ class << self
179
+
180
+ def new( str = '' )
181
+ if block_given?
182
+ begin
183
+ f = super
184
+ yield f
185
+ ensure
186
+ f.close if f
187
+ end
188
+ else
189
+ super
190
+ end
191
+ end
192
+
193
+ alias open new
194
+
195
+ end
196
+
197
+ def initialize( str = '' )
198
+ @dest = str
199
+ @closed = false
200
+ end
201
+
202
+ def close
203
+ @closed = true
204
+ end
205
+
206
+ def closed?
207
+ @closed
208
+ end
209
+
210
+ def string
211
+ @dest
212
+ end
213
+
214
+ alias value string
215
+ alias to_str string
216
+
217
+ def size
218
+ @dest.size
219
+ end
220
+
221
+ alias pos size
222
+
223
+ def inspect
224
+ "#<#{self.class}:#{@dest ? 'open' : 'closed'},#{object_id}>"
225
+ end
226
+
227
+ def print( *args )
228
+ stream_check!
229
+ raise ArgumentError, 'wrong # of argument (0 for >1)' if args.empty?
230
+ args.each do |s|
231
+ raise ArgumentError, 'nil not allowed' if s.nil?
232
+ @dest << s.to_s
233
+ end
234
+ nil
235
+ end
236
+
237
+ def puts( *args )
238
+ stream_check!
239
+ args.each do |str|
240
+ @dest << (s = str.to_s)
241
+ @dest << "\n" unless s[-1] == ?\n
242
+ end
243
+ @dest << "\n" if args.empty?
244
+ nil
245
+ end
246
+
247
+ def putc( ch )
248
+ stream_check!
249
+ @dest << ch.chr
250
+ nil
251
+ end
252
+
253
+ def printf( *args )
254
+ stream_check!
255
+ @dest << sprintf(*args)
256
+ nil
257
+ end
258
+
259
+ def write( str )
260
+ stream_check!
261
+ s = str.to_s
262
+ @dest << s
263
+ s.size
264
+ end
265
+
266
+ alias syswrite write
267
+
268
+ def <<( str )
269
+ stream_check!
270
+ @dest << str.to_s
271
+ self
272
+ end
273
+
274
+ private
275
+
276
+ def stream_check!
277
+ @closed and raise IOError, 'closed stream'
278
+ end
279
+
280
+ end