sys-proctable 0.9.1-universal-darwin

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.
data/Rakefile ADDED
@@ -0,0 +1,173 @@
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
+ spec.original_platform = spec.platform
163
+ Gem::Builder.new(spec).build
164
+ end
165
+
166
+ desc 'Install the sys-proctable library as a gem'
167
+ task :install => [:create] do
168
+ gem_name = Dir['*.gem'].first
169
+ sh "gem install #{gem_name}"
170
+ end
171
+ end
172
+
173
+ 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,4 @@
1
+ require 'mkmf'
2
+
3
+ have_type('rb_pid_t', 'ruby.h')
4
+ create_makefile('sys/proctable', 'sys')
@@ -0,0 +1,255 @@
1
+ /**********************************************************************
2
+ * Mac OS X code for sys-proctable Ruby library. *
3
+ * *
4
+ * Date: 3-Mar-2006 (original submission date) *
5
+ * Author: David Felstead (david.felstead at gmail dot com) *
6
+ * Based on bsd.c by Daniel J. Berger (djberg96 at gmail dot com) *
7
+ *********************************************************************/
8
+ #include "ruby.h"
9
+ #include <sys/param.h>
10
+ #include <sys/stat.h>
11
+ #include <sys/sysctl.h>
12
+ #include <sys/types.h>
13
+ #include <sys/user.h>
14
+ #include <errno.h>
15
+
16
+ #define SYS_PROCTABLE_VERSION "0.9.1"
17
+
18
+ #define PROC_MIB_LEN 4
19
+ #define ARGS_MIB_LEN 3
20
+ #define ARGS_MAX_LEN 4096
21
+ VALUE cProcTableError, sProcStruct;
22
+
23
+ const char* fields[] = {
24
+ "pid", "ppid", "pgid", "ruid", "rgid", "comm", "state", "pctcpu", "oncpu",
25
+ "tnum", "tdev", "wmesg", "rtime", "priority", "usrpri", "nice", "cmdline",
26
+ "starttime", "maxrss", "ixrss", "idrss", "isrss", "minflt", "majflt",
27
+ "nswap", "inblock", "oublock", "msgsnd", "msgrcv", "nsignals", "nvcsw",
28
+ "nivcsw", "utime", "stime"
29
+ };
30
+
31
+ /*
32
+ * call-seq:
33
+ * ProcTable.ps(pid=nil)
34
+ * ProcTable.ps(pid=nil){ |ps| ... }
35
+ *
36
+ * In block form, yields a ProcTableStruct for each process entry that you
37
+ * have rights to. This method returns an array of ProcTableStruct's in
38
+ * non-block form.
39
+ *
40
+ * If a +pid+ is provided, then only a single ProcTableStruct is yielded or
41
+ * returned, or nil if no process information is found for that +pid+.
42
+ */
43
+ static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){
44
+ int err;
45
+ char state[8];
46
+ struct kinfo_proc* procs;
47
+ VALUE v_pid, v_tty_num, v_tty_dev, v_start_time;
48
+ VALUE v_pstruct = Qnil;
49
+ VALUE v_array = rb_ary_new();
50
+ size_t length, count;
51
+ size_t i = 0;
52
+ char args[ARGS_MAX_LEN+1];
53
+
54
+ // Passed into sysctl call
55
+ static const int name_mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
56
+
57
+ rb_scan_args(argc, argv, "01", &v_pid);
58
+
59
+ // Get size of proc kproc buffer
60
+ err = sysctl( (int *) name_mib, PROC_MIB_LEN, NULL, &length, NULL, 0);
61
+
62
+ if(err == -1)
63
+ rb_raise(cProcTableError, "sysctl: %s", strerror(errno));
64
+
65
+ // Populate the kproc buffer
66
+ procs = malloc(length);
67
+
68
+ if(procs == NULL)
69
+ rb_raise(cProcTableError, "malloc: %s", strerror(errno));
70
+
71
+ err = sysctl( (int *) name_mib, PROC_MIB_LEN, procs, &length, NULL, 0);
72
+
73
+ if(err == -1)
74
+ rb_raise(cProcTableError, "sysctl: %s", strerror(errno));
75
+
76
+ // If we're here, we got our list
77
+ count = length / sizeof(struct kinfo_proc);
78
+
79
+ for(i = 0; i < count; i++) {
80
+ v_tty_num = Qnil;
81
+ v_tty_dev = Qnil;
82
+ v_start_time = Qnil;
83
+
84
+ // If a PID is provided, skip unless the PID matches
85
+ if( (!NIL_P(v_pid)) && (procs[i].kp_proc.p_pid != NUM2INT(v_pid)) )
86
+ continue;
87
+
88
+ *args = '\0';
89
+
90
+ /* Query the command line args */
91
+ /* TODO: Cmd line not working for now - fix */
92
+
93
+ /*args_mib[ARGS_MIB_LEN - 1] = procs[i].kp_proc.p_pid;
94
+ args_err = sysctl( (int *) args_mib, ARGS_MIB_LEN, args, &args_size, NULL, 0);
95
+
96
+ if(args_err >= 0) {
97
+ fprintf(stderr, "Ret: %d LEN: %d\n", err, args_size);
98
+ char *c;
99
+ for(c = args; c < args+args_size; c++)
100
+ if(*c == '\0') *c = ' ';
101
+ args[args_size] = '\0';
102
+ } else {
103
+ fprintf(stderr, "err: %s LEN: %d\n", strerror(errno), args_size);
104
+ }*/
105
+
106
+ // Get the start time of the process
107
+ v_start_time = rb_time_new(
108
+ procs[i].kp_proc.p_un.__p_starttime.tv_sec,
109
+ procs[i].kp_proc.p_un.__p_starttime.tv_usec
110
+ );
111
+
112
+ // Get the state of the process
113
+ switch(procs[i].kp_proc.p_stat)
114
+ {
115
+ case SIDL:
116
+ strcpy(state, "idle");
117
+ break;
118
+ case SRUN:
119
+ strcpy(state, "run");
120
+ break;
121
+ case SSLEEP:
122
+ strcpy(state, "sleep");
123
+ break;
124
+ case SSTOP:
125
+ strcpy(state, "stop");
126
+ break;
127
+ case SZOMB:
128
+ strcpy(state, "zombie");
129
+ break;
130
+ default:
131
+ strcpy(state, "unknown");
132
+ break;
133
+ }
134
+
135
+ // Get ttynum and ttydev. If ttynum is -1, there is no tty.
136
+ if(procs[i].kp_eproc.e_tdev != -1){
137
+ v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev),
138
+ v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR));
139
+ }
140
+
141
+ v_pstruct = rb_struct_new(
142
+ sProcStruct,
143
+ INT2FIX(procs[i].kp_proc.p_pid),
144
+ INT2FIX(procs[i].kp_eproc.e_ppid),
145
+ INT2FIX(procs[i].kp_eproc.e_pgid),
146
+ INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid),
147
+ INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid),
148
+ rb_str_new2(procs[i].kp_proc.p_comm),
149
+ rb_str_new2(state),
150
+ rb_float_new(procs[i].kp_proc.p_pctcpu),
151
+ Qnil,
152
+ v_tty_num,
153
+ v_tty_dev,
154
+ rb_str_new2(procs[i].kp_eproc.e_wmesg),
155
+ INT2FIX(procs[i].kp_proc.p_rtime.tv_sec),
156
+ INT2FIX(procs[i].kp_proc.p_priority),
157
+ INT2FIX(procs[i].kp_proc.p_usrpri),
158
+ INT2FIX(procs[i].kp_proc.p_nice),
159
+ rb_str_new2(args),
160
+ v_start_time,
161
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_maxrss) : Qnil,
162
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_ixrss) : Qnil,
163
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_idrss) : Qnil,
164
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_isrss) : Qnil,
165
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_minflt) : Qnil,
166
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_majflt) : Qnil,
167
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nswap) : Qnil,
168
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_inblock) : Qnil,
169
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_oublock) : Qnil,
170
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgsnd) : Qnil,
171
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgrcv) : Qnil,
172
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nsignals) : Qnil,
173
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nvcsw) : Qnil,
174
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nivcsw) : Qnil,
175
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_utime.tv_sec) : Qnil,
176
+ (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_stime.tv_sec) : Qnil
177
+ );
178
+
179
+ OBJ_FREEZE(v_pstruct); // This is read-only data
180
+
181
+ if(rb_block_given_p())
182
+ rb_yield(v_pstruct);
183
+ else
184
+ rb_ary_push(v_array, v_pstruct);
185
+ }
186
+
187
+ if(procs) free(procs);
188
+
189
+ if(!rb_block_given_p()){
190
+ if(NIL_P(v_pid))
191
+ return v_array;
192
+ else
193
+ return v_pstruct;
194
+ }
195
+
196
+ return Qnil;
197
+ }
198
+
199
+ /*
200
+ * call-seq:
201
+ * ProcTable.fields
202
+ *
203
+ * Returns an array of fields that each ProcTableStruct will contain. This
204
+ * may be useful if you want to know in advance what fields are available
205
+ * without having to perform at least one read of the /proc table.
206
+ */
207
+ static VALUE pt_fields(VALUE klass){
208
+ VALUE v_array = rb_ary_new();
209
+ int size = sizeof(fields) / sizeof(fields[0]);
210
+ int i;
211
+
212
+ for(i = 0; i < size; i++)
213
+ rb_ary_push(v_array, rb_str_new2(fields[i]));
214
+
215
+ return v_array;
216
+ }
217
+
218
+ /*
219
+ * A Ruby interface for gathering process table information.
220
+ */
221
+ void Init_proctable(){
222
+ VALUE mSys, cProcTable;
223
+
224
+ /* The Sys module serves as a namespace only */
225
+ mSys = rb_define_module("Sys");
226
+
227
+ /* The ProcTable class encapsulates process table information */
228
+ cProcTable = rb_define_class_under(mSys, "ProcTable", rb_cObject);
229
+
230
+ /* The Error class typically raised if any of the ProcTable methods fail */
231
+ cProcTableError = rb_define_class_under(cProcTable, "Error", rb_eStandardError);
232
+
233
+ /* Singleton methods */
234
+
235
+ rb_define_singleton_method(cProcTable, "ps", pt_ps, -1);
236
+ rb_define_singleton_method(cProcTable, "fields", pt_fields, 0);
237
+
238
+ /* There is no constructor */
239
+ rb_funcall(cProcTable, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
240
+
241
+ /* Constants */
242
+
243
+ /* 0.9.1: The version of the sys-proctable library */
244
+ rb_define_const(cProcTable, "VERSION", rb_str_new2(SYS_PROCTABLE_VERSION));
245
+
246
+ /* Structs */
247
+
248
+ sProcStruct = rb_struct_define("ProcTableStruct","pid","ppid","pgid","ruid",
249
+ "rgid","comm","state","pctcpu","oncpu","tnum","tdev","wmesg",
250
+ "rtime", "priority","usrpri","nice","cmdline","starttime",
251
+ "maxrss","ixrss","idrss","isrss","minflt","majflt","nswap",
252
+ "inblock","oublock","msgsnd","msgrcv","nsignals","nvcsw","nivcsw",
253
+ "utime","stime", NULL
254
+ );
255
+ }