2005-09-22 04:53:46 +00:00
|
|
|
module Rex
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class is the concrete representation of an abstract job.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class Job
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Creates an individual job instance and initializes it with the supplied
|
|
|
|
# parameters.
|
|
|
|
#
|
2005-09-23 14:41:26 +00:00
|
|
|
def initialize(container, jid, name, ctx, run_proc, clean_proc)
|
2005-09-22 04:53:46 +00:00
|
|
|
self.container = container
|
2005-09-23 14:41:26 +00:00
|
|
|
self.jid = jid
|
2005-09-22 04:53:46 +00:00
|
|
|
self.name = name
|
|
|
|
self.run_proc = run_proc
|
|
|
|
self.clean_proc = clean_proc
|
|
|
|
self.ctx = ctx
|
2009-12-02 03:32:48 +00:00
|
|
|
self.start_time = nil
|
2005-09-22 04:53:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2008-12-29 07:47:37 +00:00
|
|
|
# Runs the job in the context of its own thread if the async flag is false.
|
2005-11-15 05:22:13 +00:00
|
|
|
# Otherwise, the job is run inline.
|
2005-09-22 04:53:46 +00:00
|
|
|
#
|
|
|
|
def start(async = false)
|
2009-12-02 03:32:48 +00:00
|
|
|
self.start_time = Time.now
|
2005-09-22 04:53:46 +00:00
|
|
|
if (async)
|
|
|
|
self.job_thread = Thread.new {
|
2008-11-16 20:54:41 +00:00
|
|
|
# Deschedule our thread momentarily
|
|
|
|
select(nil, nil, nil, 0.01)
|
|
|
|
|
2006-01-05 01:54:38 +00:00
|
|
|
begin
|
|
|
|
run_proc.call(ctx)
|
|
|
|
ensure
|
|
|
|
clean_proc.call(ctx)
|
2006-09-16 20:07:25 +00:00
|
|
|
container.remove_job(self)
|
2006-01-05 01:54:38 +00:00
|
|
|
end
|
2005-09-22 04:53:46 +00:00
|
|
|
}
|
2008-11-16 20:54:41 +00:00
|
|
|
else
|
|
|
|
begin
|
|
|
|
run_proc.call(ctx)
|
|
|
|
rescue ::Exception
|
|
|
|
container.stop_job(jid)
|
|
|
|
raise $!
|
|
|
|
end
|
2005-09-22 04:53:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Stops the job if it's currently running and calls its cleanup procedure
|
|
|
|
#
|
|
|
|
def stop
|
|
|
|
if (self.job_thread)
|
|
|
|
self.job_thread.kill
|
|
|
|
self.job_thread = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
clean_proc.call(ctx) if (clean_proc)
|
|
|
|
end
|
|
|
|
|
2009-12-01 23:11:12 +00:00
|
|
|
#
|
|
|
|
# Surfaces the setings from the job to determine the current settings
|
|
|
|
#
|
|
|
|
def info
|
|
|
|
ret = {}
|
|
|
|
con = nil
|
|
|
|
ret['jid'] = self.jid
|
|
|
|
ret['name'] = self.name
|
|
|
|
if(self.ctx.class == Array)
|
|
|
|
con = self.ctx[0]
|
|
|
|
|
|
|
|
else
|
|
|
|
con = self.ctx
|
|
|
|
end
|
|
|
|
ret['datastore'] = con.datastore
|
|
|
|
if(con.kind_of? Msf::Exploit::Remote::HttpServer)
|
|
|
|
|
|
|
|
ret['datastore']['URIPATH'] = con.get_resource()
|
|
|
|
end
|
|
|
|
ret
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# The name of the job.
|
|
|
|
#
|
2005-09-22 04:53:46 +00:00
|
|
|
attr_reader :name
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# The job identifier as assigned by the job container.
|
|
|
|
#
|
2005-09-23 14:41:26 +00:00
|
|
|
attr_reader :jid
|
2005-09-22 04:53:46 +00:00
|
|
|
|
2009-12-02 03:32:48 +00:00
|
|
|
#
|
|
|
|
# The time at which this job was started
|
|
|
|
#
|
|
|
|
attr_reader :start_time #:nodoc:
|
|
|
|
|
2005-09-22 04:53:46 +00:00
|
|
|
protected
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
attr_writer :name #:nodoc:
|
|
|
|
attr_writer :jid #:nodoc:
|
|
|
|
attr_accessor :job_thread #:nodoc:
|
|
|
|
attr_accessor :container #:nodoc:
|
|
|
|
attr_accessor :run_proc #:nodoc:
|
|
|
|
attr_accessor :clean_proc #:nodoc:
|
|
|
|
attr_accessor :ctx #:nodoc:
|
2009-12-02 03:32:48 +00:00
|
|
|
attr_writer :start_time #:nodoc:
|
2005-09-22 04:53:46 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class contains zero or more abstract jobs that can be enumerated and
|
|
|
|
# stopped in a generic fashion. This is used to provide a mechanism for
|
|
|
|
# keeping track of arbitrary contexts that may or may not require a dedicated
|
|
|
|
# thread.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class JobContainer < Hash
|
|
|
|
|
|
|
|
def initialize
|
|
|
|
self.job_id_pool = 0
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Adds an already running task as a symbolic job to the container.
|
|
|
|
#
|
|
|
|
def add_job(name, ctx, run_proc, clean_proc)
|
|
|
|
real_name = name
|
|
|
|
count = 0
|
2005-09-23 14:41:26 +00:00
|
|
|
jid = job_id_pool
|
|
|
|
|
|
|
|
self.job_id_pool += 1
|
2005-09-22 04:53:46 +00:00
|
|
|
|
|
|
|
# If we were not supplied with a job name, pick one from the hat
|
|
|
|
if (real_name == nil)
|
2005-09-23 14:41:26 +00:00
|
|
|
real_name = '#' + jid.to_s
|
2005-09-22 04:53:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Find a unique job name
|
|
|
|
while (j = self[real_name])
|
|
|
|
real_name = name + " #{count}"
|
|
|
|
count += 1
|
|
|
|
end
|
|
|
|
|
2005-09-23 14:41:26 +00:00
|
|
|
j = Job.new(self, jid, real_name, ctx, run_proc, clean_proc)
|
2005-09-22 04:53:46 +00:00
|
|
|
|
2005-09-23 14:41:26 +00:00
|
|
|
self[jid.to_s] = j
|
2005-09-22 04:53:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-11-15 05:22:13 +00:00
|
|
|
# Starts a job using the supplied name and run/clean procedures.
|
2005-09-22 04:53:46 +00:00
|
|
|
#
|
|
|
|
def start_job(name, ctx, run_proc, clean_proc = nil)
|
|
|
|
j = add_job(name, ctx, run_proc, clean_proc)
|
|
|
|
j.start
|
2007-04-04 02:49:08 +00:00
|
|
|
|
|
|
|
j.jid
|
2005-09-22 04:53:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Starts a background job that doesn't call the cleanup routine or run
|
|
|
|
# the run_proc in its own thread. Rather, the run_proc is called
|
|
|
|
# immediately and the clean_proc is never called until the job is removed
|
|
|
|
# from the job container.
|
|
|
|
#
|
2006-04-03 04:33:30 +00:00
|
|
|
def start_bg_job(name, ctx, run_proc, clean_proc = nil, async = true)
|
2005-09-22 04:53:46 +00:00
|
|
|
j = add_job(name, ctx, run_proc, clean_proc)
|
2006-04-03 04:33:30 +00:00
|
|
|
j.start(async)
|
2007-04-04 02:49:08 +00:00
|
|
|
|
|
|
|
j.jid
|
2005-09-22 04:53:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Stops the job with the supplied name and forces it to cleanup. Stopping
|
|
|
|
# the job also leads to its removal.
|
|
|
|
#
|
2005-09-23 14:41:26 +00:00
|
|
|
def stop_job(jid)
|
|
|
|
if (j = self[jid.to_s])
|
2005-09-22 04:53:46 +00:00
|
|
|
j.stop
|
|
|
|
|
|
|
|
remove_job(j)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Removes a job that was previously running. This is typically called when
|
|
|
|
# a job completes its task.
|
|
|
|
#
|
|
|
|
def remove_job(inst)
|
2005-09-23 14:41:26 +00:00
|
|
|
self.delete(inst.jid.to_s)
|
2005-09-22 04:53:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
attr_accessor :job_id_pool # :nodoc:
|
2005-09-22 04:53:46 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
2008-11-16 20:54:41 +00:00
|
|
|
end
|