ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/process_stats.c
Revision: 1.65
Committed: Wed Apr 7 21:08:40 2004 UTC (20 years, 1 month ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.64: +11 -1 lines
Log Message:
The rest of the error handling stuff (except the vector code).

I've been extremely unimaginative with the string names in error.c, but
they're all in one place so much easier to tidy up. I'm also beginning to
wonder if we actually needed an SG_ERROR_SYSTEM_CALL to indicate some call
into the system failed - because the majority of our errors are those :-)

Still to do, then:
 - vector code
 - better string names in error.c
 - deal with arg string in some way
 - make use of the error status in statgrab/saidar/examples

File Contents

# Content
1 /*
2 * i-scream libstatgrab
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2004 i-scream
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 * 02111-1307 USA
20 *
21 * $Id: process_stats.c,v 1.64 2004/04/07 15:46:34 pajs Exp $
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "statgrab.h"
29 #include "tools.h"
30 #include "vector.h"
31 #if defined(SOLARIS) || defined(LINUX)
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <dirent.h>
36 #include <string.h>
37 #endif
38
39 #ifdef SOLARIS
40 #include <procfs.h>
41 #include <limits.h>
42 #define PROC_LOCATION "/proc"
43 #define MAX_FILE_LENGTH PATH_MAX
44 #endif
45 #ifdef LINUX
46 #include <limits.h>
47 #include <unistd.h>
48 #include <sys/stat.h>
49 #include <fcntl.h>
50 #define PROC_LOCATION "/proc"
51 #define MAX_FILE_LENGTH PATH_MAX
52 #endif
53 #ifdef ALLBSD
54 #include <stdlib.h>
55 #include <sys/param.h>
56 #include <sys/sysctl.h>
57 #if defined(FREEBSD) || defined(DFBSD)
58 #include <sys/user.h>
59 #else
60 #include <sys/proc.h>
61 #endif
62 #include <string.h>
63 #include <paths.h>
64 #include <fcntl.h>
65 #include <limits.h>
66 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
67 #include <kvm.h>
68 #endif
69 #include <unistd.h>
70 #ifdef NETBSD2
71 #include <sys/lwp.h>
72 #endif
73 #endif
74
75 static void proc_state_init(sg_process_stats *s) {
76 s->process_name = NULL;
77 s->proctitle = NULL;
78 }
79
80 static void proc_state_destroy(sg_process_stats *s) {
81 free(s->process_name);
82 free(s->proctitle);
83 }
84
85 sg_process_stats *sg_get_process_stats(int *entries){
86 VECTOR_DECLARE_STATIC(proc_state, sg_process_stats, 64,
87 proc_state_init, proc_state_destroy);
88 int proc_state_size = 0;
89 sg_process_stats *proc_state_ptr;
90 #ifdef ALLBSD
91 int mib[4];
92 size_t size;
93 struct kinfo_proc *kp_stats;
94 int procs, i;
95 char *proctitle;
96 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
97 kvm_t *kvmd;
98 char **args, **argsp;
99 int argslen = 0;
100 #else
101 long buflen;
102 char *p;
103 #endif
104 #ifdef NETBSD2
105 int lwps;
106 struct kinfo_lwp *kl_stats;
107 #endif
108 #endif
109 #if defined(SOLARIS) || defined(LINUX)
110 DIR *proc_dir;
111 struct dirent *dir_entry;
112 char filename[MAX_FILE_LENGTH];
113 FILE *f;
114 #ifdef SOLARIS
115 psinfo_t process_info;
116 #endif
117 #ifdef LINUX
118 char s;
119 /* If someone has a executable of 4k filename length, they deserve to get it truncated :) */
120 char ps_name[4096];
121 char *ptr;
122 VECTOR_DECLARE_STATIC(psargs, char, 128, NULL, NULL);
123 unsigned long stime, utime, starttime;
124 int x;
125 int fn;
126 int len;
127 int rc;
128 time_t uptime;
129 #endif
130
131 #ifdef LINUX
132 if ((f=fopen("/proc/uptime", "r")) == NULL) {
133 sg_set_error(SG_ERROR_OPEN, "/proc/uptime");
134 return NULL;
135 }
136 if((fscanf(f,"%lu %*d",&uptime)) != 1){
137 sg_set_error(SG_ERROR_PARSE, NULL);
138 return NULL;
139 }
140 fclose(f);
141 #endif
142
143 if((proc_dir=opendir(PROC_LOCATION))==NULL){
144 sg_set_error(SG_ERROR_OPENDIR, PROC_LOCATION);
145 return NULL;
146 }
147
148 while((dir_entry=readdir(proc_dir))!=NULL){
149 if(atoi(dir_entry->d_name) == 0) continue;
150
151 #ifdef SOLARIS
152 snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/psinfo", dir_entry->d_name);
153 #endif
154 #ifdef LINUX
155 snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/stat", dir_entry->d_name);
156 #endif
157 if((f=fopen(filename, "r"))==NULL){
158 /* Open failed.. Process since vanished, or the path was too long.
159 * Ah well, move onwards to the next one */
160 continue;
161 }
162 #ifdef SOLARIS
163 fread(&process_info, sizeof(psinfo_t), 1, f);
164 fclose(f);
165 #endif
166
167 if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
168 return NULL;
169 }
170 proc_state_ptr = proc_state+proc_state_size;
171
172 #ifdef SOLARIS
173 proc_state_ptr->pid = process_info.pr_pid;
174 proc_state_ptr->parent = process_info.pr_ppid;
175 proc_state_ptr->pgid = process_info.pr_pgid;
176 proc_state_ptr->uid = process_info.pr_uid;
177 proc_state_ptr->euid = process_info.pr_euid;
178 proc_state_ptr->gid = process_info.pr_gid;
179 proc_state_ptr->egid = process_info.pr_egid;
180 proc_state_ptr->proc_size = (process_info.pr_size) * 1024;
181 proc_state_ptr->proc_resident = (process_info.pr_rssize) * 1024;
182 proc_state_ptr->time_spent = process_info.pr_time.tv_sec;
183 proc_state_ptr->cpu_percent = (process_info.pr_pctcpu * 100.0) / 0x8000;
184 proc_state_ptr->nice = (int)process_info.pr_lwp.pr_nice - 20;
185 if (sg_update_string(&proc_state_ptr->process_name,
186 process_info.pr_fname) < 0) {
187 return NULL;
188 }
189 if (sg_update_string(&proc_state_ptr->proctitle,
190 process_info.pr_psargs) < 0) {
191 return NULL;
192 }
193
194 if(process_info.pr_lwp.pr_state==1) proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
195 if(process_info.pr_lwp.pr_state==2) proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
196 if(process_info.pr_lwp.pr_state==3) proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
197 if(process_info.pr_lwp.pr_state==4) proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
198 if(process_info.pr_lwp.pr_state==6) proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
199 #endif
200 #ifdef LINUX
201 x = fscanf(f, "%d %4096s %c %d %d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*d %*d %*d %d %*d %*d %lu %llu %llu %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %*d\n", &(proc_state_ptr->pid), ps_name, &s, &(proc_state_ptr->parent), &(proc_state_ptr->pgid), &utime, &stime, &(proc_state_ptr->nice), &starttime, &(proc_state_ptr->proc_size), &(proc_state_ptr->proc_resident));
202 /* +3 becuase man page says "Resident Set Size: number of pages the process has in real memory, minus 3 for administrative purposes." */
203 proc_state_ptr->proc_resident = (proc_state_ptr->proc_resident + 3) * getpagesize();
204 if(s == 'S') proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
205 if(s == 'R') proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
206 if(s == 'Z') proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
207 if(s == 'T') proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
208 if(s == 'D') proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
209
210 /* pa_name[0] should = '(' */
211 ptr = strchr(&ps_name[1], ')');
212 if(ptr !=NULL) *ptr='\0';
213
214 if (sg_update_string(&proc_state_ptr->process_name,
215 &ps_name[1]) < 0) {
216 return NULL;
217 }
218
219 /* cpu */
220 proc_state_ptr->cpu_percent = (100.0 * (utime + stime)) / ((uptime * 100.0) - starttime);
221
222 fclose(f);
223
224 /* uid / gid */
225 snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/status", dir_entry->d_name);
226 if ((f=fopen(filename, "r")) == NULL) {
227 /* Open failed.. Process since vanished, or the path was too long.
228 * Ah well, move onwards to the next one */
229 continue;
230 }
231
232 if((ptr=sg_f_read_line(f, "Uid:"))==NULL){
233 fclose(f);
234 continue;
235 }
236 sscanf(ptr, "Uid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->uid), &(proc_state_ptr->euid));
237
238 if((ptr=sg_f_read_line(f, "Gid:"))==NULL){
239 fclose(f);
240 continue;
241 }
242 sscanf(ptr, "Gid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->gid), &(proc_state_ptr->egid));
243
244 fclose(f);
245
246 /* proctitle */
247 snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/cmdline", dir_entry->d_name);
248
249 if((fn=open(filename, O_RDONLY)) == -1){
250 /* Open failed.. Process since vanished, or the path was too long.
251 * Ah well, move onwards to the next one */
252 continue;
253 }
254
255 #define READ_BLOCK_SIZE 128
256 len = 0;
257 do {
258 if (VECTOR_RESIZE(psargs, len + READ_BLOCK_SIZE) < 0) {
259 return NULL;
260 }
261 rc = read(fn, psargs + len, READ_BLOCK_SIZE);
262 if (rc > 0) {
263 len += rc;
264 }
265 } while (rc == READ_BLOCK_SIZE);
266 close(fn);
267
268 if (rc == -1) {
269 /* Read failed; move on. */
270 continue;
271 }
272
273 /* Turn \0s into spaces within the command line. */
274 ptr = psargs;
275 for(x = 0; x < len; x++) {
276 if (*ptr == '\0') *ptr = ' ';
277 ptr++;
278 }
279
280 if (len == 0) {
281 /* We want psargs to be NULL. */
282 if (VECTOR_RESIZE(psargs, 0) < 0) {
283 return NULL;
284 }
285 } else {
286 /* Not empty, so append a \0. */
287 if (VECTOR_RESIZE(psargs, len + 1) < 0) {
288 return NULL;
289 }
290 psargs[len] = '\0';
291 }
292
293 if (sg_update_string(&proc_state_ptr->proctitle, psargs) < 0) {
294 return NULL;
295 }
296 #endif
297
298 proc_state_size++;
299 }
300 closedir(proc_dir);
301 #endif
302
303 #ifdef ALLBSD
304 mib[0] = CTL_KERN;
305 mib[1] = KERN_PROC;
306 mib[2] = KERN_PROC_ALL;
307
308 if(sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
309 sg_set_error(SG_ERROR_SYSCTL, "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
310 return NULL;
311 }
312
313 procs = size / sizeof(struct kinfo_proc);
314
315 kp_stats = sg_malloc(size);
316 if(kp_stats == NULL) {
317 return NULL;
318 }
319 memset(kp_stats, 0, size);
320
321 if(sysctl(mib, 3, kp_stats, &size, NULL, 0) < 0) {
322 sg_set_error(SG_ERROR_SYSCTL, "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
323 free(kp_stats);
324 return NULL;
325 }
326
327 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
328 kvmd = sg_get_kvm2();
329 #endif
330
331 for (i = 0; i < procs; i++) {
332 const char *name;
333
334 #ifdef FREEBSD5
335 if (kp_stats[i].ki_stat == 0) {
336 #else
337 if (kp_stats[i].kp_proc.p_stat == 0) {
338 #endif
339 /* FreeBSD 5 deliberately overallocates the array that
340 * the sysctl returns, so we'll get a few junk
341 * processes on the end that we have to ignore. (Search
342 * for "overestimate by 5 procs" in
343 * src/sys/kern/kern_proc.c for more details.) */
344 continue;
345 }
346
347 if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
348 return NULL;
349 }
350 proc_state_ptr = proc_state+proc_state_size;
351
352 #ifdef FREEBSD5
353 name = kp_stats[i].ki_comm;
354 #elif defined(DFBSD)
355 name = kp_stats[i].kp_thread.td_comm;
356 #else
357 name = kp_stats[i].kp_proc.p_comm;
358 #endif
359 if (sg_update_string(&proc_state_ptr->process_name, name) < 0) {
360 return NULL;
361 }
362
363 #if defined(FREEBSD5) || defined(NETBSD) || defined(OPENBSD)
364 size = sizeof(buflen);
365
366 #ifdef FREEBSD5
367 if(sysctlbyname("kern.ps_arg_cache_limit", &buflen, &size, NULL, 0) < 0) {
368 sg_set_error(SG_ERROR_SYSCTLBYNAME, "kern.ps_arg_cache_limit");
369 return NULL;
370 }
371 #else
372 /* FIXME - this value can be too large on some of
373 the BSD's, which causes sysctl not to return
374 anything. Maybe we need something smaller? */
375 mib[1] = KERN_ARGMAX;
376
377 if(sysctl(mib, 2, &buflen, &size, NULL, 0) < 0) {
378 sg_set_error(SG_ERROR_SYSCTL, "CTL_KERN.KERN_ARGMAX");
379 return NULL;
380 }
381 #endif
382
383 proctitle = sg_malloc(buflen);
384 if(proctitle == NULL) {
385 return NULL;
386 }
387
388 size = buflen;
389
390 #ifdef FREEBSD5
391 mib[2] = KERN_PROC_ARGS;
392 mib[3] = kp_stats[i].ki_pid;
393 #else
394 mib[1] = KERN_PROC_ARGS;
395 mib[2] = kp_stats[i].kp_proc.p_pid;
396 mib[3] = KERN_PROC_ARGV;
397 #endif
398
399 free(proc_state_ptr->proctitle);
400 if(sysctl(mib, 4, proctitle, &size, NULL, 0) < 0) {
401 free(proctitle);
402 proc_state_ptr->proctitle = NULL;
403 }
404 else if(size > 0) {
405 proc_state_ptr->proctitle = sg_malloc(size+1);
406 if(proc_state_ptr->proctitle == NULL) {
407 return NULL;
408 }
409 p = proctitle;
410 proc_state_ptr->proctitle[0] = '\0';
411 do {
412 sg_strlcat(proc_state_ptr->proctitle, p, size+1);
413 sg_strlcat(proc_state_ptr->proctitle, " ", size+1);
414 p += strlen(p) + 1;
415 } while (p < proctitle + size);
416 free(proctitle);
417 /* remove trailing space */
418 proc_state_ptr->proctitle[strlen(proc_state_ptr->proctitle)-1] = '\0';
419 }
420 else {
421 free(proctitle);
422 proc_state_ptr->proctitle = NULL;
423 }
424 #else
425 free(proc_state_ptr->proctitle);
426 if(kvmd != NULL) {
427 args = kvm_getargv(kvmd, &(kp_stats[i]), 0);
428 if(args != NULL) {
429 argsp = args;
430 while(*argsp != NULL) {
431 argslen += strlen(*argsp) + 1;
432 argsp++;
433 }
434 proctitle = sg_malloc(argslen + 1);
435 proctitle[0] = '\0';
436 if(proctitle == NULL) {
437 return NULL;
438 }
439 while(*args != NULL) {
440 sg_strlcat(proctitle, *args, argslen + 1);
441 sg_strlcat(proctitle, " ", argslen + 1);
442 args++;
443 }
444 /* remove trailing space */
445 proctitle[strlen(proctitle)-1] = '\0';
446 proc_state_ptr->proctitle = proctitle;
447 }
448 else {
449 proc_state_ptr->proctitle = NULL;
450 }
451 }
452 else {
453 proc_state_ptr->proctitle = NULL;
454 }
455 #endif
456
457 #ifdef FREEBSD5
458 proc_state_ptr->pid = kp_stats[i].ki_pid;
459 proc_state_ptr->parent = kp_stats[i].ki_ppid;
460 proc_state_ptr->pgid = kp_stats[i].ki_pgid;
461 #else
462 proc_state_ptr->pid = kp_stats[i].kp_proc.p_pid;
463 proc_state_ptr->parent = kp_stats[i].kp_eproc.e_ppid;
464 proc_state_ptr->pgid = kp_stats[i].kp_eproc.e_pgid;
465 #endif
466
467 #ifdef FREEBSD5
468 proc_state_ptr->uid = kp_stats[i].ki_ruid;
469 proc_state_ptr->euid = kp_stats[i].ki_uid;
470 proc_state_ptr->gid = kp_stats[i].ki_rgid;
471 proc_state_ptr->egid = kp_stats[i].ki_svgid;
472 #elif defined(DFBSD)
473 proc_state_ptr->uid = kp_stats[i].kp_eproc.e_ucred.cr_ruid;
474 proc_state_ptr->euid = kp_stats[i].kp_eproc.e_ucred.cr_svuid;
475 proc_state_ptr->gid = kp_stats[i].kp_eproc.e_ucred.cr_rgid;
476 proc_state_ptr->egid = kp_stats[i].kp_eproc.e_ucred.cr_svgid;
477 #else
478 proc_state_ptr->uid = kp_stats[i].kp_eproc.e_pcred.p_ruid;
479 proc_state_ptr->euid = kp_stats[i].kp_eproc.e_pcred.p_svuid;
480 proc_state_ptr->gid = kp_stats[i].kp_eproc.e_pcred.p_rgid;
481 proc_state_ptr->egid = kp_stats[i].kp_eproc.e_pcred.p_svgid;
482 #endif
483
484 #ifdef FREEBSD5
485 proc_state_ptr->proc_size = kp_stats[i].ki_size;
486 /* This is in pages */
487 proc_state_ptr->proc_resident =
488 kp_stats[i].ki_rssize * getpagesize();
489 /* This is in microseconds */
490 proc_state_ptr->time_spent = kp_stats[i].ki_runtime / 1000000;
491 proc_state_ptr->cpu_percent =
492 ((double)kp_stats[i].ki_pctcpu / FSCALE) * 100.0;
493 proc_state_ptr->nice = kp_stats[i].ki_nice;
494 #else
495 proc_state_ptr->proc_size =
496 kp_stats[i].kp_eproc.e_vm.vm_map.size;
497 /* This is in pages */
498 proc_state_ptr->proc_resident =
499 kp_stats[i].kp_eproc.e_vm.vm_rssize * getpagesize();
500 #if defined(NETBSD) || defined(OPENBSD)
501 proc_state_ptr->time_spent =
502 kp_stats[i].kp_proc.p_rtime.tv_sec;
503 #elif defined(DFBSD)
504 proc_state_ptr->time_spent =
505 ( kp_stats[i].kp_thread.td_uticks +
506 kp_stats[i].kp_thread.td_sticks +
507 kp_stats[i].kp_thread.td_iticks ) / 1000000;
508 #else
509 /* This is in microseconds */
510 proc_state_ptr->time_spent =
511 kp_stats[i].kp_proc.p_runtime / 1000000;
512 #endif
513 proc_state_ptr->cpu_percent =
514 ((double)kp_stats[i].kp_proc.p_pctcpu / FSCALE) * 100.0;
515 proc_state_ptr->nice = kp_stats[i].kp_proc.p_nice;
516 #endif
517
518 #ifdef NETBSD2
519 {
520 size_t size;
521 int mib[5];
522
523 mib[0] = CTL_KERN;
524 mib[1] = KERN_LWP;
525 mib[2] = kp_stats[i].kp_proc.p_pid;
526 mib[3] = sizeof(struct kinfo_lwp);
527 mib[4] = 0;
528
529 if(sysctl(mib, 5, NULL, &size, NULL, 0) < 0) {
530 sg_set_error(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.0");
531 return NULL;
532 }
533
534 lwps = size / sizeof(struct kinfo_lwp);
535 mib[4] = lwps;
536
537 kl_stats = sg_malloc(size);
538 if(kl_stats == NULL) {
539 return NULL;
540 }
541
542 if(sysctl(mib, 5, kl_stats, &size, NULL, 0) < 0) {
543 sg_set_error(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.buffersize");
544 return NULL;
545 }
546 }
547
548 switch(kp_stats[i].kp_proc.p_stat) {
549 case SIDL:
550 proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
551 break;
552 case SACTIVE:
553 {
554 int i;
555
556 for(i = 0; i < lwps; i++) {
557 switch(kl_stats[i].l_stat) {
558 case LSONPROC:
559 case LSRUN:
560 proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
561 goto end;
562 case LSSLEEP:
563 proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
564 goto end;
565 case LSSTOP:
566 case LSSUSPENDED:
567 proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
568 goto end;
569 }
570 proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
571 }
572 end: ;
573 }
574 break;
575 case SSTOP:
576 proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
577 break;
578 case SZOMB:
579 proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
580 break;
581 default:
582 proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
583 break;
584 }
585 #else
586 #ifdef FREEBSD5
587 switch (kp_stats[i].ki_stat) {
588 #else
589 switch (kp_stats[i].kp_proc.p_stat) {
590 #endif
591 case SIDL:
592 case SRUN:
593 #ifdef SONPROC
594 case SONPROC: /* NetBSD */
595 #endif
596 proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
597 break;
598 case SSLEEP:
599 #ifdef SWAIT
600 case SWAIT: /* FreeBSD 5 */
601 #endif
602 #ifdef SLOCK
603 case SLOCK: /* FreeBSD 5 */
604 #endif
605 proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
606 break;
607 case SSTOP:
608 proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
609 break;
610 case SZOMB:
611 #ifdef SDEAD
612 case SDEAD: /* OpenBSD & NetBSD */
613 #endif
614 proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
615 break;
616 default:
617 proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
618 break;
619 }
620 #endif
621 proc_state_size++;
622 }
623
624 free(kp_stats);
625 #endif
626
627 #ifdef CYGWIN
628 sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
629 return NULL;
630 #endif
631
632 *entries = proc_state_size;
633 return proc_state;
634 }
635
636 sg_process_count *sg_get_process_count() {
637 static sg_process_count process_stat;
638 sg_process_stats *ps;
639 int ps_size, x;
640
641 process_stat.sleeping = 0;
642 process_stat.running = 0;
643 process_stat.zombie = 0;
644 process_stat.stopped = 0;
645 process_stat.total = 0;
646
647 ps = sg_get_process_stats(&ps_size);
648 if (ps == NULL) {
649 return NULL;
650 }
651
652 for(x = 0; x < ps_size; x++) {
653 switch (ps->state) {
654 case SG_PROCESS_STATE_RUNNING:
655 process_stat.running++;
656 break;
657 case SG_PROCESS_STATE_SLEEPING:
658 process_stat.sleeping++;
659 break;
660 case SG_PROCESS_STATE_STOPPED:
661 process_stat.stopped++;
662 break;
663 case SG_PROCESS_STATE_ZOMBIE:
664 process_stat.zombie++;
665 break;
666 default:
667 /* currently no mapping for SG_PROCESS_STATE_UNKNOWN in
668 * sg_process_count */
669 break;
670 }
671 ps++;
672 }
673
674 process_stat.total = ps_size;
675
676 return &process_stat;
677 }