sys-proctable 0.7.6 → 1.2.0

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 (52) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -0
  4. data/CHANGES +165 -0
  5. data/MANIFEST +33 -41
  6. data/README +115 -135
  7. data/Rakefile +94 -0
  8. data/benchmarks/bench_ps.rb +21 -0
  9. data/doc/top.txt +5 -11
  10. data/examples/example_ps.rb +20 -0
  11. data/lib/aix/sys/proctable.rb +458 -0
  12. data/lib/darwin/sys/proctable.rb +363 -0
  13. data/lib/freebsd/sys/proctable.rb +363 -0
  14. data/lib/linux/sys/proctable.rb +314 -0
  15. data/lib/linux/sys/proctable/cgroup_entry.rb +50 -0
  16. data/lib/linux/sys/proctable/smaps.rb +118 -0
  17. data/lib/sunos/sys/proctable.rb +456 -0
  18. data/lib/sys-proctable.rb +1 -0
  19. data/lib/sys-top.rb +1 -0
  20. data/lib/sys/proctable.rb +18 -0
  21. data/lib/sys/proctable/version.rb +6 -0
  22. data/lib/sys/top.rb +28 -19
  23. data/lib/windows/sys/proctable.rb +208 -0
  24. data/spec/sys_proctable_aix_spec.rb +328 -0
  25. data/spec/sys_proctable_all_spec.rb +89 -0
  26. data/spec/sys_proctable_darwin_spec.rb +120 -0
  27. data/spec/sys_proctable_freebsd_spec.rb +210 -0
  28. data/spec/sys_proctable_linux_spec.rb +310 -0
  29. data/spec/sys_proctable_sunos_spec.rb +316 -0
  30. data/spec/sys_proctable_windows_spec.rb +317 -0
  31. data/spec/sys_top_spec.rb +51 -0
  32. data/sys-proctable.gemspec +38 -0
  33. metadata +140 -64
  34. metadata.gz.sig +0 -0
  35. data/doc/freebsd.txt +0 -90
  36. data/doc/hpux.txt +0 -77
  37. data/doc/linux.txt +0 -85
  38. data/doc/solaris.txt +0 -99
  39. data/doc/windows.txt +0 -122
  40. data/ext/extconf.rb +0 -98
  41. data/ext/sunos/sunos.c +0 -374
  42. data/ext/sunos/sunos.h +0 -177
  43. data/ext/version.h +0 -2
  44. data/test/tc_all.rb +0 -59
  45. data/test/tc_freebsd.rb +0 -45
  46. data/test/tc_hpux.rb +0 -49
  47. data/test/tc_kvm_bsd.rb +0 -31
  48. data/test/tc_linux.rb +0 -45
  49. data/test/tc_sunos.rb +0 -52
  50. data/test/tc_top.rb +0 -26
  51. data/test/tc_windows.rb +0 -40
  52. data/test/test_memleak.rb +0 -54
@@ -1,85 +0,0 @@
1
- = Description
2
- sys-proctable
3
-
4
- A Ruby version of the 'ps' command. This is a C extension, not parsed
5
- output. For Linux, process information is read out of /proc.
6
-
7
- = Synopsis
8
- require 'sys/proctable'
9
- include Sys
10
-
11
- # Everything
12
- ProcTable.ps{ |p|
13
- puts p.pid.to_s
14
- puts p.comm
15
- ...
16
- }
17
-
18
- or
19
-
20
- # Just one process
21
- p = ProcTable.ps(2123)
22
- puts p.pid.to_s
23
- puts p.comm
24
- ...
25
-
26
- or
27
-
28
- # Return the results as an array of ProcTableStructs
29
- a = ProcTable.ps()
30
- a.each do |p|
31
- puts a.pid
32
- ...
33
- end
34
-
35
- = Constants
36
- VERSION
37
- Returns the current version number for this package (as a string).
38
-
39
- = Class Methods
40
- ProcTable.fields
41
- Returns an array of fields available on the current OS.
42
-
43
- ProcTable.ps(pid=nil)
44
- ProcTable.ps{ |s| ... }
45
- If no pid's or processes are included as arguments, in block form it
46
- returns a struct of type ProcTableStruct for every process in the proc
47
- table. Otherwise it returns an array of ProcTableStruct's.
48
-
49
- If a process id is provided, a single ProcTable struct is returned, or
50
- nil if the pid is not found.
51
-
52
- = Exception Classes
53
- ProcTableError < StandardError
54
- Raised if the /proc field is unreadable and/or unmounted.
55
-
56
- = Supported fields
57
- You can view the supported fields with the "fields()" class method.
58
-
59
- = Future Plans
60
- Create a pure Ruby version as an alternative.
61
- Change the ttynum field to ttydev and return a string instead of an int.
62
-
63
- = Known Bugs
64
- None known. Please log any bugs on the project page at
65
- http://www.rubyforge.org/projects/sysutils
66
-
67
- = License
68
- Ruby's
69
-
70
- = Copyright
71
- (C) 2003-2006 Daniel J. Berger
72
- All Rights Reserved
73
-
74
- = Warranty
75
- This package is provided "as is" and without any express or
76
- implied warranties, including, without limitation, the implied
77
- warranties of merchantability and fitness for a particular purpose.
78
-
79
- = Author
80
- Daniel J. Berger
81
- djberg96 at nospam at gmail dot com
82
- rubyhacker1 on IRC (Freenode)
83
-
84
- = See Also
85
- ps, proc(5)
@@ -1,99 +0,0 @@
1
- = Description
2
- sys-proctable
3
-
4
- A Ruby version of the 'ps' command. This is a C extension, not parsed
5
- output. For Solaris, data is read out of /proc via the psinfo struct.
6
-
7
- = Synopsis
8
- require 'sys/proctable'
9
- include Sys
10
-
11
- # Everything
12
- ProcTable.ps{ |p|
13
- puts p.pid.to_s
14
- puts p.comm
15
- ...
16
- }
17
-
18
- or
19
-
20
- # Just one process
21
- s = ProcTable.ps(2123)
22
- puts s.pid.to_s
23
- puts s.comm
24
- ...
25
-
26
- # Return the results as an array of ProcTableStructs
27
- a = ProcTable.ps
28
- a.each do |p|
29
- puts a.pid
30
- ...
31
- end
32
-
33
- = Constants
34
- VERSION
35
- Returns the current version number for this package (as a string).
36
-
37
- = Class Methods
38
- ProcTable.fields
39
- Returns an array of fields available on the current OS.
40
-
41
- ProcTable.ps(pid=nil)
42
- ProcTable.ps{ |s| ... }
43
- If no pid is included as an argument, in block form it
44
- returns a struct of type ProcTableStruct for every process in the proc
45
- table. Otherwise it returns an array of ProcTable struct's. If a pid
46
- is provided it will return a single ProcTable struct for that pid, or
47
- nil if it is not found.
48
-
49
- = Exception Classes
50
- ProcTableError < StandardError
51
- Raised if the /proc directory is unreadable and/or unmounted.
52
-
53
- = Supported fields
54
- You can view the supported fields with the "fields()" class method.
55
-
56
- = Future Plans
57
- Return a more meaningful result for the wchan member (2.6+).
58
- Add env info where possible.
59
-
60
- = Notes
61
- The "comm" field isn't really part of the psinfo struct. It is just a copy
62
- (i.e. is identical to) the "fname" field. I added it to provide a degree
63
- of consistency between all of the platforms. I will also make a point
64
- of adding it to any future platform releases.
65
-
66
- The cmdline string is limited to 80 characters, except for those processes
67
- which you (or your program) own.
68
-
69
- The ttydev field is, for now, an integer. If there is no associated tty with
70
- the process, a -1 is returned. In the future, this field will be changed to
71
- a string (i.e. the actual device name).
72
-
73
- I suppose I *could* add a -lkvm version for Solaris (this is what Dan Urist
74
- is now using in Proc::ProcessTable) but I haven't found a compelling reason
75
- to do so. If you think you have one, please let me know.
76
-
77
- = Known Bugs
78
- None that I am aware of. Please log any bugs on the RubyForge project page at
79
- http://www.rubyforge.org/projects/sysutils
80
-
81
- = License
82
- Ruby's
83
-
84
- = Copyright
85
- (C) 2003-2006 Daniel J. Berger
86
- All Rights Reserved.
87
-
88
- = Warranty
89
- This package is provided "as is" and without any express or
90
- implied warranties, including, without limitation, the implied
91
- warranties of merchantability and fitness for a particular purpose.
92
-
93
- = Author
94
- Daniel J. Berger
95
- djberg96 at nospam at gmail dot com
96
- imperator on IRC (Freenode)
97
-
98
- = See Also
99
- ps, proc
@@ -1,122 +0,0 @@
1
- = Description
2
- A Ruby interface for gathering process information. For MS Windows,
3
- the process information is gathered via OLE + WMI, using pure Ruby.
4
-
5
- = Synopsis
6
- require 'sys/proctable'
7
- include Sys
8
-
9
- # Everything
10
- ProcTable.ps{ |p|
11
- puts p.pid.to_s
12
- puts p.comm
13
- ...
14
- }
15
-
16
- or
17
-
18
- # A single pid
19
- p = ProcTable.ps(1234)
20
- puts p.pid.to_s
21
- puts p.comm
22
- ...
23
-
24
- or
25
-
26
- # Return the results as an array of ProcTableStructs
27
- a = ProcTable.ps
28
- a.each do |p|
29
- puts a.pid
30
- ...
31
- end
32
-
33
- = Constants
34
- VERSION
35
- Returns the current version number for this package (as a string).
36
-
37
- = Class Methods
38
- ProcTable.fields
39
- Returns an Array of fields available on the current OS in the
40
- ProcTableStruct.
41
-
42
- ProcTable.ps(pid=nil, host='localhost')
43
- ProcTable.ps{ |s| ... }
44
- Returns a struct of type ProcTableStruct for every process in the proc
45
- table in block form. Otherwise it returns an array of ProcTableStruct's.
46
-
47
- If 'pid' is provided, then only a struct for that pid is returned, or
48
- nil if it is not found.
49
-
50
- If 'host' is provided, then processes from that host are gathered. By
51
- default, process information is gathered on the local host.
52
-
53
- = Supported fields
54
- The currently supported fields for MS Windows (i.e. your ProcTable struct
55
- members) are:
56
-
57
- caption, cmdline, comm, creation_class_name, creation_date,
58
- cs_creation_class_name, cs_name, description, executable_path,
59
- execution_state, handle, handle_count, install_date, kernel_mode_time,
60
- maximum_working_set_size, minimum_working_set_size, name,
61
- os_creation_class_name, os_name, other_operation_count,
62
- other_transfer_count, page_faults, page_file_usage, peak_virtual_size,
63
- ppid, peak_working_set_size, priority, private_page_count, pid,
64
- quota_non_paged_pool_usage, quota_paged_pool_usage,
65
- quota_peak_non_paged_pool_usage, quota_non_paged_pool_usage,
66
- read_operation_count, read_transfer_count, session_id,
67
- termination_date, thread_count, user_mode_time, virtual_size,
68
- windows_version, working_set_size, write_operation_count,
69
- write_transfer_count
70
-
71
- You can also view them with the fields() class method.
72
-
73
- = Notes
74
- For the sake of attempting to provide a somewhat common API, the 'comm'
75
- and 'cmdline' fields have been included as part of the structure. The
76
- 'comm' member corresponds to the Name attribute of Win32_Process. The
77
- 'cmdline' attribute corresponds to either the Executable_Path attribute
78
- (on Windows 2000 or earlier) or the CommandLine attribute (on Windows XP
79
- and later).
80
-
81
- Also note that the ProcessId and ParentProcessId attributes have been
82
- abbreviated as 'pid' and 'ppid' in the struct members, again to keep the
83
- members more consistent between platforms.
84
-
85
- The "Mem Usage" and "VM Size" that you may be used to seeing in your Task
86
- Manager window (probably) correspond to the 'working_set_size' and
87
- 'page_file_usage' struct members, respectively, keeping in mind that
88
- those values are in bytes, not kilobytes. I say 'probably' because
89
- comments that I've read online indicate that it may not always line up
90
- with what you see in the Task Manager, based on the current version (or
91
- even Service Pack) of Windows that you are using.
92
-
93
- = Future Plans
94
- Possibly use the Win32_PerfFormattedData_PerfProc_Process class to get
95
- additional process information.
96
-
97
- = Known Bugs
98
- Versions of Ruby earlier than 1.8.2 resulted in segfaults when trying to
99
- run this code. You will likely encounter the same behavior.
100
-
101
- Please log any additional bug reports on the project page at
102
- http://www.rubyforge.org/projects/sysutils
103
-
104
- = License
105
- Ruby's
106
-
107
- = Copyright
108
- (C) 2003-2006 Daniel J. Berger
109
- All Rights Reserved
110
-
111
- = Warranty
112
- This package is provided "as is" and without any express or
113
- implied warranties, including, without limitation, the implied
114
- warranties of merchantability and fitness for a particular purpose.
115
-
116
- = Author
117
- Daniel J. Berger
118
- djberg96 at nospam at gmail dot com
119
- imperator on IRC (freenode)
120
-
121
- = See Also
122
- OLE + WMI
@@ -1,98 +0,0 @@
1
- #############################################################################
2
- # Installation script for sys-proctable.
3
- #
4
- # By running this file, it is assumed that you want a C extension, and not
5
- # a pure Ruby version. If you want a pure Ruby version (and you're on a
6
- # platform for which it's supported), run install.rb instead.
7
- #############################################################################
8
- require 'mkmf'
9
- require 'fileutils'
10
-
11
- c_file = nil
12
- h_file = nil
13
- tc_file = nil
14
-
15
- ########################################################################
16
- # Ruby 1.8.3 and later mandates the use of rb_pid_t over pid_t because
17
- # some libraries define their own pid_t. So, we check for that.
18
- ########################################################################
19
- have_type('rb_pid_t', 'ruby.h')
20
-
21
- ##########################################################################
22
- # Determine appropriate source files based on platform. Also, check for
23
- # certain header files and/or libraries on some platforms.
24
- #
25
- # On FreeBSD a different source file is used if the /proc filesystem is
26
- # not found (kvm is used instead). For OpenBSD or NetBSD, the kvm
27
- # interface is always used for now.
28
- ##########################################################################
29
- case RUBY_PLATFORM
30
- when /hpux/i
31
- c_file = 'hpux/hpux.c'
32
- h_file = 'hpux/hpux.h'
33
- tc_file = 'tc_hpux'
34
- when /freebsd/i
35
- if File.exists?('/proc') && Dir['/proc/*'].length > 0
36
- c_file = 'freebsd/freebsd.c'
37
- h_file = 'freebsd/freebsd.h'
38
- tc_file = 'tc_freebsd'
39
- else
40
- have_library('kvm')
41
- have_struct_member('struct kinfo_proc', 'kp_proc', 'sys/user.h')
42
- have_struct_member('struct kinfo_proc', 'kp_eproc', 'sys/user.h')
43
- c_file = 'bsd/bsd.c'
44
- tc_file = 'tc_kvm_bsd.rb'
45
- end
46
- when /openbsd|netbsd/
47
- have_library('kvm')
48
- c_file = 'bsd/bsd.c'
49
- tc_file = 'tc_kvm_bsd.rb'
50
- when /solaris|sunos/i
51
- c_file = 'sunos/sunos.c'
52
- h_file = 'sunos/sunos.h'
53
- tc_file = 'tc_sunos'
54
- have_header('procfs.h') # false means Solaris 2.5.x
55
- when /linux/i
56
- c_file = 'linux/linux.c'
57
- h_file = 'linux/linux.h'
58
- tc_file = 'tc_linux'
59
- when /darwin/i
60
- c_file = 'darwin/darwin.c'
61
- tc_file = 'tc_darwin'
62
- when /windows|win32|cygwin|mingw|dos/i
63
- msg = 'Use the install_pure_ruby.rb script to install on MS Windows'
64
- STDERR.puts msg
65
- exit
66
- else
67
- puts 'This platform not currently supported. Exiting...'
68
- exit
69
- end
70
-
71
- #####################################################################
72
- # Move the 'windows.rb' file under 'lib/sys/' to '.orig' to prevent
73
- # mkmf from installing it during the 'make install' phase.
74
- #####################################################################
75
- if File.exists?('../lib/sys/windows.rb')
76
- File.rename('../lib/sys/windows.rb', '../lib/sys/windows.orig')
77
- end
78
-
79
- ###################
80
- # build ts_all.rb
81
- ###################
82
- test_file = '../test/ts_all.rb'
83
- File.open(test_file, 'w'){ |fh|
84
- fh.puts "require 'tc_all'"
85
- fh.puts "require '#{tc_file}'"
86
- fh.puts "require 'tc_top'"
87
- }
88
-
89
- ########################################################################
90
- # Copy or link files to current directory for create_makefile to work.
91
- ########################################################################
92
- File.delete('proctable.c') rescue nil
93
- File.delete(File.basename(h_file)) rescue nil
94
-
95
- FileUtils.cp(c_file, 'proctable.c')
96
- FileUtils.cp(h_file, File.basename(h_file)) if h_file
97
-
98
- create_makefile('sys/proctable')
@@ -1,374 +0,0 @@
1
- /**************************************************************************
2
- * sunos.c (proctable.c)
3
- *
4
- * Solaris specific code for the Ruby ps extension. Some code
5
- * has been copied directly from Dan Urist's Proc::ProcessTable
6
- * Perl module.
7
- *
8
- * The portion of code that grabs data out of /proc/xxx/as is based
9
- * on a post by Roger Faulkner on comp.unix.questions.
10
- **************************************************************************/
11
- #include "ruby.h"
12
- #include "sunos.h"
13
- #include "version.h"
14
-
15
- #ifdef __cplusplus
16
- extern "C"
17
- {
18
- #endif
19
-
20
- VALUE sProcStruct, cProcError;
21
-
22
- /*
23
- * Private method that converts a psinfo struct into a Ruby struct.
24
- */
25
- #ifdef HAVE_PROCFS_H
26
- static VALUE proctable_getprocstruct(struct psinfo *p, VALUE v_cmd_array)
27
- #else
28
- static VALUE proctable_getprocstruct(struct prpsinfo *p, VALUE v_cmd_array)
29
- #endif
30
- {
31
- char state[STATE_MAX];
32
- char comm[COMM_MAX];
33
- prusage_t pbuf;
34
- VALUE cmdline;
35
- VALUE rbTTY = Qnil;
36
-
37
- /*
38
- * If we were unable to get the full command line, resort to the limited
39
- * pr_psargs struct member.
40
- */
41
- if(RARRAY(v_cmd_array)->len == 0)
42
- cmdline = rb_str_new2(p->pr_psargs);
43
- else
44
- cmdline = rb_ary_join(v_cmd_array,rb_str_new2(" "));
45
-
46
- if(PRNODEV != p->pr_ttydev)
47
- rbTTY = UINT2NUM(p->pr_ttydev);
48
- else
49
- rbTTY = INT2NUM(-1);
50
-
51
- #ifndef HAVE_PROCFS_H
52
- char wchan[WCHAN_MAX];
53
- sprintf(wchan, "%x", (unsigned int)p->pr_wchan);
54
- #endif
55
-
56
- #ifdef HAVE_PROCFS_H
57
- switch(p->pr_lwp.pr_state)
58
- #else
59
- switch(p->pr_state)
60
- #endif
61
- {
62
- case SSLEEP:
63
- strcpy(state, SLEEP);
64
- break;
65
- case SRUN:
66
- strcpy(state, RUN);
67
- break;
68
- case SZOMB:
69
- strcpy(state, ZOMBIE);
70
- break;
71
- case SSTOP:
72
- strcpy(state, STOP);
73
- break;
74
- case SIDL:
75
- strcpy(state, IDLE);
76
- break;
77
- case SONPROC:
78
- strcpy(state, ONPROC);
79
- break;
80
- }
81
-
82
- strcpy(comm, p->pr_fname);
83
-
84
- getprusage(p->pr_pid,&pbuf); /* Get the process usage info */
85
-
86
- return rb_struct_new(sProcStruct,
87
- INT2FIX(p->pr_flag),
88
- #ifdef HAVE_PROCFS_H
89
- INT2FIX(p->pr_nlwp),
90
- #endif
91
- UINT2NUM(p->pr_pid),
92
- UINT2NUM(p->pr_ppid),
93
- #ifdef HAVE_PROCFS_H
94
- UINT2NUM(p->pr_pgid),
95
- #else
96
- UINT2NUM(p->pr_pgrp),
97
- #endif
98
- UINT2NUM(p->pr_sid),
99
- UINT2NUM(p->pr_uid),
100
- UINT2NUM(p->pr_euid),
101
- UINT2NUM(p->pr_gid),
102
- UINT2NUM(p->pr_egid),
103
- #ifdef HAVE_PROCFS_H
104
- INT2FIX(p->pr_lwp.pr_pri),
105
- INT2FIX(p->pr_lwp.pr_nice),
106
- #else
107
- INT2FIX(p->pr_pri),
108
- INT2FIX(p->pr_nice),
109
- #endif
110
- rbTTY,
111
- INT2FIX(p->pr_time.tv_sec),
112
- INT2FIX(p->pr_ctime.tv_sec),
113
- #ifdef HAVE_PROCFS_H
114
- INT2FIX(p->pr_size * 1024),
115
- INT2FIX(p->pr_rssize * 1024),
116
- UINT2NUM(p->pr_lwp.pr_wchan),
117
- #else
118
- INT2FIX(p->pr_bysize),
119
- INT2FIX(p->pr_rssize),
120
- rb_str_new2(wchan),
121
- #endif
122
- rb_float_new(((double)p->pr_pctcpu)/0x8000*100),
123
- rb_float_new(((double)p->pr_pctmem)/0x8000*100),
124
- rb_str_new2(state),
125
- rb_str_new2(p->pr_fname),
126
- cmdline,
127
- rb_time_new(p->pr_start.tv_sec,0),
128
- #ifdef HAVE_PROCFS_H
129
- INT2NUM(p->pr_lwp.pr_onpro),
130
- #endif
131
- rb_str_new2(comm),
132
- INT2FIX(p->pr_argc),
133
- v_cmd_array,
134
- LONG2FIX(pbuf.pr_lwpid),
135
- INT2FIX(pbuf.pr_count),
136
- LONG2FIX(pbuf.pr_tstamp.tv_sec),
137
- LONG2FIX(pbuf.pr_create.tv_sec),
138
- LONG2FIX(pbuf.pr_term.tv_sec),
139
- LONG2FIX(pbuf.pr_rtime.tv_sec),
140
- LONG2FIX(pbuf.pr_utime.tv_sec),
141
- LONG2FIX(pbuf.pr_stime.tv_sec),
142
- LONG2FIX(pbuf.pr_ttime.tv_sec),
143
- LONG2FIX(pbuf.pr_tftime.tv_sec),
144
- LONG2FIX(pbuf.pr_dftime.tv_sec),
145
- LONG2FIX(pbuf.pr_kftime.tv_sec),
146
- LONG2FIX(pbuf.pr_ltime.tv_sec),
147
- LONG2FIX(pbuf.pr_slptime.tv_sec),
148
- LONG2FIX(pbuf.pr_wtime.tv_sec),
149
- LONG2FIX(pbuf.pr_stoptime.tv_sec),
150
- ULONG2NUM(pbuf.pr_minf),
151
- ULONG2NUM(pbuf.pr_majf),
152
- ULONG2NUM(pbuf.pr_nswap),
153
- ULONG2NUM(pbuf.pr_inblk),
154
- ULONG2NUM(pbuf.pr_oublk),
155
- ULONG2NUM(pbuf.pr_msnd),
156
- ULONG2NUM(pbuf.pr_mrcv),
157
- ULONG2NUM(pbuf.pr_sigs),
158
- ULONG2NUM(pbuf.pr_vctx),
159
- ULONG2NUM(pbuf.pr_ictx),
160
- ULONG2NUM(pbuf.pr_sysc),
161
- ULONG2NUM(pbuf.pr_ioch)
162
- );
163
- }
164
-
165
- /*
166
- * call-seq:
167
- * ProcTable.ps(pid=nil)
168
- * ProcTable.ps(pid=nil){ |ps| ... }
169
- *
170
- * In block form, yields a ProcTableStruct for each process entry that you
171
- * have rights to. This method returns an array of ProcTableStruct's in
172
- * non-block form.
173
- *
174
- * If a +pid+ is provided, then only a single ProcTableStruct is yielded or
175
- * returned, or nil if no process information is found for that +pid+.
176
- */
177
- static VALUE proctable_ps(int argc, VALUE *argv, VALUE klass)
178
- {
179
- DIR *procdir;
180
- struct dirent *procdirp;
181
- int psdata;
182
- char pathbuf[PATH_MAX];
183
-
184
- char* arg;
185
- uintptr_t addr_args;
186
- uintptr_t* arg_vec;
187
- size_t arg_len;
188
- int fd, arg_count, i, pid;
189
-
190
- VALUE v_pid;
191
- VALUE v_ps_struct = Qnil;
192
- VALUE v_array = Qnil;
193
- VALUE v_cmd_array = rb_ary_new();
194
-
195
- #ifdef HAVE_PROCFS_H
196
- struct psinfo p;
197
- char as_file[MAXPATHLEN];
198
- #else
199
- struct prpsinfo p;
200
- #endif
201
-
202
- rb_scan_args(argc, argv, "01", &v_pid);
203
-
204
- if(!rb_block_given_p())
205
- v_array = rb_ary_new();
206
-
207
- if( (procdir = opendir( "/proc" )) == NULL )
208
- rb_raise(cProcError,"/proc filesystem unreadable");
209
-
210
- while( (procdirp = readdir(procdir)) != NULL )
211
- {
212
- /* Only look at this file if it's a proc id; that is, all numbers */
213
- if(strtok(procdirp->d_name, "0123456789") != NULL ){ continue; }
214
-
215
- /* If a pid is provided, only return info on that pid */
216
- if(!NIL_P(v_pid)){
217
- pid = NUM2INT(v_pid);
218
- if(atoi(procdirp->d_name) != pid)
219
- continue;
220
- }
221
-
222
- /* Construct path of the form /proc/proc_number */
223
- strcpy(pathbuf, "/proc/");
224
- strcpy(as_file, "/proc/");
225
- strcat(pathbuf, procdirp->d_name);
226
- strcat(as_file, procdirp->d_name);
227
-
228
- #ifdef HAVE_PROCFS_H
229
- strcat(pathbuf, "/psinfo"); /* Solaris 2.6+ has process info here */
230
- strcat(as_file, "/as");
231
- #endif
232
-
233
- if( (psdata = open( pathbuf, O_RDONLY )) == -1 )
234
- continue;
235
-
236
- #ifdef HAVE_PROCFS_H
237
- read(psdata, (void *) &p, sizeof(struct psinfo));
238
- #else
239
- if(ioctl(psdata, PIOCPSINFO, &p) == -1)
240
- continue;
241
- #endif
242
-
243
- #ifdef HAVE_PROCFS_H
244
- /*
245
- * For those processes where it is possible to read /proc/xxx/as
246
- * get the entire command line string.
247
- */
248
- addr_args = p.pr_argv;
249
- arg_count = p.pr_argc;
250
-
251
- if((fd = open(as_file, O_RDONLY)) < 0){
252
- /* Do nothing - you can only get info on processes you rights to */
253
- }
254
- else
255
- {
256
- arg_vec = malloc(arg_count * sizeof(uintptr_t));
257
-
258
- /* We need this here to pick up args properly on 2.8+ */
259
- #ifdef PR_MODEL_NATIVE
260
- if(p.pr_dmodel == PR_MODEL_NATIVE){
261
- (void)pread(fd, arg_vec, arg_count * sizeof (uintptr_t), addr_args);
262
- }
263
- else{
264
- caddr32_t *arg_vec32 = (caddr32_t *)arg_vec;
265
- (void)pread(fd, arg_vec32, arg_count * sizeof (caddr32_t), addr_args);
266
- for (i = arg_count - 1; i >= 0; --i)
267
- {
268
- arg_vec[i] = arg_vec32[i];
269
- }
270
- }
271
- #else
272
- /* Need a better patch for 2.6 here */
273
- (void)pread(fd, arg_vec, arg_count * sizeof (uintptr_t), addr_args);
274
- #endif
275
-
276
- arg_len = 16;
277
- arg = malloc(arg_len+1);
278
- for(i = 0; i < arg_count; i++) {
279
-
280
- if(pread(fd, arg, arg_len, arg_vec[i]) < 0)
281
- continue;
282
-
283
- arg[arg_len] = '\0';
284
- if(strlen(arg) == arg_len){
285
- arg_len *= 2;
286
- arg = realloc(arg, arg_len + 1);
287
- i--;
288
- continue;
289
- }
290
- rb_ary_push(v_cmd_array, rb_str_new2(arg));
291
- }
292
- free(arg);
293
- free(arg_vec);
294
- }
295
- close(fd);
296
- #endif
297
-
298
- close(psdata);
299
- v_ps_struct = proctable_getprocstruct(&p, v_cmd_array);
300
-
301
- if(rb_block_given_p()){
302
- rb_yield(v_ps_struct);
303
- }
304
- else{
305
- rb_ary_push(v_array, v_ps_struct);
306
- }
307
- rb_ary_clear(v_cmd_array);
308
- }
309
- closedir(procdir);
310
-
311
- /* If a process ID was provided and found, return a single struct */
312
- if(!NIL_P(v_pid))
313
- return v_ps_struct;
314
-
315
- return v_array; /* nil if block was provided */
316
- }
317
-
318
- /*
319
- * call-seq:
320
- * ProcTable.fields
321
- *
322
- * Returns an array of fields that each ProcTableStruct will contain. This
323
- * may be useful if you want to know in advance what fields are available
324
- * without having to perform at least one read of the /proc table.
325
- */
326
- static VALUE proctable_fields(VALUE klass){
327
- uint_t i;
328
- VALUE rbFarray = rb_ary_new();
329
-
330
- for(i = 0; i < (sizeof(fields) / sizeof(fields[0])); i++)
331
- rb_ary_push(rbFarray, rb_str_new2(fields[i]));
332
-
333
- return rbFarray;
334
- }
335
-
336
- /*
337
- * A Ruby interface for gathering process table information.
338
- */
339
- void Init_proctable(){
340
- VALUE mSys, cProcTable;
341
-
342
- /* Modules and Classes */
343
- mSys = rb_define_module("Sys");
344
- cProcTable = rb_define_class_under(mSys, "ProcTable", rb_cObject);
345
- cProcError = rb_define_class_under(mSys, "ProcTableError", rb_eStandardError);
346
-
347
- /* Class methods */
348
- rb_define_singleton_method(cProcTable, "fields", proctable_fields, 0);
349
- rb_define_singleton_method(cProcTable, "ps", proctable_ps, -1);
350
-
351
- /* Constants */
352
- rb_define_const(cProcTable, "VERSION", rb_str_new2(SYS_PROCTABLE_VERSION));
353
-
354
- /* Structs */
355
- sProcStruct = rb_struct_define("ProcTableStruct","flag",
356
- #ifdef HAVE_PROCFS_H
357
- "nlwp",
358
- #endif
359
- "pid","ppid","pgid","sid","uid","euid","gid","egid","priority","nice",
360
- "ttydev","time","ctime","size","rss","wchan","pctcpu","pctmem","state",
361
- "fname","cmdline","start",
362
- #ifdef HAVE_PROCFS_H
363
- "processor",
364
- #endif
365
- "comm","num_args","cmd_args","lwpid","count","tstamp","create","term",
366
- "rtime","utime","stime","ttime","tftime","dftime","kftime","ltime",
367
- "slptime","wtime","stoptime","minf","majf","nswap","inblk","oublk",
368
- "msnd","mrcv","sigs","vctx","ictx","sysc","ioch",NULL
369
- );
370
- }
371
-
372
- #ifdef __cplusplus
373
- }
374
- #endif