Module: Ragweed::Wraposx
- Defined in:
- lib/ragweed/wraposx.rb,
lib/ragweed/wraposx/wraposx.rb,
lib/ragweed/wraposx/constants.rb,
lib/ragweed/wraposx/region_info.rb,
lib/ragweed/wraposx/region_info.rb,
lib/ragweed/wraposx/thread_info.rb,
lib/ragweed/wraposx/kernelerrorx.rb,
lib/ragweed/wraposx/thread_context.rb,
lib/ragweed/wraposx/thread_context.rb
Defined Under Namespace
Modules: Dl, EFlags, KErrno, KernelReturn, Ptrace, Signal, ThreadInfo, Vm, Wait Classes: KernelCallError, RegionBasicInfo, RegionExtendedInfo, RegionInfo, RegionTopInfo, ThreadContext
Constant Summary collapse
- VERSION =
:stopdoc:
'0.1.6'- LIBPATH =
::File.(::File.dirname(__FILE__)) + ::File::SEPARATOR
- PATH =
::File.dirname(LIBPATH) + ::File::SEPARATOR
- LIBS =
These hashes are the magic glue of the ragweed system calls. This one holds the library references from Ruby/DL.
Hash.new do |h, str| if not str =~ /^[\.\/].*/ str = "/usr/lib/" + str end if not str =~ /.*\.dylib$/ str = str + ".dylib" end h[str] = DL.dlopen(str) end
- CALLS =
This hash holds the function references from Ruby/DL. It also auto populates LIBS. CALLS[“<library>!<function>:<argument types>=<return type>”] Hash.new is a beautiful thing.
Hash.new do |h, str| lib = proc = args = ret = nil lib, rest = str.split "!" proc, rest = rest.split ":" args, ret = rest.split("=") if rest ret ||= "0" raise "need proc" if not proc h[str] = LIBS[lib][proc, ret + args] end
- NULL =
DL::PtrData.new(0)
- SIZEOFINT =
DL.sizeof('I')
- SIZEOFLONG =
DL.sizeof('L')
- I386_THREAD_STATE_COUNT =
FIXME - constants need to be in separate sub modules XXX - move to class based implementation a la region_info define i386_THREAD_STATE_COUNT ((mach_msg_type_number_t)( sizeof (i386_thread_state_t) / sizeof (int) )) i386_thread_state_t is a struct w/ 16 uint
16- I386_THREAD_STATE =
1- REGISTER_SYMS =
[:eax,:ebx,:ecx,:edx,:edi,:esi,:ebp,:esp,:ss,:eflags,:eip,:cs,:ds,:es,:fs,:gs]
Class Method Summary collapse
-
.dl_bignum_to_ulong(x) ⇒ Object
function to marshal 32bit integers into DL::PtrData objects necessary due to Ruby/DL not properly dealing with 31 and 32 bit integers.
-
.execv(path, *args) ⇒ Object
Changes execution to file in path with *args as though called from command line.
-
.getpid ⇒ Object
pid_t getpid(void);.
-
.kill(pid, sig) ⇒ Object
Sends a signal to a process.
-
.libpath(*args) ⇒ Object
Returns the library path for the module.
-
.mach_task_self ⇒ Object
From docs at web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_task_self.html Returns send rights to the task’s kernel port.
-
.path(*args) ⇒ Object
Returns the lpath for the module.
-
.ptrace(request, pid, addr, data) ⇒ Object
Apple’s ptrace is fairly gimped.
-
.require_all_libs_relative_to(fname, dir = nil) ⇒ Object
Utility method used to require all files ending in .rb that lie in the directory below this file that has the same name as the filename passed in.
-
.sysctl(mib, oldlen = 0, newb = "") ⇒ Object
Used to query kernel state.
-
.sysctl_raw(mib, oldlen = 0, newb = "") ⇒ Object
Used to query kernel state.
-
.task_for_pid(pid, target = nil) ⇒ Object
Requires sudo to use as of 10.5 or 10.4.11(ish) Returns the task id for a process.
-
.task_resume(task) ⇒ Object
Resumes a suspended task by id.
-
.task_suspend(task) ⇒ Object
Suspends a task by id.
-
.task_threads(port) ⇒ Object
Returns an Array of thread IDs for the given task.
-
.thread_get_state(thread) ⇒ Object
Returns a Hash of the thread’s registers given a thread id.
-
.thread_get_state_raw(thread) ⇒ Object
Returns string representation of a thread’s registers for unpacking given a thread id.
-
.thread_info_raw(thread, flavor) ⇒ Object
Returns the packed string representation of the thread_info_t struct for later parsing.
-
.thread_resume(thread) ⇒ Object
Resumes a suspended thread by id.
-
.thread_set_state(thread, state) ⇒ Object
Sets the register state of thread from a Hash containing it’s values.
-
.thread_set_state_raw(thread, state) ⇒ Object
Sets the register state of thread from a packed string containing it’s values.
-
.thread_suspend(thread) ⇒ Object
Suspends a thread by id.
-
.time ⇒ Object
time_t time(time_t *tloc);.
-
.version ⇒ Object
Returns the version string for the library.
-
.vm_protect(task, addr, size, setmax, prot) ⇒ Object
Changes the protection state beginning at addr for size bytes to the mask prot.
-
.vm_read(task, addr, sz = 256) ⇒ Object
Reads sz bytes from task’s address space starting at addr.
-
.vm_region_raw(task, address, flavor) ⇒ Object
Returns a string containing the memory region information for task at address.
-
.vm_write(task, addr, val) ⇒ Object
Writes val to task’s memory space at address addr.
-
.wait ⇒ Object
Oringially coded for use in debuggerosx but I’ve switched to waitpid for usability and debugging purposes.
-
.waitpid(pid, opt = 1) ⇒ Object
The wait used in debuggerosx.
Class Method Details
.dl_bignum_to_ulong(x) ⇒ Object
function to marshal 32bit integers into DL::PtrData objects necessary due to Ruby/DL not properly dealing with 31 and 32 bit integers
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 167 def dl_bignum_to_ulong(x) if x.class == Fixnum return DL::PtrData.new(x) else # shut up c = x / 4 e = x - (c * 4) v = DL::PtrData.new 0 v += c v += c v += c v += c v += e return v end end |
.execv(path, *args) ⇒ Object
Changes execution to file in path with *args as though called from command line.
int execv(const char *path, char *const argv[]);
342 343 344 345 346 347 348 349 350 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 342 def execv(path,*args) DL.last_error = 0 argv = "" args.flatten.each { |arg| argv = "#{ argv }#{arg.to_ptr.ref.to_s(SIZEOFINT)}" } argv += ("\x00"*SIZEOFINT) r = CALLS["libc!execv:SP"].call(path,argv.to_ptr).first raise SystemCallError.new("execv", DL.last_error) if r == -1 return r end |
.getpid ⇒ Object
pid_t getpid(void);
see also getpid(2)
51 52 53 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 51 def getpid CALLS["libc!getpid:=I"].call.first end |
.kill(pid, sig) ⇒ Object
Sends a signal to a process
int kill(pid_t pid, int sig);
See kill(2)
159 160 161 162 163 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 159 def kill(pid, sig) DL.last_error = 0 r = CALLS["libc!kill:II=I"].call(pid,sig).first raise SystemCallError.new("kill",DL.last_error) if r != 0 end |
.libpath(*args) ⇒ Object
Returns the library path for the module. If any arguments are given, they will be joined to the end of the libray path using File.join.
23 24 25 |
# File 'lib/ragweed/wraposx.rb', line 23 def self.libpath( *args ) args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten) end |
.mach_task_self ⇒ Object
From docs at web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_task_self.html Returns send rights to the task’s kernel port.
mach_port_t mach_task_self(void)
There is no man page for this call.
114 115 116 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 114 def mach_task_self CALLS["libc!mach_task_self:=I"].call().first end |
.path(*args) ⇒ Object
Returns the lpath for the module. If any arguments are given, they will be joined to the end of the path using File.join.
31 32 33 |
# File 'lib/ragweed/wraposx.rb', line 31 def self.path( *args ) args.empty? ? PATH : ::File.join(PATH, args.flatten) end |
.ptrace(request, pid, addr, data) ⇒ Object
Apple’s ptrace is fairly gimped. The memory read and write functionality has been removed. We will be using mach kernel calls for that. see vm_read and vm_write. for details on ptrace and the process for the Wraposx/debuggerosx port see: www.matasano.com/log/1100/what-ive-been-doing-on-my-summer-vacation-or-it-has-to-work-otherwise-gdb-wouldnt/
int ptrace(int request, pid_t pid, caddr_t addr, int data);
see also ptrace(2)
64 65 66 67 68 69 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 64 def ptrace(request, pid, addr, data) DL.last_error = 0 r = CALLS["libc!ptrace:IIII=I"].call(request, pid, addr, data).first raise SystemCallError.new("ptrace", DL.last_error) if r == -1 and DL.last_error != 0 return r end |
.require_all_libs_relative_to(fname, dir = nil) ⇒ Object
Utility method used to require all files ending in .rb that lie in the directory below this file that has the same name as the filename passed in. Optionally, a specific directory name can be passed in such that the filename does not have to be equivalent to the directory.
40 41 42 43 44 45 46 47 48 |
# File 'lib/ragweed/wraposx.rb', line 40 def self.require_all_libs_relative_to( fname, dir = nil ) dir ||= ::File.basename(fname, '.*') search_me = ::File.( ::File.join(::File.dirname(fname), dir, '**', '*.rb')) Dir.glob(search_me).sort.each {|rb| require rb} # require File.dirname(File.basename(__FILE__)) + "/#{x}" end |
.sysctl(mib, oldlen = 0, newb = "") ⇒ Object
Used to query kernel state. Returns output buffer on successful call or required buffer size on ENOMEM.
mib: and array of integers decribing the MIB newb: the buffer to replace the old information (only used on some commands so it defaults to empty) oldlenp: output buffer size
int
sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
this function doesn’t really match the Ruby Way(tm)
see sysctl(8)
297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 297 def sysctl(mib,oldlen=0,newb="") DL.last_error = 0 mibp = mib.pack("I_"*mib.size).to_ptr oldlenp = [oldlen].pack("I_").to_ptr namelen = mib.size oldp = (oldlen > 0 ? "\x00"*oldlen : NULL) newp = (newb.empty? ? NULL : newb.to_ptr) newlen = newb.size r = CALLS["libc!sysctl:PIPPPI=I"].call(mibp, namelen, oldp, oldlenp, newp, newlen).first return oldlenp.to_str(SIZEOFINT).unpack("I_").first if (r == -1 and DL.last_error == Errno::ENOMEM::Errno) raise SystemCallError.new("sysctl", DL.last_error) if r != 0 return oldp.to_str(oldlenp.to_str(SIZEOFINT).unpack("I_").first) end |
.sysctl_raw(mib, oldlen = 0, newb = "") ⇒ Object
Used to query kernel state. Returns output buffer on successful call and required buffer size as an Array.
mib: and array of integers decribing the MIB newb: the buffer to replace the old information (only used on some commands so it defaults to empty) oldlenp: output buffer size
int
sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
this function doesn’t really match the Ruby Way(tm)
see sysctl(8)
324 325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 324 def sysctl_raw(mib,oldlen=0,newb="") DL.last_error = 0 mibp = mib.pack('I_'*mib.size).to_ptr oldlenp = [oldlen].pack("I_").to_ptr namelen = mib.size oldp = (oldlen > 0 ? ("\x00"*oldlen).to_ptr : NULL) newp = (newb.empty? ? NULL : newb.to_ptr) newlen = newb.size r = CALLS["libc!sysctl:PIPPPI=I"].call(mibp, namelen, oldp, oldlenp, newp, newlen).first ret = (DL.last_error == Errno::ENOMEM::Errno ? NULL : oldp) raise SystemCallError.new("sysctl", DL.last_error) if (r != 0 and DL.last_error != Errno::ENOMEM::Errno) return [ret,oldlenp.to_str(SIZEOFINT).unpack("I_").first] end |
.task_for_pid(pid, target = nil) ⇒ Object
Requires sudo to use as of 10.5 or 10.4.11(ish) Returns the task id for a process.
kern_return_t task_for_pid(
mach_port_name_t target_tport,
int pid,
mach_port_name_t *t);
There is no man page for this call.
127 128 129 130 131 132 133 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 127 def task_for_pid(pid, target=nil) target ||= mach_task_self port = ("\x00"*SIZEOFINT).to_ptr r = CALLS["libc!task_for_pid:IIP=I"].call(target, pid, port).first raise KernelCallError.new(:task_for_pid, r) if r != 0 return port.to_s(SIZEOFINT).unpack('i_').first end |
.task_resume(task) ⇒ Object
Resumes a suspended task by id.
kern_return_t task_resume
(task_t task);
There is no man page for this function.
279 280 281 282 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 279 def task_resume(task) r = CALLS["libc!task_resume:I=I"].call(task).first raise KernelCallError.new(:task_resume, r) if r != 0 end |
.task_suspend(task) ⇒ Object
Suspends a task by id.
kern_return_t task_suspend
(task_t task);
There is no man page for this function.
268 269 270 271 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 268 def task_suspend(task) r = CALLS["libc!task_suspend:I=I"].call(task).first raise KernelCallError.new(:task_suspend, r) if r != 0 end |
.task_threads(port) ⇒ Object
Returns an Array of thread IDs for the given task
kern_return_t task_threads
(task_t task,
thread_act_port_array_t thread_list,
mach_msg_type_number_t* thread_count);
There is no man page for this funtion.
143 144 145 146 147 148 149 150 151 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 143 def task_threads(port) threads = ("\x00"*SIZEOFINT).to_ptr #threads = 0 count = ("\x00"*SIZEOFINT).to_ptr r = CALLS["libc!task_threads:IPP=I"].call(port, threads, count).first t = DL::PtrData.new(threads.to_s(SIZEOFINT).unpack('i_').first) raise KernelCallError.new(:task_threads, r) if r != 0 return t.to_a("I", count.to_s(SIZEOFINT).unpack('I_').first) end |
.thread_get_state(thread) ⇒ Object
Returns a Hash of the thread’s registers given a thread id.
kern_return_t thread_get_state
(thread_act_t target_thread,
thread_state_flavor_t flavor,
thread_state_t old_state,
mach_msg_type_number_t old_state_count);
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/ragweed/wraposx/thread_context.rb', line 146 def thread_get_state(thread) state_arr = ("\x00"*SIZEOFINT*I386_THREAD_STATE_COUNT).to_ptr count = ([I386_THREAD_STATE_COUNT].pack("I_")).to_ptr r = CALLS["libc!thread_get_state:IIPP=I"].call(thread, I386_THREAD_STATE, state_arr, count).first raise KernelCallError.new(:thread_get_state, r) if r != 0 r = state_arr.to_s(I386_THREAD_STATE_COUNT*SIZEOFINT).unpack("I_"*I386_THREAD_STATE_COUNT) regs = Hash.new I386_THREAD_STATE_COUNT.times do |i| regs[REGISTER_SYMS[i]] = r[i] end return regs end |
.thread_get_state_raw(thread) ⇒ Object
Returns string representation of a thread’s registers for unpacking given a thread id
kern_return_t thread_get_state
(thread_act_t target_thread,
thread_state_flavor_t flavor,
thread_state_t old_state,
mach_msg_type_number_t old_state_count);
166 167 168 169 170 171 172 |
# File 'lib/ragweed/wraposx/thread_context.rb', line 166 def thread_get_state_raw(thread) state_arr = ("\x00"*SIZEOFINT*I386_THREAD_STATE_COUNT).to_ptr count = ([I386_THREAD_STATE_COUNT].pack("I_")).to_ptr r = CALLS["libc!thread_get_state:IIPP=I"].call(thread, I386_THREAD_STATE, state_arr, count).first raise KernelCallError.new(:thread_get_state, r) if r != 0 return state_arr.to_s(I386_THREAD_STATE_COUNT*SIZEOFINT) end |
.thread_info_raw(thread, flavor) ⇒ Object
Returns the packed string representation of the thread_info_t struct for later parsing. kern_return_t thread_info
(thread_act_t target_thread,
thread_flavor_t flavor,
thread_info_t thread_info,
mach_msg_type_number_t thread_info_count);
217 218 219 220 221 222 223 |
# File 'lib/ragweed/wraposx/thread_info.rb', line 217 def thread_info_raw(thread, flavor) info = ("\x00"*1024).to_ptr count = ([Ragweed::Wraposx::ThreadInfo::FLAVORS[flavor][:count]].pack("I_")).to_ptr r = CALLS["libc!thread_info:IIPP=I"].call(thread,flavor,info,Ragweed::Wraposx::ThreadInfo::FLAVORS[flavor][:count]).first raise KernelCallError.new(r) if r != 0 return info.to_s(Ragweed::Wraposx::ThreadInfo::FLAVORS[flavor][:size]) end |
.thread_resume(thread) ⇒ Object
Resumes a suspended thread by id.
kern_return_t thread_resume
(thread_act_t target_thread);
There is no man page for this function.
246 247 248 249 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 246 def thread_resume(thread) r = CALLS["libc!thread_resume:I=I"].call(thread).first raise KernelCallError.new(:thread_resume, r) if r != 0 end |
.thread_set_state(thread, state) ⇒ Object
Sets the register state of thread from a Hash containing it’s values.
kern_return_t thread_set_state
(thread_act_t target_thread,
thread_state_flavor_t flavor,
thread_state_t new_state,
target_thread new_state_count);
181 182 183 184 185 186 187 188 189 |
# File 'lib/ragweed/wraposx/thread_context.rb', line 181 def thread_set_state(thread, state) s = Array.new I386_THREAD_STATE_COUNT.times do |i| s << state[REGISTER_SYMS[i]] end s = s.pack("I_"*I386_THREAD_STATE_COUNT).to_ptr r = CALLS["libc!thread_set_state:IIPI=I"].call(thread, I386_THREAD_STATE, s, I386_THREAD_STATE_COUNT).first raise KernelCallError.new(:thread_set_state, r) if r!= 0 end |
.thread_set_state_raw(thread, state) ⇒ Object
Sets the register state of thread from a packed string containing it’s values.
kern_return_t thread_set_state
(thread_act_t target_thread,
thread_state_flavor_t flavor,
thread_state_t new_state,
target_thread new_state_count);
198 199 200 201 |
# File 'lib/ragweed/wraposx/thread_context.rb', line 198 def thread_set_state_raw(thread, state) r = CALLS["libc!thread_set_state:IIPI=I"].call(thread, I386_THREAD_STATE, state.to_ptr, I386_THREAD_STATE_COUNT).first raise KernelCallError.new(:thread_set_state, r) if r!= 0 end |
.thread_suspend(thread) ⇒ Object
Suspends a thread by id.
kern_return_t thread_suspend
(thread_act_t target_thread);
There is no man page for this function.
257 258 259 260 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 257 def thread_suspend(thread) r = CALLS["libc!thread_suspend:I=I"].call(thread).first raise KernelCallError.new(:thread_suspend, r) if r != 0 end |
.time ⇒ Object
time_t time(time_t *tloc);
see also time(3)
43 44 45 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 43 def time CALLS["libc!time:=I"].call.first end |
.version ⇒ Object
Returns the version string for the library.
15 16 17 |
# File 'lib/ragweed/wraposx.rb', line 15 def self.version VERSION end |
.vm_protect(task, addr, size, setmax, prot) ⇒ Object
Changes the protection state beginning at addr for size bytes to the mask prot. If setmax is true this will set the maximum permissions, otherwise it will set FIXME
kern_return_t vm_protect
(vm_task_t target_task,
vm_address_t address,
vm_size_t size,
boolean_t set_maximum,
vm_prot_t new_protection);
There is no man page for this function.
232 233 234 235 236 237 238 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 232 def vm_protect(task, addr, size, setmax, prot) addr = dl_bignum_to_ulong(addr) setmax = setmax ? 1 : 0 r = CALLS["libc!vm_protect:IPIII=I"].call(task,addr,size,setmax,prot).first raise KernelCallError.new(:vm_protect, r) if r != 0 return nil end |
.vm_read(task, addr, sz = 256) ⇒ Object
Reads sz bytes from task’s address space starting at addr.
kern_return_t vm_read_overwrite
(vm_task_t target_task,
vm_address_t address,
vm_size_t size,
vm_address_t *data_out,
mach_msg_type_number_t *data_size);
There is no man page for this function.
194 195 196 197 198 199 200 201 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 194 def vm_read(task, addr, sz=256) addr = dl_bignum_to_ulong(addr) buf = ("\x00" * sz).to_ptr len = (sz.to_l32).to_ptr r = CALLS["libc!vm_read_overwrite:IPIPP=I"].call(task, addr, sz, buf, len).first raise KernelCallError.new(:vm_read, r) if r != 0 return buf.to_str(len.to_str(4).to_l32) end |
.vm_region_raw(task, address, flavor) ⇒ Object
Returns a string containing the memory region information for task at address. Currently Apple only supports the basic flavor. The other two flavors are included for completeness.
kern_return_t vm_region
(vm_task_t target_task,
vm_address_t address,
vm_size_t size,
vm_region_flavor_t flavor,
vm_region_info_t info,
mach_msg_type_number_t info_count,
memory_object_name_t object_name);
239 240 241 242 243 244 245 246 247 248 |
# File 'lib/ragweed/wraposx/region_info.rb', line 239 def vm_region_raw(task, address, flavor) info = ("\x00"*64).to_ptr count = ([Vm::FLAVORS[flavor][:count]].pack("I_")).to_ptr address = ([address].pack("L_")).to_ptr objn = ([0].pack("I_")).to_ptr sz = ("\x00"*SIZEOFINT).to_ptr r = CALLS["libc!vm_region:IPPIPPP=I"].call(task, address, sz, flavor, info, count, objn).first raise KernelCallError.new(:vm_region, r) if r != 0 return "#{info.to_s(Vm::FLAVORS[flavor][:size])}#{address.to_s(SIZEOFLONG)}#{sz.to_s(SIZEOFINT)}" end |
.vm_write(task, addr, val) ⇒ Object
Writes val to task’s memory space at address addr. It is necessary for val.size to report the size of val in bytes
kern_return_t vm_write
(vm_task_t target_task,
vm_address_t address,
pointer_t data,
mach_msg_type_number_t data_count);
There is no man page for this function.
213 214 215 216 217 218 219 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 213 def vm_write(task, addr, val) addr = dl_bignum_to_ulong(addr) val = val.to_ptr r = CALLS["libc!vm_write:IPPI=I"].call(task, addr, val, val.size).first raise KernelCallError.new(:vm_write, r) if r != 0 return nil end |
.wait ⇒ Object
Oringially coded for use in debuggerosx but I’ve switched to waitpid for usability and debugging purposes.
Returns status of child when child recieves a signal.
pid_t wait(int *stat_loc);
see also wait(2)
80 81 82 83 84 85 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 80 def wait status = ("\x00"*SIZEOFINT).to_ptr r = CALLS["libc!wait:=I"].call(status).first raise SystemCallError.new("wait", DL.last_error) if r== -1 return status.to_s(SIZEOFINT).unpack('i_').first end |
.waitpid(pid, opt = 1) ⇒ Object
The wait used in debuggerosx. opt is an OR of the options to be used.
Returns an array. The first element is the pid of the child process as returned by the waitpid system call. The second, the status as an integer of that pid.
pid_t waitpid(pid_t pid, int *stat_loc, int options);
see also wait(2)
98 99 100 101 102 103 104 105 |
# File 'lib/ragweed/wraposx/wraposx.rb', line 98 def waitpid(pid, opt=1) pstatus = ("\x00"*SIZEOFINT).to_ptr r = CALLS["libc!waitpid:IPI=I"].call(pid, pstatus, opt).first raise SystemCallError.new("waitpid", DL.last_error) if r== -1 # maybe I should return a Hash? return [r, pstatus.to_s(SIZEOFINT).unpack('i_').first] end |