sys-proctable 0.7.4 → 0.7.5

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/CHANGES CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.7.5 - 23-Nov-2006
2
+ * Fixed int/long issues for Linux. Thanks go to Matt Lightner for the spot.
3
+ * Minor documentation fixes and changes to the extconf.rb file.
4
+
1
5
  == 0.7.4 - 20-Nov-2006
2
6
  * Added a patch that deals with the large file compilation issue on Solaris.
3
7
  You no longer need to build Ruby with --disable-largefile, or build a
@@ -20,7 +24,7 @@
20
24
  * Include bsd.c in tarball (oops).
21
25
  * Minor test updates for FreeBSD.
22
26
  * The 'pct_cpu' member for the BSD/kvm version has been changed to 'pctcpu'
23
- consistency with other platforms.
27
+ for consistency with other platforms.
24
28
 
25
29
  == 0.7.1 - 8-May-2005
26
30
  * Bug fixed for the cmdline info on Linux. Thanks go to Arash Abedinzadeh
data/doc/freebsd.txt CHANGED
@@ -38,7 +38,7 @@ VERSION
38
38
 
39
39
  = Class Methods
40
40
  ProcTable.fields
41
- Returns a list of fields available on the current OS. Also takes a block.
41
+ Returns an array of fields available on the current OS.
42
42
 
43
43
  ProcTable.ps(pid = nil)
44
44
  ProcTable.ps{ |s| ... }
data/doc/hpux.txt CHANGED
@@ -30,8 +30,7 @@ VERSION
30
30
 
31
31
  = Class Methods
32
32
  ProcTable.fields
33
- Returns a list of fields available on the current OS. May also take
34
- a block.
33
+ Returns an array of fields available on the current OS.
35
34
 
36
35
  ProcTable.ps(pid=nil)
37
36
  ProcTable.ps{ |s| ... }
data/doc/linux.txt CHANGED
@@ -38,8 +38,7 @@ VERSION
38
38
 
39
39
  = Class Methods
40
40
  ProcTable.fields
41
- Returns a list of fields available on the current OS. May also take a
42
- block.
41
+ Returns an array of fields available on the current OS.
43
42
 
44
43
  ProcTable.ps(pid=nil)
45
44
  ProcTable.ps{ |s| ... }
data/doc/solaris.txt CHANGED
@@ -36,8 +36,7 @@ VERSION
36
36
 
37
37
  = Class Methods
38
38
  ProcTable.fields
39
- Returns a list of fields available on the current OS. May also take
40
- a block.
39
+ Returns an array of fields available on the current OS.
41
40
 
42
41
  ProcTable.ps(pid=nil)
43
42
  ProcTable.ps{ |s| ... }
data/ext/extconf.rb CHANGED
@@ -84,7 +84,6 @@ File.open(test_file, 'w'){ |fh|
84
84
  fh.puts '$LOAD_PATH.unshift Dir.pwd'
85
85
  fh.puts '$LOAD_PATH.unshift Dir.pwd + "/lib"'
86
86
  fh.puts '$LOAD_PATH.unshift Dir.pwd + "/ext"'
87
- fh.puts "require 'tc_all'"
88
87
  fh.puts "require '#{tc_file}'"
89
88
  fh.puts "require 'tc_top'"
90
89
  }
@@ -95,7 +94,7 @@ File.open(test_file, 'w'){ |fh|
95
94
  File.delete('proctable.c') rescue nil
96
95
  File.delete(File.basename(h_file)) rescue nil
97
96
 
98
- File.symlink(c_file, 'proctable.c')
99
- File.symlink(h_file, File.basename(h_file)) if h_file
97
+ FileUtils.cp(c_file, 'proctable.c')
98
+ FileUtils.cp(h_file, File.basename(h_file)) if h_file
100
99
 
101
100
  create_makefile('sys/proctable')
data/ext/linux/linux.c ADDED
@@ -0,0 +1,320 @@
1
+ /***************************************************************
2
+ * linux.c (proctable.c)
3
+ *
4
+ * Linux 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
+ * Author: Daniel J. Berger
9
+ **************************************************************/
10
+ #include "ruby.h"
11
+ #include "linux.h"
12
+ #include "version.h"
13
+
14
+ #ifdef __cplusplus
15
+ extern "C"
16
+ {
17
+ #endif
18
+
19
+ VALUE sProc, cProcError;
20
+
21
+ /*
22
+ * Converts a proc_info struct into a Ruby struct.
23
+ */
24
+ static VALUE proctable_get_process(struct proc_info *p, VALUE env_hash) {
25
+ return rb_struct_new(sProc,
26
+ rb_str_new2(p->cmdline),
27
+ rb_str_new2(p->cwd),
28
+ rb_str_new2(p->exe),
29
+ INT2FIX(p->pid),
30
+ rb_str_new2(p->name),
31
+ INT2FIX(p->uid),
32
+ INT2FIX(p->euid),
33
+ INT2FIX(p->gid),
34
+ INT2FIX(p->egid),
35
+ rb_str_new2(p->comm),
36
+ rb_str_new(p->state,1),
37
+ INT2FIX(p->ppid),
38
+ INT2FIX(p->pgrp),
39
+ INT2FIX(p->session),
40
+ INT2FIX(p->tty_num),
41
+ INT2FIX(p->tpgid),
42
+ ULONG2NUM(p->flags),
43
+ ULONG2NUM(p->minflt),
44
+ ULONG2NUM(p->cminflt),
45
+ ULONG2NUM(p->majflt),
46
+ ULONG2NUM(p->cmajflt),
47
+ ULONG2NUM(p->utime),
48
+ ULONG2NUM(p->stime),
49
+ LONG2FIX(p->cutime),
50
+ LONG2FIX(p->cstime),
51
+ LONG2FIX(p->priority),
52
+ LONG2FIX(p->nice),
53
+ LONG2FIX(p->itrealvalue),
54
+ ULONG2NUM(p->starttime),
55
+ ULONG2NUM(p->vsize),
56
+ LONG2FIX(p->rss),
57
+ ULONG2NUM(p->rlim),
58
+ ULONG2NUM(p->startcode),
59
+ ULONG2NUM(p->endcode),
60
+ ULONG2NUM(p->startstack),
61
+ ULONG2NUM(p->kstkesp),
62
+ ULONG2NUM(p->kstkeip),
63
+ ULONG2NUM(p->signal),
64
+ ULONG2NUM(p->blocked),
65
+ ULONG2NUM(p->sigignore),
66
+ ULONG2NUM(p->sigcatch),
67
+ ULONG2NUM(p->wchan),
68
+ ULONG2NUM(p->nswap),
69
+ ULONG2NUM(p->cnswap),
70
+ INT2FIX(p->exit_signal),
71
+ INT2FIX(p->processor),
72
+ env_hash
73
+ );
74
+ }
75
+
76
+ /*
77
+ * call-seq:
78
+ * ProcTable.ps(pid=nil)
79
+ * ProcTable.ps(pid=nil){ |ps| ... }
80
+ *
81
+ * In block form, yields a ProcTableStruct for each process entry that you
82
+ * have rights to. This method returns an array of ProcTableStruct's in
83
+ * non-block form.
84
+ *
85
+ * If a +pid+ is provided, then only a single ProcTableStruct is yielded or
86
+ * returned, or nil if no process information is found for that +pid+.
87
+ */
88
+ static VALUE proctable_ps(int argc, VALUE *argv, VALUE klass){
89
+ DIR* dir_ptr;
90
+ FILE* file_ptr;
91
+ struct dirent* dirent_ptr;
92
+ struct proc_info p;
93
+ char pathbuf[NAME_MAX];
94
+ int temp, num_scanned;
95
+ int pid = -1;
96
+
97
+ VALUE v_pid = Qnil;
98
+ VALUE v_array = Qnil;
99
+ VALUE v_pstruct = Qnil;
100
+ VALUE v_env = rb_hash_new();
101
+
102
+ rb_scan_args(argc, argv, "01", &v_pid);
103
+
104
+ if((dir_ptr = opendir("/proc")) == NULL)
105
+ rb_raise(cProcError, "/proc filesystem unreadable");
106
+
107
+ if(!NIL_P(v_pid))
108
+ pid = NUM2INT(v_pid);
109
+
110
+ if(!rb_block_given_p())
111
+ v_array = rb_ary_new();
112
+
113
+ /* Iterate through all the (numeric) process entries uner /proc */
114
+ while((dirent_ptr = readdir(dir_ptr)) != NULL){
115
+
116
+ /* Only look at this file if it's a proc id; that is, all numbers */
117
+ if( strtok(dirent_ptr->d_name, "0123456789") != NULL )
118
+ continue;
119
+
120
+ if(!NIL_P(v_pid)){
121
+ if(atoi(dirent_ptr->d_name) != pid){
122
+ continue;
123
+ }
124
+ }
125
+
126
+ /* Get the /proc/PID/cmdline info */
127
+ sprintf(pathbuf, "%s%s%s", "/proc/", dirent_ptr->d_name, "/cmdline");
128
+ if( (file_ptr = fopen(pathbuf, "r")) != NULL ){
129
+ size_t got;
130
+ if((got = fread(p.cmdline, sizeof(char), ARG_MAX, file_ptr)) > 0 ){
131
+ size_t i;
132
+
133
+ /* Replace \0 characters with spaces */
134
+ for(i = 0; i < got; i++){
135
+ if(p.cmdline[i] == '\0'){
136
+ p.cmdline[i] = ' ';
137
+ }
138
+ }
139
+
140
+ p.cmdline[got] = '\0';
141
+ trimr(p.cmdline); /* Trim trailing whitespace */
142
+ }
143
+ fclose(file_ptr);
144
+ }
145
+
146
+ /* Get the /proc/PID/exe info (which is a link) */
147
+ sprintf(pathbuf, "%s%s%s", "/proc/", dirent_ptr->d_name, "/exe");
148
+ memset(p.exe, 0, sizeof(p.exe));
149
+
150
+ if(readlink(pathbuf, p.exe, sizeof(p.exe)) == -1){ /* Ignore */ }
151
+
152
+ /* Get the /proc/PID/cwd info (which is a link) */
153
+ sprintf(pathbuf, "%s%s%s", "/proc/", dirent_ptr->d_name, "/cwd");
154
+ memset(p.cwd, 0, sizeof(p.cwd));
155
+
156
+ if(readlink(pathbuf, p.cwd, sizeof(p.cwd)) == -1){ /* Ignore */ }
157
+
158
+ /* Get name, uid, euid, gid and gid info out of /proc/PID/status */
159
+ sprintf(pathbuf, "%s%s%s", "/proc/", dirent_ptr->d_name, "/status");
160
+
161
+ if((file_ptr = fopen(pathbuf,"r")) != NULL ){
162
+ char line[ARG_MAX];
163
+ char dummy[ARG_MAX];
164
+
165
+ while(fgets(line, ARG_MAX - 1, file_ptr) != NULL){
166
+ if(!strncmp("Name", line, strlen("Name"))) {
167
+ sscanf(line, "%s %s", dummy, p.name);
168
+ }
169
+ else if(!strncmp("Uid", line, strlen("Uid"))){
170
+ sscanf(line, "%s %d %d", dummy, &p.uid, &p.euid);
171
+ }
172
+ else if (!strncmp("Gid", line, strlen("Gid"))) {
173
+ sscanf(line, "%s %d %d", dummy, &p.gid, &p.egid);
174
+ }
175
+ }
176
+ fclose(file_ptr);
177
+ }
178
+
179
+ /* Get the /proc/PID/stat info */
180
+ sprintf(pathbuf,"%s%s%s","/proc/",dirent_ptr->d_name,"/stat");
181
+ if((file_ptr = fopen(pathbuf,"r")) != NULL){
182
+ num_scanned = fscanf(file_ptr,
183
+ "%d %s %s %d %d\
184
+ %d %d %d %lu %lu\
185
+ %lu %lu %lu %lu %lu\
186
+ %ld %ld %ld %ld %d\
187
+ %ld %lu %lu %ld %lu\
188
+ %lu %lu %lu %lu %lu\
189
+ %lu %lu %lu %lu %lu\
190
+ %lu %lu %d %d",
191
+ &p.pid, p.comm, p.state, &p.ppid, &p.pgrp,
192
+ &p.session, &p.tty_num, &p.tpgid, &p.flags, &p.minflt,
193
+ &p.cminflt, &p.majflt, &p.cmajflt, &p.utime, &p.stime,
194
+ &p.cutime, &p.cstime, &p.priority, &p.nice, &temp,
195
+ &p.itrealvalue,&p.starttime, &p.vsize, &p.rss, &p.rlim,
196
+ &p.startcode, &p.endcode, &p.startstack, &p.kstkesp, &p.kstkeip,
197
+ &p.signal, &p.blocked, &p.sigignore, &p.sigcatch, &p.wchan,
198
+ &p.nswap, &p.cnswap, &p.exit_signal,&p.processor
199
+ );
200
+
201
+ fclose(file_ptr);
202
+
203
+ if(num_scanned < 39)
204
+ rb_sys_fail("fscanf");
205
+ }
206
+
207
+ /* Get rid of the parens in the comm field */
208
+ strcpy(p.comm, strtok(p.comm,"()"));
209
+
210
+ /**********************************************************************
211
+ * Get the environ string out or /proc/PID/environ and make a hash
212
+ * out of it
213
+ **********************************************************************/
214
+ sprintf(pathbuf, "%s%s%s", "/proc/", dirent_ptr->d_name, "/environ");
215
+ if((file_ptr = fopen( pathbuf, "r" )) != NULL){
216
+
217
+ int count;
218
+ char env_buf[ARG_MAX];
219
+ char key[MAX_ENV_NAME];
220
+ char *next_var, *value;
221
+
222
+ /* Get char count */
223
+ count = fread(env_buf, sizeof(char), ARG_MAX, file_ptr);
224
+ next_var = env_buf;
225
+
226
+ while(next_var < env_buf + count){
227
+ value = strchr(next_var,'=');
228
+ /***************************************************************
229
+ * It's possible some environ files contain data that's not in
230
+ * the KEY=value format. For such cases, we'll just set the
231
+ * string as the key, and set the corresponding value to nil.
232
+ ***************************************************************/
233
+ if(NULL == value){
234
+ rb_hash_aset(v_env, rb_str_new2(next_var), Qnil);
235
+ break;
236
+ }
237
+ strncpy(key, next_var, value - next_var);
238
+ key[value-next_var] = '\0';
239
+
240
+ ++value;
241
+ rb_hash_aset(v_env, rb_str_new2(key), rb_str_new2(value));
242
+ next_var += strlen(next_var) + 1;
243
+ }
244
+
245
+ fclose(file_ptr);
246
+ }
247
+
248
+ /* If cmdline is empty, use comm instead */
249
+ if(0 == strlen(p.cmdline))
250
+ strcpy(p.cmdline, p.comm);
251
+
252
+ v_pstruct = proctable_get_process(&p, v_env);
253
+
254
+ if(rb_block_given_p())
255
+ rb_yield(v_pstruct);
256
+ else
257
+ rb_ary_push(v_array, v_pstruct);
258
+ }
259
+
260
+ closedir(dir_ptr);
261
+
262
+ /* If a process ID was provided and found, return a single struct */
263
+ if(!NIL_P(v_pid))
264
+ return v_pstruct;
265
+
266
+ return v_array; /* nil if block was provided */
267
+ }
268
+
269
+ /*
270
+ * call-seq:
271
+ * ProcTable.fields
272
+ *
273
+ * Returns an array of fields that each ProcTableStruct will contain. This
274
+ * may be useful if you want to know in advance what fields are available
275
+ * without having to perform at least one read of the /proc table.
276
+ */
277
+ static VALUE proctable_fields(VALUE klass){
278
+ unsigned int i;
279
+ VALUE rbFarray = rb_ary_new();
280
+
281
+ for(i = 0; i < sizeof(fields)/sizeof(fields[0]); i++)
282
+ rb_ary_push(rbFarray,rb_str_new2(fields[i]));
283
+
284
+ return rbFarray;
285
+ }
286
+
287
+ /*
288
+ * A Ruby interface for gathering process table information.
289
+ */
290
+ void Init_proctable()
291
+ {
292
+ VALUE mSys, cProcTable;
293
+
294
+ /* Modules and Classes */
295
+ mSys = rb_define_module("Sys");
296
+ cProcTable = rb_define_class_under(mSys, "ProcTable", rb_cObject);
297
+ cProcError = rb_define_class_under(mSys, "ProcTableError",rb_eStandardError);
298
+
299
+ /* Class Methods */
300
+ rb_define_singleton_method(cProcTable, "fields", proctable_fields, 0);
301
+ rb_define_singleton_method(cProcTable, "ps", proctable_ps, -1);
302
+
303
+ /* Constants */
304
+ rb_define_const(cProcTable,"VERSION",rb_str_new2(SYS_PROCTABLE_VERSION));
305
+
306
+ /* Structs */
307
+ sProc = rb_struct_define("ProcTableStruct","cmdline","cwd","exe","pid",
308
+ "name", "uid", "euid", "gid", "egid", "comm","state","ppid",
309
+ "pgrp","session","tty_num","tpgid","flags","minflt","cminflt","majflt",
310
+ "cmajflt","utime","stime","cutime","cstime","priority","nice",
311
+ "itrealvalue","starttime","vsize","rss","rlim","startcode","endcode",
312
+ "startstack","kstkesp","kstkeip","signal","blocked","sigignore",
313
+ "sigcatch","wchan","nswap","cnswap","exit_signal","processor","environ",
314
+ NULL
315
+ );
316
+ }
317
+
318
+ #ifdef __cplusplus
319
+ }
320
+ #endif
data/ext/linux/linux.h ADDED
@@ -0,0 +1,138 @@
1
+ /************************************************************************
2
+ * linux.h
3
+ *
4
+ * Linux specific information, including struct layout.
5
+ ************************************************************************/
6
+ #include <dirent.h>
7
+ #include <linux/limits.h>
8
+ #include <unistd.h>
9
+ #include <string.h>
10
+ #include <ctype.h>
11
+
12
+ #ifndef CLK_TCK
13
+ #define CLK_TCK sysconf(_SC_CLK_TCK)
14
+ #endif
15
+
16
+ #define MAX_ENV_NAME 128
17
+
18
+ /****************************************************************************
19
+ * Note that the 20th field (between nice and itrealvalue) is not included
20
+ * in our struct. It is a simple placeholder that was hardcoded for a
21
+ * removed field. See the proc man page for more details.
22
+ *
23
+ * Also note that the environ attribute is not part of this struct, mostly
24
+ * because I wouldn't know what type to set it to. It *is* part of the ruby
25
+ * struct, however.
26
+ ****************************************************************************/
27
+ struct proc_info{
28
+ char cmdline[ARG_MAX];
29
+ char cwd[ARG_MAX];
30
+ char exe[ARG_MAX];
31
+ int pid;
32
+ char name[ARG_MAX];
33
+ int uid;
34
+ int euid;
35
+ int gid;
36
+ int egid;
37
+ char comm[ARG_MAX];
38
+ char state[1];
39
+ int ppid;
40
+ int pgrp;
41
+ int session;
42
+ int tty_num;
43
+ int tpgid;
44
+ unsigned long flags;
45
+ unsigned long minflt;
46
+ unsigned long cminflt;
47
+ unsigned long majflt;
48
+ unsigned long cmajflt;
49
+ unsigned long utime;
50
+ unsigned long stime;
51
+ long cutime;
52
+ long cstime;
53
+ long priority;
54
+ long nice;
55
+ long itrealvalue;
56
+ unsigned long starttime;
57
+ unsigned long vsize;
58
+ long rss;
59
+ unsigned long rlim;
60
+ unsigned long startcode;
61
+ unsigned long endcode;
62
+ unsigned long startstack;
63
+ unsigned long kstkesp;
64
+ unsigned long kstkeip;
65
+ unsigned long signal;
66
+ unsigned long blocked;
67
+ unsigned long sigignore;
68
+ unsigned long sigcatch;
69
+ unsigned long wchan;
70
+ unsigned long nswap;
71
+ unsigned long cnswap;
72
+ int exit_signal;
73
+ int processor;
74
+ };
75
+
76
+ /*****************************************************************************
77
+ * This array's only purpose is for the 'fields()' class method. If there's
78
+ * a way to report fields out of our defined struct (sProc), please tell me
79
+ * how!
80
+ *****************************************************************************/
81
+ char *fields[] = {
82
+ "cmdline",
83
+ "cwd",
84
+ "exe",
85
+ "pid",
86
+ "name",
87
+ "uid",
88
+ "euid",
89
+ "gid",
90
+ "egid",
91
+ "comm",
92
+ "state",
93
+ "ppid",
94
+ "pgrp",
95
+ "session",
96
+ "tty_num",
97
+ "tpgid",
98
+ "flags",
99
+ "minflt",
100
+ "cminflt",
101
+ "majflt",
102
+ "cmajflt",
103
+ "utime",
104
+ "stime",
105
+ "cutime",
106
+ "cstime",
107
+ "priority",
108
+ "nice",
109
+ "itrealvalue",
110
+ "starttime",
111
+ "vsize",
112
+ "rss",
113
+ "rlim",
114
+ "startcode",
115
+ "endcode",
116
+ "startstack",
117
+ "kstkesp",
118
+ "kstkeip",
119
+ "signal",
120
+ "blocked",
121
+ "sigignore",
122
+ "sigcatch",
123
+ "wchan",
124
+ "nswap",
125
+ "cnswap",
126
+ "exit_signal",
127
+ "processor",
128
+ "environ"
129
+ };
130
+
131
+ /* Helper function to remove trailing whitespace. Use for cmdline info */
132
+ void trimr(char* s){
133
+ char* p = s + strlen(s);
134
+ while(--p >= s && isspace(*p))
135
+ ;
136
+
137
+ *++p = 0;
138
+ }
data/ext/version.h CHANGED
@@ -1,2 +1,2 @@
1
1
  /* version.h - stores the version number for all platforms (that use C) */
2
- #define SYS_PROCTABLE_VERSION "0.7.4"
2
+ #define SYS_PROCTABLE_VERSION "0.7.5"
data/test/tc_all.rb CHANGED
@@ -22,14 +22,14 @@ if base == 'test' || base =~ /sys-proctable.*/
22
22
  $LOAD_PATH.unshift(Dir.pwd + '/lib')
23
23
  end
24
24
 
25
- require 'sys/proctable'
26
25
  require 'test/unit'
26
+ require 'sys/proctable'
27
27
  include Sys
28
28
 
29
29
  class TC_ProcTable_All < Test::Unit::TestCase
30
30
 
31
31
  def test_version
32
- assert_equal('0.7.4', ProcTable::VERSION)
32
+ assert_equal('0.7.5', ProcTable::VERSION)
33
33
  end
34
34
 
35
35
  def test_fields
data/test/tc_linux.rb CHANGED
@@ -9,7 +9,7 @@ if base == 'test' || base =~ /sys-proctable.*/
9
9
  require 'fileutils'
10
10
  require 'rbconfig'
11
11
 
12
- Dir.chdir '..' if base == 'test'
12
+ Dir.chdir('..') if base == 'test'
13
13
  file = 'ext/proctable.' + Config::CONFIG['DLEXT']
14
14
  Dir.mkdir('sys') unless File.exists?('sys')
15
15
  FileUtils.cp(file, 'sys')
@@ -17,10 +17,7 @@ if base == 'test' || base =~ /sys-proctable.*/
17
17
  $LOAD_PATH.unshift(Dir.pwd)
18
18
  end
19
19
 
20
- require "sys/proctable"
21
- require "test/unit"
22
20
  require "test/tc_all"
23
- include Sys
24
21
 
25
22
  class TC_ProcTable_Linux < Test::Unit::TestCase
26
23
 
data/test/tc_top.rb CHANGED
@@ -6,15 +6,13 @@
6
6
  base = File.basename(Dir.pwd)
7
7
 
8
8
  if base == 'test' || base =~ /sys-proctable.*/
9
- require 'fileutils'
10
9
  Dir.chdir('..') if base == 'test'
11
- Dir.mkdir('sys') unless File.exists?('sys')
12
- FileUtils.cp('lib/top.rb', 'sys')
13
- $LOAD_PATH.unshift Dir.pwd
10
+ $LOAD_PATH.unshift(Dir.pwd)
11
+ $LOAD_PATH.unshift(Dir.pwd + '/lib')
14
12
  end
15
13
 
16
- require 'sys/top'
17
14
  require 'test/unit'
15
+ require 'sys/top'
18
16
  include Sys
19
17
 
20
18
  class TC_Top < Test::Unit::TestCase
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: sys-proctable
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.7.4
7
- date: 2006-11-21 00:00:00 -07:00
6
+ version: 0.7.5
7
+ date: 2006-11-23 00:00:00 -07:00
8
8
  summary: An interface for providing process table information
9
9
  require_paths:
10
10
  - lib
@@ -30,30 +30,30 @@ authors:
30
30
  - Daniel J. Berger
31
31
  files:
32
32
  - doc/freebsd.txt
33
- - doc/hpux.txt
34
- - doc/linux.txt
35
- - doc/solaris.txt
36
33
  - doc/top.txt
34
+ - doc/solaris.txt
37
35
  - doc/windows.txt
38
- - test/tc_all.rb
39
- - test/tc_freebsd.rb
40
- - test/tc_hpux.rb
41
- - test/tc_kvm_bsd.rb
36
+ - doc/hpux.txt
37
+ - doc/linux.txt
42
38
  - test/tc_linux.rb
43
39
  - test/tc_sunos.rb
44
- - test/tc_top.rb
40
+ - test/tc_kvm_bsd.rb
41
+ - test/tc_hpux.rb
45
42
  - test/tc_windows.rb
46
43
  - test/test_memleak.rb
44
+ - test/tc_all.rb
45
+ - test/tc_freebsd.rb
46
+ - test/tc_top.rb
47
47
  - lib/sys/top.rb
48
48
  - CHANGES
49
49
  - README
50
50
  - MANIFEST
51
- - ext/sunos/sunos.c
51
+ - ext/linux/linux.c
52
52
  - ext/extconf.rb
53
53
  - ext/version.h
54
- - ext/sunos/sunos.h
54
+ - ext/linux/linux.h
55
55
  test_files:
56
- - test/tc_sunos.rb
56
+ - test/tc_linux.rb
57
57
  rdoc_options: []
58
58
 
59
59
  extra_rdoc_files:
@@ -61,8 +61,8 @@ extra_rdoc_files:
61
61
  - README
62
62
  - MANIFEST
63
63
  - doc/top.txt
64
- - doc/solaris.txt
65
- - ext/sunos/sunos.c
64
+ - doc/linux.txt
65
+ - ext/linux/linux.c
66
66
  executables: []
67
67
 
68
68
  extensions:
data/ext/sunos/sunos.c DELETED
@@ -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
data/ext/sunos/sunos.h DELETED
@@ -1,177 +0,0 @@
1
- /*****************************************************************************
2
- * solaris.h
3
- *
4
- * Solaris specific header file. Some things copy/pasted straight out
5
- * of Dan Urist's Proc::ProcessTable Perl module.
6
- *****************************************************************************/
7
- #include <stdio.h>
8
- #include <stdlib.h>
9
- #include <dirent.h>
10
- #include <sys/param.h>
11
- #include <sys/types.h>
12
- #include <sys/proc.h>
13
- #include <fcntl.h>
14
- #include <string.h>
15
- #include <unistd.h>
16
- #include <utmpx.h>
17
-
18
- /* This bit of magic was taken from a post by Stefan Teleman on the KDE
19
- * mailing list. It allows us to build without having to disable largefile
20
- * support or explicitly build a 64 bit Ruby.
21
- */
22
- #if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
23
- #define PROCFS_FILE_OFFSET_BITS_HACK 1
24
- #undef _FILE_OFFSET_BITS
25
- #else
26
- #define PROCFS_FILE_OFFSET_BITS_HACK 0
27
- #endif
28
-
29
- #if defined(HAVE_PROCFS_H)
30
- #include <procfs.h>
31
- #else
32
- #include <sys/procfs.h>
33
- #endif
34
-
35
- #if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1)
36
- #define _FILE_OFFSET_BITS 64
37
- #endif
38
-
39
- #ifndef CLK_TCK
40
- #define CLK_TCK sysconf(_SC_CLK_TCK)
41
- #endif
42
-
43
- #ifndef NAME_MAX
44
- #define NAME_MAX 255
45
- #endif
46
-
47
- /* Ruby 1.8.3 or later */
48
- #ifdef HAVE_TYPE_RB_PID_T
49
- #define pid_t rb_pid_t
50
- #endif
51
-
52
- #define COMM_MAX 64
53
- #define STATE_MAX 20
54
- #define WCHAN_MAX 64
55
-
56
- /* Function prototypes */
57
- static void getprusage(pid_t pid, prusage_t* pr_usage);
58
-
59
- /* Process state strings that we return */
60
- #define SLEEP "sleep"
61
- #define WAIT "wait"
62
- #define RUN "run"
63
- #define IDLE "idle"
64
- #define ZOMBIE "zombie"
65
- #define STOP "stop"
66
- #define ONPROC "onprocessor"
67
-
68
- /*
69
- * A simple static structure, mainly for use with the 'fields()' class method.
70
- * The fields here *should* be identical to the fields listed in the ps_struct.
71
- * The exception is the 'comm' field, which I added to give it a bit of
72
- * (foolish?) consistency with the other platforms. I will try to make sure
73
- * that field is common to all platforms.
74
- */
75
- static char* fields[] = {
76
- "flag",
77
- #ifdef HAVE_PROCFS_H
78
- "nlwp",
79
- #endif
80
- "pid",
81
- "ppid",
82
- "pgid",
83
- "sid",
84
- "uid",
85
- "euid",
86
- "gid",
87
- "egid",
88
- "priority",
89
- "nice",
90
- "ttydev",
91
- "time",
92
- "ctime",
93
- "size",
94
- "rss",
95
- "wchan",
96
- "pctcpu",
97
- "pctmem",
98
- "state",
99
- "fname",
100
- "cmdline",
101
- "start",
102
- #ifdef HAVE_PROCFS_H
103
- "processor",
104
- #endif
105
- "comm",
106
- "num_args",
107
- "cmd_args",
108
- "lwpid",
109
- "count",
110
- "tstamp",
111
- "create",
112
- "term",
113
- "rtime",
114
- "utime",
115
- "stime",
116
- "ttime",
117
- "tftime",
118
- "dftime",
119
- "kftime",
120
- "ltime",
121
- "slptime",
122
- "wtime",
123
- "stoptime",
124
- "minf",
125
- "majf",
126
- "nswap",
127
- "inblk",
128
- "oublk",
129
- "msnd",
130
- "mrcv",
131
- "sigs",
132
- "vctx",
133
- "ictx",
134
- "sysc",
135
- "ioch"
136
- };
137
-
138
- /*
139
- * Private function for getting data out of the /proc/self/usage directory.
140
- * Based on Rich Teer's function in "Solaris Systems Programming", p.329
141
- * and p.332.
142
- */
143
- #if defined(HAVE_PROCFS_H)
144
- static void getprusage(pid_t pid, prusage_t* pr_usage){
145
- int fd;
146
- char name[PATH_MAX];
147
-
148
- snprintf(name, PATH_MAX, "/proc/%ld/usage", (long)pid);
149
-
150
- if((fd = open(name, O_RDONLY)) == -1)
151
- rb_sys_fail(0);
152
-
153
- if(read(fd,pr_usage,sizeof(prusage_t)) == -1){
154
- close(fd);
155
- rb_sys_fail(0);
156
- }
157
-
158
- close(fd);
159
- }
160
- #else
161
- static void getprusage(pid_t pid, prusage_t* pr_usage){
162
- int fd;
163
- char name[PATH_MAX];
164
-
165
- snprintf(name, PATH_MAX, "/proc/%ld", (long)pid);
166
-
167
- if((fd = open(name, O_RDONLY)) == -1)
168
- rb_sys_fail(0);
169
-
170
- if(ioctl(fd,PIOCUSAGE,pr_usage) == -1){
171
- close(fd);
172
- rb_sys_fail(0);
173
- }
174
-
175
- close(fd);
176
- }
177
- #endif