sys-proctable 0.9.1-universal-darwin

Sign up to get free protection for your applications and to get access to all the features.
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
+ }