From: Heesob Park Date: 2008-08-26T10:59:16+09:00 Subject: Re: Unraveling binary data out of the proc filesystem on Solaris Hi, 2008/8/26 Daniel Berger : > Hi all, > > Ruby 1.8.6 > Solaris 10 > > I'm trying to get process information on a Solaris using pure Ruby. > For the basic information, this is fairly straightforward, as I read > out of /proc//psinfo. > > However, where I'm having trouble is getting the command line > arguments out of /proc//as. Basically, I need to know how to > unravel the data I'm reading into a human readable string. > > Here's some sample code: > > # sunos.rb > module Sys > class ProcTable > def self.ps(pid = nil) > Dir.foreach("/proc") do |file| > next if file =~ /\D/ > next if pid && file.to_i != pid > > psinfo = IO.read("/proc/#{file}/psinfo") > > pid = psinfo[8,4].unpack("L")[0] > puts "PID: #{pid}" > > argc = psinfo[188,4].unpack("L")[0] # pr_argc > addr = psinfo[192,4].unpack("L")[0] # pr_argv > > size = argc * 4 # 4 is the sizeof(caddr32_t) > asinfo = IO.read("/proc/#{file}/as", size, addr) > > # How do I unravel asinfo? > p asinfo > end > end > end > end > > if $0 == __FILE__ > include Sys > ProcTable.ps(2764) # or whatever pid you prefer > end > > The C code I'm trying to simulate, which I pulled from a post by Roger > Faulkner on comp.unix.questions, looks something like this: > > addr_args = p.pr_argv; /* from the psinfo struct */ > arg_count = p.pr_argc; /* from the psinfo struct */ > > if((fd = open(as_file, O_RDONLY)) < 0){ > /* Do nothing - you can only get info on processes you rights to */ > } > else > { > arg_vec = malloc(arg_count * sizeof(uintptr_t)); > (void)pread(fd, arg_vec, arg_count * sizeof (uintptr_t), > addr_args); > > arg_len = 16; > arg = malloc(arg_len+1); > > for(i = 0; i < arg_count; i++) { > if(pread(fd, arg, arg_len, arg_vec[i]) < 0) > continue; > > arg[arg_len] = '\0'; > if(strlen(arg) == arg_len){ > arg_len *= 2; > arg = realloc(arg, arg_len + 1); > i--; > continue; > } > rb_ary_push(v_cmd_array, rb_str_new2(arg)); > } > free(arg); > free(arg_vec); > } > > close(fd); > > Any ideas how to get the string(s) I need out of /proc//as ? > Roger Faulkner mentioned in the com.unix.solraris like this: /proc//as is not your ordinary sparse file. Attempts to read from non-existent portions of it yield a zero read(). The accessible portions of the as file are described by the /proc//map file. Reading the map file gives you an array of structures describing the legitimate addresses in the process. Read (and re-read) the proc(4) man page documentation Refer to http://unix.derkeiler.com/Newsgroups/comp.unix.solaris/2003-05/3189.html According to the man page proc(4): as Contains the address-space image of the process; it can be opened for both reading and writing. lseek(2) is used to position the file at the virtual address of interest and then the address space can be examined or changed through read(2) or write(2) (or by using pread(2) or pwrite(2) for the combined operation). According to the man page pread(2): The pread() function performs the same action as read(), except that it reads from a given position in the file without changing the file pointer. The first three arguments to pread() are the same as read() with the addition of a fourth argument offset for the desired position inside the file. pread() will read up to the maximum offset value that can be represented in an off_t for regular files. An attempt to perform a pread() on a file that is incapable of seeking results in an error. I guess you should use lseek and read combination. HTH, Park Heesob