#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "os/DecOSF.h" /* Make sure /proc is mounted */ char* OS_initialize() { struct statvfs svfs; static char* no_proc = "/proc unavailable"; if( statvfs("/proc", &svfs) == -1 ) { return no_proc; } return NULL; } /* FIXME we should get minimum info like process ID and ownership from file stat-- does this work for IOCTL-proc? Does it for FS-proc? It does on linux... */ void OS_get_table() { int maxproc, procnum, procbase; int psdata; char pathbuf[MAXPATHLEN]; /* defined in */ struct tbl_procinfo pstbl[PROCCNT]; /* defined in */ struct prpsinfo psbuf; struct prcred pscredbuf; /* variables to hold some values for bless_into_proc */ char state[20]; char pctcpu[7]; char pctmem[7]; long pr_age, now; uid_t *psgroups; int i; AV *group_array; SV *group_ref; if( (maxproc = table( TBL_PROCINFO, 0, NULL, (unsigned int) -1, 0 )) == -1 ) return; /* loop over all processes */ procbase = -1; for( procnum = 0; procnum < maxproc; procnum ++) { /* Get the table entries */ if( (procbase < 0) || (procnum >= (procbase + PROCCNT)) ) { procbase = procnum; if( table( TBL_PROCINFO, procbase, pstbl, PROCCNT, sizeof (struct tbl_procinfo)) == -1 ) continue; } /* See if the process exists */ if( pstbl[procnum % PROCCNT].pi_status == PI_EMPTY ) continue; /* Construct path of the form /proc/proc_number */ sprintf( pathbuf, "/proc/%d", pstbl[procnum % PROCCNT].pi_pid ); if( (psdata = open( pathbuf, O_RDONLY )) == -1 ) continue; if( ioctl(psdata, PIOCPSINFO, &psbuf) == -1 ) continue; if( ioctl(psdata, PIOCCRED, &pscredbuf) == -1 ) continue; if( (psgroups = malloc(pscredbuf.pr_ngroups * sizeof (u_int))) == NULL ) continue; if( ioctl(psdata, PIOCGROUPS, psgroups) == -1 ) { free(psgroups); continue; } close(psdata); /* translate process state, makros defined in */ switch( psbuf.pr_state) { case SSLEEP: strcpy(state, SLEEP); break; case SWAIT: strcpy(state, WAIT); break; case SRUN: strcpy(state, RUN); break; case SZOMB: strcpy(state, ZOMBIE); break; case SSTOP: strcpy(state, STOP); break; case SIDL: strcpy(state, IDLE); break; } now = time(NULL); pr_age = now - psbuf.pr_start.tv_sec; if (pr_age < 1) { sprintf( pctcpu, "%3.2f", (float) 0.0); /* pr_time.tv_sec is 0 */ } else { sprintf( pctcpu, "%3.2f", (float) ((psbuf.pr_time.tv_sec * 100) / pr_age)); } /* create groups array */ group_array = newAV(); for (i = 0; i < pscredbuf.pr_ngroups; i++) { av_push(group_array, newSViv(psgroups[i])); } free(psgroups); group_ref = newRV_noinc((SV *) group_array); bless_into_proc( Format, Fields, psbuf.pr_uid, /* uid, uid_t is int */ psbuf.pr_gid, /* gid, gid_t is int */ pscredbuf.pr_euid, /* euid, uid_t is int */ pscredbuf.pr_egid, /* egid, uid_t is int */ pscredbuf.pr_suid, /* suid, uid_t is int */ pscredbuf.pr_sgid, /* sgid, uid_t is int */ group_ref, /* groups, perl ref to array */ psbuf.pr_pid, /* pid, pid_t is int */ psbuf.pr_ppid, /* ppid, pid_t is int */ psbuf.pr_pgrp, /* pgrp, pid_t is int */ psbuf.pr_sid, /* sess, pid_t is int */ psbuf.pr_pri, /* priority, long, */ psbuf.pr_ttydev, /* ttynum, dev_t is int */ psbuf.pr_flag, /* flags, u_long */ psbuf.pr_time.tv_sec, /* time, long */ psbuf.pr_size * getpagesize(), /* size (bytes) */ psbuf.pr_rssize * getpagesize(), /* rss (bytes) */ psbuf.pr_start.tv_sec, /* start */ psbuf.pr_fname, /* fname */ pctcpu, /* pctcpu */ state, /* state */ psbuf.pr_psargs /* cmndline */ ); } }