sys-proctable 0.9.1-universal-solaris

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,175 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/testtask'
4
+ require 'rbconfig'
5
+ include Config
6
+
7
+ CLEAN.include(
8
+ '**/*.core', # Core dump files
9
+ '**/*.gem', # Gem files
10
+ '**/*.rbc', # Rubinius
11
+ '**/*.o', # C object file
12
+ '**/*.log', # Ruby extension build log
13
+ '**/Makefile', # C Makefile
14
+ '**/conftest.dSYM', # OS X build directory
15
+ "**/*.#{CONFIG['DLEXT']}" # C shared object
16
+ )
17
+
18
+ desc 'Build the sys-proctable library for C versions of sys-proctable'
19
+ task :build => [:clean] do
20
+ case Config::CONFIG['host_os']
21
+ when /bsd/i
22
+ dir = 'ext/bsd'
23
+ when /darwin/i
24
+ dir = 'ext/darwin'
25
+ when /hpux/i
26
+ dir = 'ext/hpux'
27
+ end
28
+
29
+ unless Config::CONFIG['host_os'] =~ /win32|mswin|dos|cygwin|mingw|windows|linux|sunos|solaris/i
30
+ Dir.chdir(dir) do
31
+ ruby 'extconf.rb'
32
+ sh 'make'
33
+ cp 'proctable.' + Config::CONFIG['DLEXT'], 'sys'
34
+ end
35
+ end
36
+ end
37
+
38
+ desc 'Install the sys-proctable library'
39
+ task :install => [:build] do
40
+ file = nil
41
+ dir = File.join(Config::CONFIG['sitelibdir'], 'sys')
42
+
43
+ Dir.mkdir(dir) unless File.exists?(dir)
44
+
45
+ case Config::CONFIG['host_os']
46
+ when /mswin|win32|msdos|cygwin|mingw|windows/i
47
+ file = 'lib/windows/sys/proctable.rb'
48
+ when /linux/i
49
+ file = 'lib/linux/sys/proctable.rb'
50
+ when /sunos|solaris/i
51
+ file = 'lib/sunos/sys/proctable.rb'
52
+ when /bsd/i
53
+ Dir.chdir('ext/bsd'){ sh 'make install' }
54
+ when /darwin/i
55
+ Dir.chdir('ext/darwin'){ sh 'make install' }
56
+ when /hpux/i
57
+ Dir.chdir('ext/hpux'){ sh 'make install' }
58
+ end
59
+
60
+ cp(file, dir, :verbose => true) if file
61
+ end
62
+
63
+ desc 'Uninstall the sys-proctable library'
64
+ task :uninstall do
65
+ case Config::CONFIG['host_os']
66
+ when /win32|mswin|dos|cygwin|mingw|windows|linux|sunos|solaris/i
67
+ dir = File.join(Config::CONFIG['sitelibdir'], 'sys')
68
+ file = File.join(dir, 'proctable.rb')
69
+ else
70
+ dir = File.join(Config::CONFIG['sitearchdir'], 'sys')
71
+ file = File.join(dir, 'proctable.' + Config::CONFIG['DLEXT'])
72
+ end
73
+
74
+ rm(file)
75
+ end
76
+
77
+ desc 'Run the benchmark suite'
78
+ task :bench => [:build] do
79
+ sh "ruby -Ilib benchmarks/bench_ps.rb"
80
+ end
81
+
82
+ desc 'Run the example program'
83
+ task :example => [:build] do
84
+ sh 'ruby -Ilib -Iext examples/example_ps.rb'
85
+ end
86
+
87
+ desc 'Run the test suite'
88
+ Rake::TestTask.new do |t|
89
+ task :test => :build
90
+ t.libs << 'test' << '.'
91
+
92
+ case Config::CONFIG['host_os']
93
+ when /mswin|msdos|cygwin|mingw|windows/i
94
+ t.test_files = FileList['test/test_sys_proctable_windows.rb']
95
+ t.libs << 'lib/windows'
96
+ when /linux/i
97
+ t.test_files = FileList['test/test_sys_proctable_linux.rb']
98
+ t.libs << 'lib/linux'
99
+ when /sunos|solaris/i
100
+ t.test_files = FileList['test/test_sys_proctable_sunos.rb']
101
+ t.libs << 'lib/sunos'
102
+ when /darwin/i
103
+ t.libs << 'ext/darwin'
104
+ t.test_files = FileList['test/test_sys_proctable_darwin.rb']
105
+ when /bsd/i
106
+ t.libs << 'ext/bsd'
107
+ t.test_files = FileList['test/test_sys_proctable_bsd.rb']
108
+ when /hpux/i
109
+ t.libs << 'ext/hpux'
110
+ t.test_files = FileList['test/test_sys_proctable_hpux.rb']
111
+ end
112
+ end
113
+
114
+ namespace :gem do
115
+ desc 'Create a gem'
116
+ task :create => [:clean] do
117
+ spec = eval(IO.read('sys-proctable.gemspec'))
118
+
119
+ # I've had to manually futz with the spec here in some cases
120
+ # in order to get the universal platform settings I want because
121
+ # of some bugginess in Rubygems' platform.rb.
122
+ #
123
+ case Config::CONFIG['host_os']
124
+ when /bsd/i
125
+ spec.platform = Gem::Platform.new('universal-bsd')
126
+ spec.files << 'ext/bsd/sys/proctable.c'
127
+ spec.extra_rdoc_files << 'ext/bsd/sys/proctable.c'
128
+ spec.test_files << 'test/test_sys_proctable_bsd.rb'
129
+ spec.extensions = ['ext/bsd/extconf.rb']
130
+ when /darwin/i
131
+ spec.platform = Gem::Platform.new('universal-darwin')
132
+ spec.files << 'ext/darwin/sys/proctable.c'
133
+ spec.extra_rdoc_files << 'ext/darwin/sys/proctable.c'
134
+ spec.test_files << 'test/test_sys_proctable_darwin.rb'
135
+ spec.extensions = ['ext/darwin/extconf.rb']
136
+ when /hpux/i
137
+ spec.platform = Gem::Platform.new('universal-hpux')
138
+ spec.files << 'ext/hpux/sys/proctable.c'
139
+ spec.extra_rdoc_files << 'ext/hpux/sys/proctable.c'
140
+ spec.test_files << 'test/test_sys_proctable_hpux.rb'
141
+ spec.extensions = ['ext/hpux/extconf.rb']
142
+ when /linux/i
143
+ spec.platform = Gem::Platform.new('universal-linux')
144
+ spec.require_paths = ['lib', 'lib/linux']
145
+ spec.files += ['lib/linux/sys/proctable.rb']
146
+ spec.test_files << 'test/test_sys_proctable_linux.rb'
147
+ when /sunos|solaris/i
148
+ spec.platform = Gem::Platform.new('universal-solaris10.0')
149
+ spec.platform.version = nil
150
+ spec.require_paths = ['lib', 'lib/sunos']
151
+ spec.files += ['lib/sunos/sys/proctable.rb']
152
+ spec.test_files << 'test/test_sys_proctable_sunos.rb'
153
+ when /mswin|win32|dos|cygwin|mingw|windows/i
154
+ spec.platform = Gem::Platform::CURRENT
155
+ spec.platform.cpu = 'universal'
156
+ spec.platform.version = nil
157
+ spec.require_paths = ['lib', 'lib/windows']
158
+ spec.files += ['lib/windows/sys/proctable.rb']
159
+ spec.test_files << 'test/test_sys_proctable_windows.rb'
160
+ end
161
+
162
+ # https://github.com/rubygems/rubygems/issues/147
163
+ spec.original_platform = spec.platform
164
+
165
+ Gem::Builder.new(spec).build
166
+ end
167
+
168
+ desc 'Install the sys-proctable library as a gem'
169
+ task :install => [:create] do
170
+ gem_name = Dir['*.gem'].first
171
+ sh "gem install #{gem_name}"
172
+ end
173
+ end
174
+
175
+ task :default => :test
@@ -0,0 +1,21 @@
1
+ ########################################################################
2
+ # bench_ps.rb
3
+ #
4
+ # Benchmark program to show overall speed and compare the block form
5
+ # versus the non-block form. You should run this benchmark via the
6
+ # 'rake bench' Rake task.
7
+ ########################################################################
8
+ require 'benchmark'
9
+ require 'sys/proctable'
10
+
11
+ MAX = 10
12
+
13
+ Benchmark.bm do |bench|
14
+ bench.report("Block form"){
15
+ MAX.times{ Sys::ProcTable.ps{} }
16
+ }
17
+
18
+ bench.report("Non-block form"){
19
+ MAX.times{ Sys::ProcTable.ps }
20
+ }
21
+ end
data/doc/top.txt ADDED
@@ -0,0 +1,47 @@
1
+ = Description
2
+ A simple 'top' interface for Ruby
3
+
4
+ = Prerequisites
5
+ Requires the "sys/proctable" package (which should be installed along
6
+ with this package).
7
+
8
+ = Synopsis
9
+ require "sys/top"
10
+
11
+ Sys::Top.top(5).each{ |ps|
12
+ p ps
13
+ }
14
+
15
+ = Constants
16
+ VERSION
17
+ Returns the version number of this package as a String.
18
+
19
+ = Class Methods
20
+ Sys::Top.top(number=10, field="pctcpu")
21
+ Returns an array of ProcTableStruct's. The size of the array (i.e. the
22
+ number of processes) that it returns is based on +number+, and sorted by
23
+ +pctcpu+. By default, the size and field values are 10 and "pctcpu",
24
+ respectively.
25
+
26
+ = Notes
27
+ Not all fields are available on all platforms. Please check your
28
+ platform specific documentation for which fields are available.
29
+
30
+ = Bugs
31
+ None that I'm aware of. Please log bug reports on the project page at
32
+ http://www.rubyforge.org/projects/sysutils
33
+
34
+ = License
35
+ Artistic 2.0
36
+
37
+ = Copyright
38
+ (C) 2004-2009 Daniel J. Berger
39
+ All Rights Reserved.
40
+
41
+ = Warranty
42
+ This package is provided "as is" and without any express or
43
+ implied warranties, including, without limitation, the implied
44
+ warranties of merchantability and fitness for a particular purpose.
45
+
46
+ = Author
47
+ Daniel J. Berger
@@ -0,0 +1,20 @@
1
+ #######################################################################
2
+ # example_ps.rb
3
+ #
4
+ # Generic test program that demonstrates the use of ProcTable.ps. You
5
+ # can run this via the 'rake example' task.
6
+ #
7
+ # Modify as you see fit
8
+ #######################################################################
9
+ require 'sys/proctable'
10
+ include Sys
11
+
12
+ puts "VERSION: " + ProcTable::VERSION
13
+ sleep 2
14
+
15
+ ProcTable.ps{ |s|
16
+ ProcTable.fields.each{ |field|
17
+ puts "#{field}: " + s.send(field).to_s
18
+ }
19
+ puts '=' * 30
20
+ }
@@ -0,0 +1,462 @@
1
+ ########################################################################
2
+ # proctable.rb
3
+ #
4
+ # A pure Ruby version of sys-proctable for SunOS 5.8 or later.
5
+ ########################################################################
6
+
7
+ # The Sys module serves as a namespace only.
8
+ module Sys
9
+
10
+ # The ProcTable class encapsulates process table information.
11
+ class ProcTable
12
+
13
+ class Error < StandardError; end
14
+
15
+ # There is no constructor
16
+ private_class_method :new
17
+
18
+ # The version of the sys-proctable library
19
+ VERSION = '0.9.1'
20
+
21
+ private
22
+
23
+ PRNODEV = -1 # non-existent device
24
+
25
+ @fields = [
26
+ :flag, # process flags (deprecated)
27
+ :nlwp, # number of active lwp's in the process
28
+ :pid, # unique process id
29
+ :ppid, # process id of parent
30
+ :pgid, # pid of session leader
31
+ :sid, # session id
32
+ :uid, # real user id
33
+ :euid, # effective user id
34
+ :gid, # real group id
35
+ :egid, # effective group id
36
+ :addr, # address of the process
37
+ :size, # size of process in kbytes
38
+ :rssize, # resident set size in kbytes
39
+ :ttydev, # tty device (or PRNODEV)
40
+ :pctcpu, # % of recent cpu used by all lwp's
41
+ :pctmem, # % of system memory used by process
42
+ :start, # absolute process start time
43
+ :time, # usr + sys cpu time for this process
44
+ :ctime, # usr + sys cpu time for reaped children
45
+ :fname, # name of the exec'd file
46
+ :psargs, # initial characters argument list - same as cmdline
47
+ :wstat, # if a zombie, the wait status
48
+ :argc, # initial argument count
49
+ :argv, # address of initial argument vector
50
+ :envp, # address of initial environment vector
51
+ :dmodel, # data model of the process
52
+ :taskid, # task id
53
+ :projid, # project id
54
+ :nzomb, # number of zombie lwp's in the process
55
+ :poolid, # pool id
56
+ :zoneid, # zone id
57
+ :contract, # process contract
58
+ :lwpid, # lwp id
59
+ :wchan, # wait address for sleeping lwp
60
+ :stype, # synchronization event type
61
+ :state, # numeric lwp state
62
+ :sname, # printable character for state
63
+ :nice, # nice for cpu usage
64
+ :syscall, # system call number (if in syscall)
65
+ :pri, # priority
66
+ :clname, # scheduling class name
67
+ :name, # name of system lwp
68
+ :onpro, # processor which last ran thsi lwp
69
+ :bindpro, # processor to which lwp is bound
70
+ :bindpset, # processor set to which lwp is bound
71
+ :count, # number of contributing lwp's
72
+ :tstamp, # current time stamp
73
+ :create, # process/lwp creation time stamp
74
+ :term, # process/lwp termination time stamp
75
+ :rtime, # total lwp real (elapsed) time
76
+ :utime, # user level cpu time
77
+ :stime, # system call cpu time
78
+ :ttime, # other system trap cpu time
79
+ :tftime, # text page fault sleep time
80
+ :dftime, # text page fault sleep time
81
+ :kftime, # kernel page fault sleep time
82
+ :ltime, # user lock wait sleep time
83
+ :slptime, # all other sleep time
84
+ :wtime, # wait-cpu (latency) time
85
+ :stoptime, # stopped time
86
+ :minf, # minor page faults
87
+ :majf, # major page faults
88
+ :nswap, # swaps
89
+ :inblk, # input blocks
90
+ :oublk, # output blocks
91
+ :msnd, # messages sent
92
+ :mrcv, # messages received
93
+ :sigs, # signals received
94
+ :vctx, # voluntary context switches
95
+ :ictx, # involuntary context switches
96
+ :sysc, # system calls
97
+ :ioch, # chars read and written
98
+ :path, # array of symbolic link paths from /proc/<pid>/path
99
+ :contracts, # array symbolic link paths from /proc/<pid>/contracts
100
+ :fd, # array of used file descriptors
101
+ :cmd_args, # array of command line arguments
102
+ :environ, # hash of environment associated with the process,
103
+ :cmdline # joined cmd_args if present, otherwise psargs
104
+ ]
105
+
106
+ @psinfo_pack_directive = [
107
+ 'i', # pr_flag
108
+ 'i', # pr_nlwp
109
+ 'i', # pr_pid
110
+ 'i', # pr_ppid
111
+ 'i', # pr_pgid
112
+ 'i', # pr_sid
113
+ 'i', # pr_uid
114
+ 'i', # pr_euid
115
+ 'i', # pr_gid
116
+ 'i', # pr_egid
117
+ 'L', # pr_addr
118
+ 'L', # pr_size
119
+ 'L', # pr_rssize
120
+ 'L', # pr_pad1
121
+ 'i', # pr_ttydev
122
+ 'S', # pr_pctcpu
123
+ 'S', # pr_pctmem
124
+ 'LL', # pr_start
125
+ 'LL', # pr_time
126
+ 'LL', # pr_ctime
127
+ 'A16', # pr_fname[PRFNSZ]
128
+ 'A80', # pr_psargs[PRARGSZ]
129
+ 'i', # pr_wstat
130
+ 'i', # pr_argc
131
+ 'L', # pr_argv
132
+ 'L', # pr_envp
133
+ 'C', # pr_dmodel
134
+ 'A3', # pr_pad2[3]
135
+ 'i', # pr_taskid
136
+ 'i', # pr_projid
137
+ 'i', # pr_nzomb
138
+ 'i', # pr_poolid
139
+ 'i', # pr_zoneid
140
+ 'i', # pr_contract
141
+ 'i', # pr_filler
142
+ # --- LWPSINFO ---
143
+ 'i', # pr_flag
144
+ 'i', # pr_lwpid
145
+ 'L', # pr_addr
146
+ 'L', # pr_wchan
147
+ 'C', # pr_stype
148
+ 'C', # pr_state
149
+ 'A', # pr_sname
150
+ 'C', # pr_nice
151
+ 's', # pr_syscall
152
+ 'C', # pr_oldpri
153
+ 'C', # pr_cpu
154
+ 'i', # pr_pri
155
+ 'S', # pr_pctcpu
156
+ 'S', # pr_pad
157
+ 'LL', # pr_start
158
+ 'LL', # pr_time
159
+ 'A8', # pr_clname[PRCLSZ]
160
+ 'A16', # pr_name[PRFNSZ]
161
+ 'i', # pr_onpro
162
+ 'i', # pr_bindpro
163
+ 'i', # pr_bindpset
164
+ ].join
165
+
166
+ @prusage_pack_directive = [
167
+ 'i', # pr_lwpid
168
+ 'i', # pr_count
169
+ 'L2', # pr_tstamp
170
+ 'L2', # pr_create
171
+ 'L2', # pr_term
172
+ 'L2', # pr_rtime
173
+ 'L2', # pr_utime
174
+ 'L2', # pr_stime
175
+ 'L2', # pr_ttime
176
+ 'L2', # pr_tftime
177
+ 'L2', # pr_dftime
178
+ 'L2', # pr_kftime
179
+ 'L2', # pr_ltime
180
+ 'L2', # pr_slptime
181
+ 'L2', # pr_wtime
182
+ 'L2', # pr_stoptime
183
+ 'L12', # pr_filltime
184
+ 'L', # pr_minf
185
+ 'L', # pr_majf
186
+ 'L', # pr_nswap
187
+ 'L', # pr_inblk
188
+ 'L', # pr_oublk
189
+ 'L', # pr_msnd
190
+ 'L', # pr_mrcv
191
+ 'L', # pr_sigs
192
+ 'L', # pr_vctx
193
+ 'L', # pr_ictx
194
+ 'L', # pr_sysc
195
+ 'L', # pr_ioch
196
+ ].join
197
+
198
+ public
199
+
200
+ ProcTableStruct = Struct.new("ProcTableStruct", *@fields) do
201
+ alias comm fname
202
+ end
203
+
204
+ # In block form, yields a ProcTableStruct for each process entry that you
205
+ # have rights to. This method returns an array of ProcTableStruct's in
206
+ # non-block form.
207
+ #
208
+ # If a +pid+ is provided, then only a single ProcTableStruct is yielded or
209
+ # returned, or nil if no process information is found for that +pid+.
210
+ #
211
+ # Example:
212
+ #
213
+ # # Iterate over all processes
214
+ # ProcTable.ps do |proc_info|
215
+ # p proc_info
216
+ # end
217
+ #
218
+ # # Print process table information for only pid 1001
219
+ # p ProcTable.ps(1001)
220
+ #
221
+ def self.ps(pid = nil)
222
+ raise TypeError unless pid.is_a?(Fixnum) if pid
223
+
224
+ array = block_given? ? nil : []
225
+ struct = nil
226
+
227
+ Dir.foreach("/proc") do |file|
228
+ next if file =~ /\D/ # Skip non-numeric entries under /proc
229
+
230
+ # Only return information for a given pid, if provided
231
+ if pid
232
+ next unless file.to_i == pid
233
+ end
234
+
235
+ # Skip over any entries we don't have permissions to read
236
+ next unless File.readable?("/proc/#{file}/psinfo")
237
+
238
+ psinfo = IO.read("/proc/#{file}/psinfo") rescue next
239
+
240
+ psinfo_array = psinfo.unpack(@psinfo_pack_directive)
241
+
242
+ struct = ProcTableStruct.new
243
+
244
+ struct.flag = psinfo_array[0] # pr_flag
245
+ struct.nlwp = psinfo_array[1] # pr_nlwp
246
+ struct.pid = psinfo_array[2] # pr_pid
247
+ struct.ppid = psinfo_array[3] # pr_ppid
248
+ struct.pgid = psinfo_array[4] # pr_pgid
249
+ struct.sid = psinfo_array[5] # pr_sid
250
+ struct.uid = psinfo_array[6] # pr_uid
251
+ struct.euid = psinfo_array[7] # pr_euid
252
+ struct.gid = psinfo_array[8] # pr_gid
253
+ struct.egid = psinfo_array[9] # pr_egid
254
+ struct.addr = psinfo_array[10] # pr_addr
255
+ struct.size = psinfo_array[11] * 1024 # pr_size (in bytes)
256
+ struct.rssize = psinfo_array[12] * 1024 # pr_rssize (in bytes)
257
+
258
+ # skip pr_pad1
259
+
260
+ struct.ttydev = psinfo_array[14] # pr_ttydev
261
+ struct.pctcpu = (psinfo_array[15] * 100).to_f / 0x8000 # pr_pctcpu
262
+ struct.pctmem = (psinfo_array[16] * 100).to_f / 0x8000 # pr_pctmem
263
+
264
+ struct.start = Time.at(psinfo_array[17]) # pr_start (tv_sec)
265
+ struct.time = psinfo_array[19] # pr_time (tv_sec)
266
+ struct.ctime = psinfo_array[21] # pr_ctime (tv_sec)
267
+
268
+ struct.fname = psinfo_array[23] # pr_fname
269
+ struct.psargs = psinfo_array[24] # pr_psargs
270
+ struct.wstat = psinfo_array[25] # pr_wstat
271
+ struct.argc = psinfo_array[26] # pr_argc
272
+ struct.argv = psinfo_array[27] # pr_argv
273
+ struct.envp = psinfo_array[28] # pr_envp
274
+ struct.dmodel = psinfo_array[29] # pr_dmodel
275
+
276
+ # skip pr_pad2
277
+
278
+ struct.taskid = psinfo_array[31] # pr_taskid
279
+ struct.projid = psinfo_array[32] # pr_projid
280
+ struct.nzomb = psinfo_array[33] # pr_nzomb
281
+ struct.poolid = psinfo_array[34] # pr_poolid
282
+ struct.zoneid = psinfo_array[35] # pr_zoneid
283
+ struct.contract = psinfo_array[36] # pr_contract
284
+
285
+ # skip pr_filler
286
+
287
+ ### LWPSINFO struct info
288
+
289
+ # skip pr_flag
290
+
291
+ struct.lwpid = psinfo_array[39] # pr_lwpid
292
+
293
+ # skip pr_addr
294
+
295
+ struct.wchan = psinfo_array[41] # pr_wchan
296
+ struct.stype = psinfo_array[42] # pr_stype
297
+ struct.state = psinfo_array[43] # pr_state
298
+ struct.sname = psinfo_array[44] # pr_sname
299
+ struct.nice = psinfo_array[45] # pr_nice
300
+ struct.syscall = psinfo_array[46] # pr_syscall
301
+
302
+ # skip pr_oldpri
303
+ # skip pr_cpu
304
+
305
+ struct.pri = psinfo_array[49] # pr_pri
306
+
307
+ # skip pr_pctcpu
308
+ # skip pr_pad
309
+ # skip pr_start
310
+ # skip pr_time
311
+
312
+ struct.clname = psinfo_array[56] # pr_clname
313
+ struct.name = psinfo_array[57] # pr_name
314
+ struct.onpro = psinfo_array[58] # pr_onpro
315
+ struct.bindpro = psinfo_array[59] # pr_bindpro
316
+ struct.bindpset = psinfo_array[60] # pr_bindpset
317
+
318
+ # Get the full command line out of /proc/<pid>/as.
319
+ begin
320
+ File.open("/proc/#{file}/as") do |fd|
321
+ fd.sysseek(struct.argv, IO::SEEK_SET)
322
+ address = fd.sysread(struct.argc * 4).unpack("L")[0]
323
+
324
+ struct.cmd_args = []
325
+
326
+ 0.upto(struct.argc - 1){ |i|
327
+ fd.sysseek(address, IO::SEEK_SET)
328
+ data = fd.sysread(128)[/^[^\0]*/] # Null strip
329
+ struct.cmd_args << data
330
+ address += data.length + 1 # Add 1 for the space
331
+ }
332
+
333
+ # Get the environment hash associated with the process.
334
+ struct.environ = {}
335
+
336
+ fd.sysseek(struct.envp, IO::SEEK_SET)
337
+
338
+ env_address = fd.sysread(128).unpack("L")[0]
339
+
340
+ # TODO: Optimization potential here.
341
+ loop do
342
+ fd.sysseek(env_address, IO::SEEK_SET)
343
+ data = fd.sysread(1024)[/^[^\0]*/] # Null strip
344
+ break if data.empty?
345
+ key, value = data.split('=')
346
+ struct.environ[key] = value
347
+ env_address += data.length + 1 # Add 1 for the space
348
+ end
349
+ end
350
+ rescue Errno::EACCES, Errno::EOVERFLOW, EOFError
351
+ # Skip this if we don't have proper permissions, if there's
352
+ # no associated environment, or if there's a largefile issue.
353
+ rescue Errno::ENOENT
354
+ next # The process has terminated. Bail out!
355
+ end
356
+
357
+ ### struct prusage
358
+
359
+ begin
360
+ prusage = 0.chr * 512
361
+ prusage = IO.read("/proc/#{file}/usage")
362
+
363
+ prusage_array = prusage.unpack(@prusage_pack_directive)
364
+
365
+ # skip pr_lwpid
366
+ struct.count = prusage_array[1]
367
+ struct.tstamp = prusage_array[2]
368
+ struct.create = prusage_array[4]
369
+ struct.term = prusage_array[6]
370
+ struct.rtime = prusage_array[8]
371
+ struct.utime = prusage_array[10]
372
+ struct.stime = prusage_array[12]
373
+ struct.ttime = prusage_array[14]
374
+ struct.tftime = prusage_array[16]
375
+ struct.dftime = prusage_array[18]
376
+ struct.kftime = prusage_array[20]
377
+ struct.ltime = prusage_array[22]
378
+ struct.slptime = prusage_array[24]
379
+ struct.wtime = prusage_array[26]
380
+ struct.stoptime = prusage_array[28]
381
+ # skip filltime
382
+ struct.minf = prusage_array[42]
383
+ struct.majf = prusage_array[43]
384
+ struct.nswap = prusage_array[44]
385
+ struct.inblk = prusage_array[45]
386
+ struct.oublk = prusage_array[46]
387
+ struct.msnd = prusage_array[47]
388
+ struct.mrcv = prusage_array[48]
389
+ struct.sigs = prusage_array[49]
390
+ struct.vctx = prusage_array[50]
391
+ struct.ictx = prusage_array[51]
392
+ struct.sysc = prusage_array[52]
393
+ struct.ioch = prusage_array[53]
394
+ rescue Errno::EACCES
395
+ # Do nothing if we lack permissions. Just move on.
396
+ rescue Errno::ENOENT
397
+ next # The process has terminated. Bail out!
398
+ end
399
+
400
+ # Information from /proc/<pid>/path. This is represented as a hash,
401
+ # with the symbolic link name as the key, and the file it links to
402
+ # as the value, or nil if it cannot be found.
403
+ #--
404
+ # Note that cwd information can be gathered from here, too.
405
+ struct.path = {}
406
+
407
+ Dir["/proc/#{file}/path/*"].each{ |entry|
408
+ link = File.readlink(entry) rescue nil
409
+ struct.path[File.basename(entry)] = link
410
+ }
411
+
412
+ # Information from /proc/<pid>/contracts. This is represented as
413
+ # a hash, with the symbolic link name as the key, and the file
414
+ # it links to as the value.
415
+ struct.contracts = {}
416
+
417
+ Dir["/proc/#{file}/contracts/*"].each{ |entry|
418
+ link = File.readlink(entry) rescue nil
419
+ struct.contracts[File.basename(entry)] = link
420
+ }
421
+
422
+ # Information from /proc/<pid>/fd. This returns an array of
423
+ # numeric file descriptors used by the process.
424
+ struct.fd = Dir["/proc/#{file}/fd/*"].map{ |f| File.basename(f).to_i }
425
+
426
+ # Use the cmd_args as the cmdline if available. Otherwise use
427
+ # the psargs. This struct member is provided to provide a measure
428
+ # of consistency with the other platform implementations.
429
+ if struct.cmd_args && struct.cmd_args.length > 0
430
+ struct.cmdline = struct.cmd_args.join(' ')
431
+ else
432
+ struct.cmdline = struct.psargs
433
+ end
434
+
435
+ # This is read-only data
436
+ struct.freeze
437
+
438
+ if block_given?
439
+ yield struct
440
+ else
441
+ array << struct
442
+ end
443
+ end
444
+
445
+ pid ? struct : array
446
+ end
447
+
448
+ # Returns an array of fields that each ProcTableStruct will contain. This
449
+ # may be useful if you want to know in advance what fields are available
450
+ # without having to perform at least one read of the /proc table.
451
+ #
452
+ # Example:
453
+ #
454
+ # Sys::ProcTable.fields.each{ |field|
455
+ # puts "Field: #{field}"
456
+ # }
457
+ #
458
+ def self.fields
459
+ @fields.map{ |f| f.to_s }
460
+ end
461
+ end
462
+ end