sys-proctable 0.7.4 → 0.7.5

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