File Coverage

ProcessTable.xs
Criterion Covered Total %
statement 75 125 60.0
branch 38 88 43.1
condition n/a
subroutine n/a
pod n/a
total 113 213 53.0


line stmt bran cond sub pod time code
1             #ifdef PROCESSTABLE_THREAD
2             #define __REENTRANT
3             #endif
4              
5             #ifdef __cplusplus
6             extern "C" {
7             #endif
8             #include "EXTERN.h"
9             #include "perl.h"
10             #include "XSUB.h"
11             #ifdef __cplusplus
12             }
13             #endif
14              
15             #ifdef PROCESSTABLE_THREAD
16             #include
17             #endif
18              
19             /* dTHX was used in perl 5.005 */
20             #ifndef dTHX
21             #define dTHX dTHR
22             #endif
23              
24             /********************/
25             /* General includes */
26             /********************/
27             #include
28             #include
29             #include
30             #include
31             #include
32              
33             /* prototypes to make the compiler shut up */
34             void ppt_warn(const char*, ...);
35             void ppt_die(const char*, ...);
36             void store_ttydev(HV*, unsigned long);
37             void bless_into_proc(char* , char**, ...);
38             void OS_get_table();
39             char* OS_initialize();
40              
41             char** Fields = NULL;
42             int Numfields;
43              
44             /* Cache a pointer the TTY device number hash for quick lookups */
45             HV* Ttydevs;
46              
47             /* This holds a pointer to the list of process objects we will build */
48             AV* Proclist;
49              
50             /* Our local varargs warn which can be called as extern by code
51             * that doesn't know Perl internals (and thus doesn't have a
52             * warn() defined).
53             *
54             * I think vwarn() and vcroak() have been changed to warn() and
55             * croak() in perl 5.8?? warn and croak exist in 5.6, but don't
56             * seem to accept format args.
57             */
58 0           void ppt_warn(const char *pat, ...) {
59             dTHX;
60             va_list args;
61 0           va_start(args, pat);
62 0           vwarn(pat, &args);
63 0           va_end(args);
64 0           }
65              
66             /* same with croak */
67 0           void ppt_croak(const char *pat, ...) {
68             dTHX;
69             va_list args;
70 0           va_start(args, pat);
71 0           vcroak(pat, &args);
72             va_end(args);
73             }
74              
75             /* Look up the tty device, given the ttynum and store it */
76 53           void store_ttydev( HV* myhash, unsigned long ttynum ){
77             SV** ttydev;
78             char ttynumbuf[1024];
79            
80 53           sprintf(ttynumbuf, "%lu", ttynum);
81 53 50         if(
82 53 50         Ttydevs != NULL &&
83 53           (ttydev = hv_fetch(Ttydevs, ttynumbuf, strlen(ttynumbuf), 0)) != NULL
84             ){
85 0           hv_store(myhash, "ttydev", strlen("ttydev"), newSVsv(*ttydev), 0);
86             }
87             else{
88             /* hv_store(myhash, "ttydev", strlen("ttydev"), newSV(0), 0); */
89              
90             /* Stuff an empty string into the hash if there is no tty; this */
91             /* way the ttydev method won't return undef for nonexistent ttys. I'm */
92             /* not sure if this is really the right behavior... */
93              
94 53           hv_store(myhash, "ttydev", strlen("ttydev"), newSVpv("",0), 0);
95              
96             }
97 53           }
98              
99              
100             /**********************************************************************/
101             /* This gets called by OS-specific get_table */
102             /* format specifies what types are being passed in, in a string */
103             /* containing these specifiers: */
104             /* A ignore this array of strings */
105             /* a array of strings, delimated with NULL, next argument is len */
106             /* S ignore this string */
107             /* s string */
108             /* I ignore this int */
109             /* i int */
110             /* L ignore this long */
111             /* l long */
112             /* J ignore this long-long */
113             /* j long-long */
114             /* U ignore this unsigned */
115             /* u unsigned */
116             /* V perl scalar value */
117             /* P ignore this string */
118             /* p unsigned long */
119             /* fields is an array of pointers to field names */
120             /* following that is a var args list of field values */
121             /**********************************************************************/
122 53           void bless_into_proc(char* format, char** fields, ...){
123             va_list args;
124             char* key;
125             char* s_val;
126             SV *SV_val;
127             int i_val;
128             unsigned u_val;
129             long l_val;
130             unsigned long p_val;
131             long long ll_val;
132              
133             HV* myhash;
134             SV* ref;
135             HV* mystash;
136             SV* blessed;
137              
138             /* Blech */
139 53 100         if(Fields == NULL){
140 3           Fields = fields;
141 3           Numfields = strlen(format);
142             }
143              
144 53           myhash = newHV(); /* create a perl hash */
145              
146 53           va_start(args, fields);
147 2120 100         while( *format ){
148 2067           key = *fields;
149 2067           switch(*format)
150             {
151             case 'A': /* ignore; creates an undef value for this key in the hash */
152 0 0         va_arg(args, char *);
153 0 0         va_arg(args, int);
154 0           hv_store(myhash, key, strlen(key), &PL_sv_undef, 0);
155 0           break;
156             case 'a': /* string */
157 106 50         s_val = va_arg(args, char *);
158 106 50         i_val = va_arg(args, int);
159             {
160             int len;
161             char *s;
162 106           AV *av = newAV();
163              
164 1473 100         for (s = s_val; s < (s_val + i_val); s += len + 1) {
165 1367           len = strlen(s);
166 1367           av_push (av, newSVpvn (s, len));
167             }
168 106           hv_store (myhash, key, strlen(key), newRV_noinc((SV *) av), 0);
169             }
170 106           break;
171              
172             case 'S': /* ignore; creates an undef value for this key in the hash */
173 0 0         va_arg(args, char *);
174 0           hv_store(myhash, key, strlen(key), newSV(0), 0);
175 0           break;
176             case 's': /* string */
177 371 100         s_val = va_arg(args, char *);
178 371           hv_store(myhash, key, strlen(key), newSVpv(s_val, strlen(s_val)), 0);
179 371           break;
180              
181             case 'I': /* ignore; creates an undef value for this key in the hash */
182 0 0         va_arg(args, int);
183 0           hv_store(myhash, key, strlen(key), newSV(0), 0);
184 0           break;
185             case 'i': /* int */
186 795 100         i_val = va_arg(args, int);
187 795           hv_store(myhash, key, strlen(key), newSViv(i_val), 0);
188              
189             /* Look up and store the tty if this is ttynum */
190 795 100         if( !strcmp(key, "ttynum") ) store_ttydev( myhash, i_val );
191 795           break;
192              
193             case 'U': /* ignore; creates an undef value for this key in the hash */
194 0 0         va_arg(args, unsigned );
195 0           hv_store(myhash, key, strlen(key), newSV(0), 0);
196 0           break;
197             case 'u': /* int */
198 0 0         u_val = va_arg(args, unsigned);
199 0           hv_store(myhash, key, strlen(key), newSVuv(u_val), 0);
200 0           break;
201              
202             case 'L': /* ignore; creates an undef value for this key in the hash */
203 0 0         va_arg(args, long);
204 0           hv_store(myhash, key, strlen(key), newSV(0), 0);
205 0           break;
206             case 'l': /* long */
207 371 50         l_val = va_arg(args, long);
208 371           hv_store(myhash, key, strlen(key), newSVnv(l_val), 0);
209             /* Look up and store the tty if this is ttynum */
210 371 50         if( !strcmp(key, "ttynum") ) store_ttydev( myhash, l_val );
211 371           break;
212              
213             case 'P': /* ignore; creates an undef value for this key in the hash */
214 0 0         va_arg(args, unsigned long);
215 0           hv_store(myhash, key, strlen(key), newSV(0), 0);
216 0           break;
217             case 'p': /* unsigned long */
218 53 50         p_val = va_arg(args, unsigned long);
219 53           hv_store(myhash, key, strlen(key), newSVnv(p_val), 0);
220 53           break;
221              
222             case 'J': /* ignore; creates an undef value for this key in the hash */
223 0 0         va_arg(args, long long);
224 0           hv_store(myhash, key, strlen(key), newSV(0), 0);
225 0           break;
226             case 'j': /* long long */
227 371 50         ll_val = va_arg(args, long long);
228 371           hv_store(myhash, key, strlen(key), newSVnv(ll_val), 0);
229 371           break;
230              
231             case 'V': /* perl scalar value */
232 0 0         SV_val = va_arg(args, SV *);
233 0           hv_store(myhash, key, strlen(key), SV_val, 0);
234 0           break;
235              
236             default:
237 0           croak("Unknown data format type `%c' returned from OS_get_table", *format);
238             va_end(args);
239             }
240            
241 2067           format++;
242 2067           fields++;
243             }
244              
245             /* objectify the hash */
246 53           ref = newRV_noinc((SV*) myhash); /* create ref from hash pointer */
247 53           mystash = gv_stashpv("Proc::ProcessTable::Process", 1); /* create symbol table for this obj */
248 53           blessed = sv_bless(ref, mystash); /* bless it */
249             /* push it onto the array */
250 53           av_push(Proclist, blessed);
251              
252 53           va_end(args);
253 53           }
254              
255             /**********************************************************************/
256             /* Generic funcs generated by h2xs */
257             /**********************************************************************/
258              
259             static int
260 0           not_here(s)
261             char *s;
262             {
263 0           croak("%s not implemented on this architecture", s);
264             return -1;
265             }
266              
267             static double
268 0           constant(name, arg)
269             char *name;
270             int arg;
271             {
272 0           errno = 0;
273 0           switch (*name) {
274             }
275 0           errno = EINVAL;
276 0           return 0;
277              
278             not_there:
279             errno = ENOENT;
280             return 0;
281             }
282              
283             #ifdef PROCESSTABLE_THREAD
284             pthread_mutex_t _mutex_table;
285             pthread_mutex_t _mutex_new;
286              
287             void
288             mutex_op(int lock, pthread_mutex_t *mutex)
289             {
290             if (lock == 0) { /*unlock*/
291             pthread_mutex_unlock(mutex);
292             } else { /*lock*/
293             pthread_mutex_lock(mutex);
294             }
295             }
296             #endif
297              
298             void
299 6           mutex_new(int lock)
300             {
301             #ifdef PROCESSTABLE_THREAD
302             mutex_op(lock, &_mutex_new);
303             #endif
304 6           }
305              
306             void
307 10           mutex_table(int lock)
308             {
309             #ifdef PROCESSTABLE_THREAD
310             mutex_op(lock, &_mutex_table);
311             #endif
312 10           }
313              
314             MODULE = Proc::ProcessTable PACKAGE = Proc::ProcessTable
315             PROTOTYPES: DISABLE
316              
317             BOOT:
318             #ifdef PROCESSTABLE_THREAD
319             pthread_mutex_init(&_mutex_table, NULL);
320             pthread_mutex_init(&_mutex_new, NULL);
321             #endif
322              
323             void
324             mutex_new(lock)
325             int lock
326              
327             void
328             mutex_table(lock)
329             int lock
330              
331             double
332             constant(name,arg)
333             char * name
334             int arg
335              
336             SV*
337             table(obj)
338             SV* obj
339             CODE:
340              
341             /* Check that we have an actual object.
342             calling Proc::Processtable->table SIGSEVs
343             calling on an actual object is valid my $proc_obj = Proc::ProcessTable->new; $proc_obj->table;
344             */
345 6 50         if (!obj || !SvOK (obj) || !SvROK (obj) || !sv_isobject (obj)) {
    50          
    0          
    0          
    100          
    50          
346 1           croak("Must call table from an initalized object created with new");
347             }
348              
349              
350             HV* hash;
351             SV** fetched;
352              
353              
354 5           mutex_table(1);
355             /* Cache a pointer to the tty device hash */
356 5           Ttydevs = perl_get_hv("Proc::ProcessTable::TTYDEVS", FALSE);
357              
358             /* dereference our object to a hash */
359 5           hash = (HV*) SvRV(obj);
360              
361             /* If the Table array already exists on our object we clear it
362             and store a pointer to it in Proclist */
363 5 100         if( hv_exists(hash, "Table", 5) ){
364             /* fetch the hash entry */
365 2           fetched = hv_fetch(hash, "Table", 5, 0);
366             /* what's stored in the hash is a ref to the array, so we need
367             to dereference it */
368 2           Proclist = (AV*) SvRV(*fetched);
369 2           av_clear(Proclist);
370             }
371             else{
372             /* Otherwise we create the array and store it on the object. */
373 3           Proclist = newAV();
374 3           hv_store(hash, "Table", 5, newRV_noinc((SV*)Proclist), 0);
375             }
376              
377             /* Call get_table to build the process objects and push them onto
378             the Proclist */
379 5           OS_get_table();
380              
381             /* Return a ref to our process list */
382 5           RETVAL = newRV_inc((SV*) Proclist);
383              
384 5           mutex_table(0);
385            
386             OUTPUT:
387             RETVAL
388              
389             void
390             fields(obj)
391             SV* obj
392             PPCODE:
393              
394             /* see above. This should be called on an object generated by new */
395 2 50         if (!obj || !SvOK (obj) || !SvROK (obj) || !sv_isobject (obj)) {
    50          
    0          
    0          
    100          
    50          
396 1           croak("Must call fields from an initalized object created with new");
397             }
398              
399             int i;
400             SV* my_sv;
401              
402 1 50         if( Fields == NULL ){
403 0 0         PUSHMARK(SP);
404 0 0         XPUSHs(obj);
405 0           PUTBACK;
406 0           perl_call_method("table", G_DISCARD);
407             }
408              
409 1 50         EXTEND(SP,Numfields);
    50          
410 40 100         for (i=0; i < Numfields; i++ ){
411 39           my_sv = newSVpv(Fields[i],0);
412 39           PUSHs(sv_2mortal(my_sv));
413             }
414              
415             void
416             _initialize_os(obj)
417             SV* obj
418             CODE:
419             char* error;
420              
421 3 50         if( (error = OS_initialize()) != NULL ){
422 0           croak("%s", error);
423             }