ragweed 0.1.7.2

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 (63) hide show
  1. data/History.txt +32 -0
  2. data/README.rdoc +35 -0
  3. data/README.txt +9 -0
  4. data/Rakefile +34 -0
  5. data/examples/hittracertux.rb +49 -0
  6. data/examples/hittracerx.rb +63 -0
  7. data/examples/hook_notepad.rb +9 -0
  8. data/examples/snicker.rb +183 -0
  9. data/examples/tux-example.rb +23 -0
  10. data/lib/ragweed/arena.rb +55 -0
  11. data/lib/ragweed/blocks.rb +128 -0
  12. data/lib/ragweed/debugger32.rb +338 -0
  13. data/lib/ragweed/debuggerosx.rb +427 -0
  14. data/lib/ragweed/debuggertux.rb +346 -0
  15. data/lib/ragweed/detour.rb +223 -0
  16. data/lib/ragweed/ptr.rb +48 -0
  17. data/lib/ragweed/rasm/bblock.rb +73 -0
  18. data/lib/ragweed/rasm/isa.rb +1115 -0
  19. data/lib/ragweed/rasm.rb +59 -0
  20. data/lib/ragweed/sbuf.rb +197 -0
  21. data/lib/ragweed/trampoline.rb +103 -0
  22. data/lib/ragweed/utils.rb +156 -0
  23. data/lib/ragweed/wrap32/debugging.rb +163 -0
  24. data/lib/ragweed/wrap32/device.rb +49 -0
  25. data/lib/ragweed/wrap32/event.rb +50 -0
  26. data/lib/ragweed/wrap32/hooks.rb +23 -0
  27. data/lib/ragweed/wrap32/overlapped.rb +46 -0
  28. data/lib/ragweed/wrap32/process.rb +506 -0
  29. data/lib/ragweed/wrap32/process_token.rb +59 -0
  30. data/lib/ragweed/wrap32/thread_context.rb +208 -0
  31. data/lib/ragweed/wrap32/winx.rb +16 -0
  32. data/lib/ragweed/wrap32/wrap32.rb +526 -0
  33. data/lib/ragweed/wrap32.rb +59 -0
  34. data/lib/ragweed/wraposx/constants.rb +122 -0
  35. data/lib/ragweed/wraposx/kernelerrorx.rb +147 -0
  36. data/lib/ragweed/wraposx/region_info.rb +254 -0
  37. data/lib/ragweed/wraposx/thread_context.rb +203 -0
  38. data/lib/ragweed/wraposx/thread_info.rb +227 -0
  39. data/lib/ragweed/wraposx/wraposx.rb +433 -0
  40. data/lib/ragweed/wraposx.rb +59 -0
  41. data/lib/ragweed/wraptux/constants.rb +68 -0
  42. data/lib/ragweed/wraptux/threads.rb +7 -0
  43. data/lib/ragweed/wraptux/wraptux.rb +76 -0
  44. data/lib/ragweed/wraptux.rb +59 -0
  45. data/lib/ragweed.rb +84 -0
  46. data/ragweed.gemspec +34 -0
  47. data/spec/ragweed_spec.rb +7 -0
  48. data/spec/spec_helper.rb +16 -0
  49. data/tasks/ann.rake +80 -0
  50. data/tasks/bones.rake +20 -0
  51. data/tasks/gem.rake +201 -0
  52. data/tasks/git.rake +40 -0
  53. data/tasks/notes.rake +27 -0
  54. data/tasks/post_load.rake +34 -0
  55. data/tasks/rdoc.rake +51 -0
  56. data/tasks/rubyforge.rake +55 -0
  57. data/tasks/setup.rb +292 -0
  58. data/tasks/spec.rake +54 -0
  59. data/tasks/svn.rake +47 -0
  60. data/tasks/test.rake +40 -0
  61. data/tasks/zentest.rake +36 -0
  62. data/test/test_ragweed.rb +0 -0
  63. metadata +132 -0
@@ -0,0 +1,59 @@
1
+ # Dir[File.expand_path("#{File.dirname(__FILE__)}/wraposx/*.rb")].each do |file|
2
+ # require file
3
+ # end
4
+ module Ragweed; end
5
+ module Ragweed::Wraposx
6
+
7
+ # :stopdoc:
8
+ VERSION = '0.1.7.2'
9
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
10
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
11
+ # :startdoc:
12
+
13
+ # Returns the version string for the library.
14
+ #
15
+ def self.version
16
+ VERSION
17
+ end
18
+
19
+ # Returns the library path for the module. If any arguments are given,
20
+ # they will be joined to the end of the libray path using
21
+ # <tt>File.join</tt>.
22
+ #
23
+ def self.libpath( *args )
24
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
25
+ end
26
+
27
+ # Returns the lpath for the module. If any arguments are given,
28
+ # they will be joined to the end of the path using
29
+ # <tt>File.join</tt>.
30
+ #
31
+ def self.path( *args )
32
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
33
+ end
34
+
35
+ # Utility function to load utility classes and extensions
36
+ def self.require_utils
37
+ %w{utils}.each{|r| require self.libpath(r)+'.rb'}
38
+ end
39
+
40
+ # Utility method used to require all files ending in .rb that lie in the
41
+ # directory below this file that has the same name as the filename passed
42
+ # in. Optionally, a specific _directory_ name can be passed in such that
43
+ # the _filename_ does not have to be equivalent to the directory.
44
+ #
45
+ def self.require_all_libs_relative_to( fname, dir = nil )
46
+ self.require_utils
47
+ dir ||= ::File.basename(fname, '.*')
48
+ search_me = ::File.expand_path(
49
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
50
+
51
+ Dir.glob(search_me).reject{|rb| rb =~ /#{__FILE__}/}.sort.each {|rb| require rb}
52
+ # require File.dirname(File.basename(__FILE__)) + "/#{x}"
53
+
54
+ end
55
+ end # module Ragweed::Wraposx
56
+
57
+ Ragweed::Wraposx.require_all_libs_relative_to(__FILE__)
58
+
59
+ # EOF
@@ -0,0 +1,68 @@
1
+ NULL = nil
2
+ module Ragweed; end
3
+ module Ragweed::Wraptux;end
4
+
5
+ module Ragweed::Wraptux::Ptrace
6
+ TRACE_ME = 0
7
+ PEEK_TEXT = 1
8
+ PEEK_DATA = 2
9
+ PEEK_USER = 3
10
+ POKE_TEXT = 4
11
+ POKE_DATA = 5
12
+ POKE_USER = 6
13
+ CONTINUE = 7
14
+ KILL = 8
15
+ STEP = 9
16
+ GETREGS = 12
17
+ SETREGS = 13
18
+ ATTACH = 16
19
+ DETACH = 17
20
+ SYSCALL = 24
21
+ end
22
+
23
+ module Ragweed::Wraptux::Signal
24
+ SIGHUP = 1
25
+ SIGINT = 2
26
+ SIGQUIT = 3
27
+ SIGILL = 4
28
+ SIGTRAP = 5
29
+ SIGABRT = 6
30
+ SIGIOT = 6
31
+ SIGBUS = 7
32
+ SIGFPE = 8
33
+ SIGKILL = 9
34
+ SIGUSR1 = 10
35
+ SIGSEGV = 11
36
+ SIGUSR2 = 12
37
+ SIGPIPE = 13
38
+ SIGALRM = 14
39
+ SIGTERM = 15
40
+ SIGSTKFLT = 16
41
+ SIGCHLD = 17
42
+ SIGCONT = 18
43
+ SIGSTOP = 19
44
+ SIGTSTP = 20
45
+ SIGTTIN = 21
46
+ SIGTTOU = 22
47
+ SIGURG = 23
48
+ SIGXCPU = 24
49
+ SIGXFSZ = 25
50
+ SIGVTALRM = 26
51
+ SIGPROF = 27
52
+ SIGWINCH = 28
53
+ SIGIO = 29
54
+ SIGPOLL = SIGIO
55
+ #SIGLOST = 29
56
+ SIGPWR = 30
57
+ SIGSYS = 31
58
+ SIGUNUSED = 31
59
+ end
60
+
61
+ module Ragweed::Wraptux::Wait
62
+ NOHANG = 1
63
+ UNTRACED = 2
64
+ EXITED = 4
65
+ STOPPED = 8
66
+ CONTINUED = 10
67
+ NOWWAIT = 20
68
+ end
@@ -0,0 +1,7 @@
1
+ ## New 'ThreadInfo' sub module
2
+ ## so Wraptux matches the API
3
+ module Ragweed; end
4
+ module Ragweed::Wraptux; end
5
+
6
+ module Ragweed::Wraptux::ThreadInfo
7
+ end
@@ -0,0 +1,76 @@
1
+ require 'dl'
2
+
3
+ module Ragweed; end
4
+ module Ragweed::Wraptux
5
+ LIBS = Hash.new do |h, str|
6
+ if not str =~ /^[\.\/].*/
7
+ str = "/lib/" + str
8
+ end
9
+ if not str =~ /.*\.so.6$/
10
+ str = str + ".so.6"
11
+ end
12
+ h[str] = DL.dlopen(str)
13
+ end
14
+
15
+ CALLS = Hash.new do |h, str|
16
+ lib = proc = args = ret = nil
17
+ lib, rest = str.split "!"
18
+ proc, rest = rest.split ":"
19
+ args, ret = rest.split("=") if rest
20
+ ret ||= "0"
21
+ raise "need proc" if not proc
22
+ h[str] = LIBS[lib][proc, ret + args]
23
+ end
24
+
25
+ NULL = DL::PtrData.new(0)
26
+
27
+ SIZEOFINT = DL.sizeof('I')
28
+ SIZEOFLONG = DL.sizeof('L')
29
+
30
+ class << self
31
+ #long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
32
+ def ptrace(request, pid, addr, data)
33
+ DL.last_error = 0
34
+ r = CALLS["libc!ptrace:IIII=I"].call(request, pid, addr, data).first
35
+ raise SystemCallError.new("ptrace", DL.last_error) if r == -1 and DL.last_error != 0
36
+
37
+ case request
38
+ when Ptrace::PEEK_TEXT, Ptrace::PEEK_DATA
39
+ return r
40
+ end
41
+ end
42
+
43
+ def malloc(sz)
44
+ r = CALLS["libc!malloc:L=L"].call(sz)
45
+ return r
46
+ end
47
+
48
+ #wait(int *status);
49
+ def wait
50
+ status = ("\x00"*SIZEOFINT).to_ptr.to_i
51
+ r = CALLS["libc!wait:I=I"].call(status).first
52
+ raise SystemCallError.new("wait", DL.last_error) if r == -1
53
+ self.continue # continue with the ptrace at this point
54
+ return status.to_s(SIZEOFINT).unpack('i_').first
55
+ end
56
+
57
+ #waitpid(pid_t pid, int *stat_loc, int options);
58
+ def waitpid(pid, opt=1)
59
+ pstatus = ("\x00"*SIZEOFINT).to_ptr
60
+ r = CALLS["libc!waitpid:IPI=I"].call(pid, pstatus, opt).first
61
+ raise SystemCallError.new("waitpid", DL.last_error) if r == -1
62
+ return [r, pstatus.to_s(SIZEOFINT).unpack('i_').first]
63
+ end
64
+
65
+ #kill(pid_t pid, int sig);
66
+ def kill(pid, sig)
67
+ DL.last_error = 0
68
+ r = CALLS["libc!kill:II=I"].call(pid,sig).first
69
+ raise SystemCallError.new("kill",DL.last_error) if r != 0
70
+ end
71
+
72
+ def getpid
73
+ CALLS["libc!getpid:=I"].call.first
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,59 @@
1
+ # Dir[File.expand_path("#{File.dirname(__FILE__)}/wraptux/*.rb")].each do |file|
2
+ # require file
3
+ # end
4
+ module Ragweed; end
5
+ module Ragweed::Wraptux
6
+
7
+ # :stopdoc:
8
+ VERSION = '0.1.7.2'
9
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
10
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
11
+ # :startdoc:
12
+
13
+ # Returns the version string for the library.
14
+ #
15
+ def self.version
16
+ VERSION
17
+ end
18
+
19
+ # Returns the library path for the module. If any arguments are given,
20
+ # they will be joined to the end of the libray path using
21
+ # <tt>File.join</tt>.
22
+ #
23
+ def self.libpath( *args )
24
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
25
+ end
26
+
27
+ # Returns the lpath for the module. If any arguments are given,
28
+ # they will be joined to the end of the path using
29
+ # <tt>File.join</tt>.
30
+ #
31
+ def self.path( *args )
32
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
33
+ end
34
+
35
+ # Utility function to load utility classes and extensions
36
+ def self.require_utils
37
+ %w{utils}.each{|r| require self.libpath(r)+'.rb'}
38
+ end
39
+
40
+ # Utility method used to require all files ending in .rb that lie in the
41
+ # directory below this file that has the same name as the filename passed
42
+ # in. Optionally, a specific _directory_ name can be passed in such that
43
+ # the _filename_ does not have to be equivalent to the directory.
44
+ #
45
+ def self.require_all_libs_relative_to( fname, dir = nil )
46
+ self.require_utils
47
+ dir ||= ::File.basename(fname, '.*')
48
+ search_me = ::File.expand_path(
49
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
50
+
51
+ Dir.glob(search_me).sort.each {|rb| require rb}
52
+ # require File.dirname(File.basename(__FILE__)) + "/#{x}"
53
+
54
+ end
55
+ end # module Ragweed::Wraptux
56
+
57
+ Ragweed::Wraptux.require_all_libs_relative_to(__FILE__)
58
+
59
+ # EOF
data/lib/ragweed.rb ADDED
@@ -0,0 +1,84 @@
1
+
2
+ module Ragweed
3
+
4
+ # :stopdoc:
5
+ VERSION = '0.1.7.2'
6
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
7
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
8
+ # :startdoc:
9
+
10
+ # Returns the version string for the library.
11
+ #
12
+ def self.version
13
+ VERSION
14
+ end
15
+
16
+ # Returns the library path for the module. If any arguments are given,
17
+ # they will be joined to the end of the libray path using
18
+ # <tt>File.join</tt>.
19
+ #
20
+ def self.libpath( *args )
21
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
22
+ end
23
+
24
+ # Returns the lpath for the module. If any arguments are given,
25
+ # they will be joined to the end of the path using
26
+ # <tt>File.join</tt>.
27
+ #
28
+ def self.path( *args )
29
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
30
+ end
31
+
32
+ # Utility method used to require all files ending in .rb that lie in the
33
+ # directory below this file that has the same name as the filename passed
34
+ # in. Optionally, a specific _directory_ name can be passed in such that
35
+ # the _filename_ does not have to be equivalent to the directory.
36
+ #
37
+ def self.require_all_libs_relative_to( fname, dir = nil )
38
+ dir ||= ::File.basename(fname, '.*')
39
+ search_me = ::File.expand_path(
40
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
41
+
42
+ # Don't want to load wrapper or debugger here.
43
+ Dir.glob(search_me).sort.reject{|rb| rb =~ /(wrap|debugger|rasm[^\.])/}.each {|rb| require rb}
44
+ # require File.dirname(File.basename(__FILE__)) + "/#{x}"d
45
+ end
46
+
47
+ def self.require_os_libs_relative_to( fname, dir= nil )
48
+ dir ||= ::File.basename(fname, '.*')
49
+ pkgs = ""
50
+ dbg = ""
51
+ case
52
+ when RUBY_PLATFORM =~ /win(dows|32)/i
53
+ pkgs = '32'
54
+ when RUBY_PLATFORM =~ /darwin/i
55
+ pkgs = 'osx'
56
+ when RUBY_PLATFORM =~ /linux/i
57
+ pkgs = 'tux'
58
+ # when RUBY_PLATFORM =~ /java/i
59
+ # TODO - Java port using jni?
60
+ else
61
+ warn "Platform not supported no wrapper libraries loaded."
62
+ end
63
+
64
+ if not pkgs.empty?
65
+ search_me = File.expand_path(File.join(File.dirname(fname), dir, "*#{pkgs}.rb"))
66
+ Dir.glob(search_me).sort.reverse.each {|rb| require rb}
67
+ end
68
+ end
69
+ end # module Ragweed
70
+
71
+
72
+ # pkgs = %w[arena sbuf ptr process event rasm blocks detour trampoline device debugger hooks]
73
+ # pkgs << 'wrap32' if RUBY_PLATFORM =~ /win(dows|32)/i
74
+ # pkgs << 'wraposx' if RUBY_PLATFORM =~ /darwin/i
75
+ # pkgs << 'wraptux' if RUBY_PLATFORM =~ /linux/i
76
+ # pkgs.each do |x|
77
+ # require File.dirname(__FILE__) + "/#{x}"
78
+ # end
79
+
80
+
81
+ Ragweed.require_os_libs_relative_to(__FILE__)
82
+ Ragweed.require_all_libs_relative_to(__FILE__)
83
+
84
+ # EOF
data/ragweed.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ragweed}
5
+ s.version = "0.1.7.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["tduehr, tqbf, struct"]
9
+ s.date = %q{2009-09-21}
10
+ s.description = %q{General debugging tool written in Ruby for OSX/Win32/Linux}
11
+ s.email = %q{td@matasano.com}
12
+ s.extra_rdoc_files = ["History.txt", "README.rdoc", "README.txt"]
13
+ s.files = ["History.txt", "README.rdoc", "README.txt", "Rakefile", "examples/hittracertux.rb", "examples/hittracerx.rb", "examples/hook_notepad.rb", "examples/snicker.rb", "examples/tux-example.rb", "lib/ragweed.rb", "lib/ragweed/arena.rb", "lib/ragweed/blocks.rb", "lib/ragweed/debugger32.rb", "lib/ragweed/debuggerosx.rb", "lib/ragweed/debuggertux.rb", "lib/ragweed/detour.rb", "lib/ragweed/ptr.rb", "lib/ragweed/rasm.rb", "lib/ragweed/rasm/bblock.rb", "lib/ragweed/rasm/isa.rb", "lib/ragweed/sbuf.rb", "lib/ragweed/trampoline.rb", "lib/ragweed/utils.rb", "lib/ragweed/wrap32.rb", "lib/ragweed/wrap32/debugging.rb", "lib/ragweed/wrap32/device.rb", "lib/ragweed/wrap32/event.rb", "lib/ragweed/wrap32/hooks.rb", "lib/ragweed/wrap32/overlapped.rb", "lib/ragweed/wrap32/process.rb", "lib/ragweed/wrap32/process_token.rb", "lib/ragweed/wrap32/thread_context.rb", "lib/ragweed/wrap32/winx.rb", "lib/ragweed/wrap32/wrap32.rb", "lib/ragweed/wraposx.rb", "lib/ragweed/wraposx/constants.rb", "lib/ragweed/wraposx/kernelerrorx.rb", "lib/ragweed/wraposx/region_info.rb", "lib/ragweed/wraposx/thread_context.rb", "lib/ragweed/wraposx/thread_info.rb", "lib/ragweed/wraposx/wraposx.rb", "lib/ragweed/wraptux.rb", "lib/ragweed/wraptux/constants.rb", "lib/ragweed/wraptux/threads.rb", "lib/ragweed/wraptux/wraptux.rb", "ragweed.gemspec", "spec/ragweed_spec.rb", "spec/spec_helper.rb", "tasks/ann.rake", "tasks/bones.rake", "tasks/gem.rake", "tasks/git.rake", "tasks/notes.rake", "tasks/post_load.rake", "tasks/rdoc.rake", "tasks/rubyforge.rake", "tasks/setup.rb", "tasks/spec.rake", "tasks/svn.rake", "tasks/test.rake", "tasks/zentest.rake", "test/test_ragweed.rb"]
14
+ s.homepage = %q{http://github.com/tduehr/ragweed/tree/master}
15
+ s.rdoc_options = ["--inline-source", "--line-numbers", "--main", "README.txt"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{Scriptable debugger}
20
+ s.test_files = ["test/test_ragweed.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_development_dependency(%q<bones>, [">= 2.5.1"])
28
+ else
29
+ s.add_dependency(%q<bones>, [">= 2.5.1"])
30
+ end
31
+ else
32
+ s.add_dependency(%q<bones>, [">= 2.5.1"])
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe Ragweed do
5
+ end
6
+
7
+ # EOF
@@ -0,0 +1,16 @@
1
+
2
+ require File.expand_path(
3
+ File.join(File.dirname(__FILE__), %w[.. lib ragweed]))
4
+
5
+ Spec::Runner.configure do |config|
6
+ # == Mock Framework
7
+ #
8
+ # RSpec uses it's own mocking framework by default. If you prefer to
9
+ # use mocha, flexmock or RR, uncomment the appropriate line:
10
+ #
11
+ # config.mock_with :mocha
12
+ # config.mock_with :flexmock
13
+ # config.mock_with :rr
14
+ end
15
+
16
+ # EOF
data/tasks/ann.rake ADDED
@@ -0,0 +1,80 @@
1
+
2
+ begin
3
+ require 'bones/smtp_tls'
4
+ rescue LoadError
5
+ require 'net/smtp'
6
+ end
7
+ require 'time'
8
+
9
+ namespace :ann do
10
+
11
+ # A prerequisites task that all other tasks depend upon
12
+ task :prereqs
13
+
14
+ file PROJ.ann.file do
15
+ ann = PROJ.ann
16
+ puts "Generating #{ann.file}"
17
+ File.open(ann.file,'w') do |fd|
18
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
19
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
20
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
21
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
22
+ fd.puts
23
+ fd.puts("== DESCRIPTION")
24
+ fd.puts
25
+ fd.puts(PROJ.description)
26
+ fd.puts
27
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
28
+ fd.puts
29
+ ann.paragraphs.each do |p|
30
+ fd.puts "== #{p.upcase}"
31
+ fd.puts
32
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
33
+ fd.puts
34
+ end
35
+ fd.puts ann.text if ann.text
36
+ end
37
+ end
38
+
39
+ desc "Create an announcement file"
40
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
41
+
42
+ desc "Send an email announcement"
43
+ task :email => ['ann:prereqs', PROJ.ann.file] do
44
+ ann = PROJ.ann
45
+ from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
46
+ to = Array(ann.email[:to])
47
+
48
+ ### build a mail header for RFC 822
49
+ rfc822msg = "From: #{from}\n"
50
+ rfc822msg << "To: #{to.join(',')}\n"
51
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
52
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
53
+ rfc822msg << "\n"
54
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
55
+ rfc822msg << "Message-Id: "
56
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
57
+ rfc822msg << File.read(ann.file)
58
+
59
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
60
+ ann.email[key]
61
+ end
62
+
63
+ params[3] = PROJ.email if params[3].nil?
64
+
65
+ if params[4].nil?
66
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
67
+ params[4] = STDIN.gets.chomp
68
+ end
69
+
70
+ ### send email
71
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
72
+ end
73
+ end # namespace :ann
74
+
75
+ desc 'Alias to ann:announcement'
76
+ task :ann => 'ann:announcement'
77
+
78
+ CLOBBER << PROJ.ann.file
79
+
80
+ # EOF
data/tasks/bones.rake ADDED
@@ -0,0 +1,20 @@
1
+
2
+ if HAVE_BONES
3
+
4
+ namespace :bones do
5
+
6
+ desc 'Show the PROJ open struct'
7
+ task :debug do |t|
8
+ atr = if t.application.top_level_tasks.length == 2
9
+ t.application.top_level_tasks.pop
10
+ end
11
+
12
+ if atr then Bones::Debug.show_attr(PROJ, atr)
13
+ else Bones::Debug.show PROJ end
14
+ end
15
+
16
+ end # namespace :bones
17
+
18
+ end # HAVE_BONES
19
+
20
+ # EOF