version 1.19, 2000/06/18 17:59:56 |
version 1.20, 2001/02/17 22:51:26 |
|
|
|
|
/* get_process_info passes back a handle. This is what it looks like: */ |
/* get_process_info passes back a handle. This is what it looks like: */ |
|
|
struct handle |
struct handle { |
{ |
struct kinfo_proc **next_proc; /* points to next valid proc pointer */ |
struct kinfo_proc **next_proc; /* points to next valid proc pointer */ |
int remaining; /* number of pointers remaining */ |
int remaining; /* number of pointers remaining */ |
|
}; |
}; |
|
|
/* declarations for load_avg */ |
/* declarations for load_avg */ |
|
|
#define X_CP_TIME 0 |
#define X_CP_TIME 0 |
|
|
static struct nlist nlst[] = { |
static struct nlist nlst[] = { |
{ "_cp_time" }, /* 0 */ |
{"_cp_time"}, /* 0 */ |
{ 0 } |
{0} |
}; |
}; |
|
|
/* |
/* |
* These definitions control the format of the per-process area |
* These definitions control the format of the per-process area |
*/ |
*/ |
|
|
static char header[] = |
static char header[] = |
" PID X PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND"; |
" PID X PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND"; |
/* 0123456 -- field to fill in starts at header+6 */ |
/* 0123456 -- field to fill in starts at header+6 */ |
#define UNAME_START 6 |
#define UNAME_START 6 |
|
|
|
|
/* the extra nulls in the string "run" are for adding a slash and |
/* the extra nulls in the string "run" are for adding a slash and |
the processor number when needed */ |
the processor number when needed */ |
|
|
char *state_abbrev[] = |
char *state_abbrev[] = { |
{ |
"", "start", "run\0\0\0", "sleep", "stop", "zomb", |
"", "start", "run\0\0\0", "sleep", "stop", "zomb", |
|
}; |
}; |
|
|
|
|
|
|
|
|
/* these are retrieved from the kernel in _init */ |
/* these are retrieved from the kernel in _init */ |
|
|
static int stathz; |
static int stathz; |
|
|
/* these are offsets obtained via nlist and used in the get_ functions */ |
/* these are offsets obtained via nlist and used in the get_ functions */ |
|
|
|
|
static long cp_diff[CPUSTATES]; |
static long cp_diff[CPUSTATES]; |
|
|
/* these are for detailing the process states */ |
/* these are for detailing the process states */ |
|
int process_states[7]; |
int process_states[7]; |
char *procstatenames[] = { |
char *procstatenames[] = { |
"", " starting, ", " running, ", " idle, ", " stopped, ", " zombie, ", |
"", " starting, ", " running, ", " idle, ", " stopped, ", " zombie, ", |
NULL |
NULL |
|
}; |
}; |
|
|
/* these are for detailing the cpu states */ |
/* these are for detailing the cpu states */ |
|
int cpu_states[CPUSTATES]; |
int cpu_states[CPUSTATES]; |
char *cpustatenames[] = { |
char *cpustatenames[] = { |
"user", "nice", "system", "interrupt", "idle", NULL |
"user", "nice", "system", "interrupt", "idle", NULL |
|
}; |
}; |
|
|
/* these are for detailing the memory statistics */ |
/* these are for detailing the memory statistics */ |
|
int memory_stats[8]; |
int memory_stats[8]; |
char *memorynames[] = { |
char *memorynames[] = { |
"Real: ", "K/", "K act/tot ", "Free: ", "K ", |
"Real: ", "K/", "K act/tot ", "Free: ", "K ", |
|
#ifdef DOSWAP |
#ifdef DOSWAP |
"Swap: ", "K/", "K used/tot", |
"Swap: ", "K/", "K used/tot", |
#endif |
#endif |
NULL |
NULL |
}; |
}; |
|
|
#ifdef ORDER |
#ifdef ORDER |
/* these are names given to allowed sorting orders -- first is default */ |
/* these are names given to allowed sorting orders -- first is default */ |
|
char *ordernames[] = {"cpu", "size", "res", "time", "pri", NULL}; |
char *ordernames[] = {"cpu", "size", "res", "time", "pri", NULL}; |
|
#endif |
#endif |
|
|
/* these are for keeping track of the proc array */ |
/* these are for keeping track of the proc array */ |
|
|
static int nproc; |
static int nproc; |
static int onproc = -1; |
static int onproc = -1; |
static int pref_len; |
static int pref_len; |
|
|
static struct kinfo_proc **pref; |
static struct kinfo_proc **pref; |
|
|
/* these are for getting the memory statistics */ |
/* these are for getting the memory statistics */ |
|
|
static int pageshift; /* log base 2 of the pagesize */ |
static int pageshift; /* log base 2 of the pagesize */ |
|
|
/* define pagetok in terms of pageshift */ |
/* define pagetok in terms of pageshift */ |
|
|
#define pagetok(size) ((size) << pageshift) |
#define pagetok(size) ((size) << pageshift) |
|
|
int |
int |
getstathz() |
getstathz() |
{ |
{ |
int mib[2]; |
|
struct clockinfo cinf; |
struct clockinfo cinf; |
size_t size = sizeof(cinf); |
size_t size = sizeof(cinf); |
|
int mib[2]; |
|
|
mib[0] = CTL_KERN; |
mib[0] = CTL_KERN; |
mib[1] = KERN_CLOCKRATE; |
mib[1] = KERN_CLOCKRATE; |
|
|
|
|
int |
int |
machine_init(statics) |
machine_init(statics) |
struct statics *statics; |
struct statics *statics; |
{ |
{ |
register int i = 0; |
char errbuf[_POSIX2_LINE_MAX]; |
register int pagesize; |
int pagesize, i = 0; |
char errbuf[_POSIX2_LINE_MAX]; |
|
|
|
if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) { |
if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) { |
warnx("%s", errbuf); |
warnx("%s", errbuf); |
return(-1); |
return (-1); |
} |
} |
|
setegid(getgid()); |
|
setgid(getgid()); |
|
|
setegid(getgid()); |
/* get the list of symbols we want to access in the kernel */ |
setgid(getgid()); |
if (kvm_nlist(kd, nlst) < 0) { |
|
warnx("nlist failed"); |
|
return (-1); |
|
} |
|
/* make sure they were all found */ |
|
if (i > 0 && check_nlist(nlst) > 0) |
|
return (-1); |
|
|
/* get the list of symbols we want to access in the kernel */ |
stathz = getstathz(); |
if (kvm_nlist(kd, nlst) < 0) { |
if (stathz == -1) |
warnx("nlist failed"); |
return (-1); |
return(-1); |
|
} |
|
|
|
/* make sure they were all found */ |
/* stash away certain offsets for later use */ |
if (i > 0 && check_nlist(nlst) > 0) |
cp_time_offset = nlst[X_CP_TIME].n_value; |
return(-1); |
|
|
|
stathz = getstathz(); |
pbase = NULL; |
if (stathz == -1) |
pref = NULL; |
return(-1); |
onproc = -1; |
|
nproc = 0; |
|
|
/* stash away certain offsets for later use */ |
/* get the page size with "getpagesize" and calculate pageshift from |
cp_time_offset = nlst[X_CP_TIME].n_value; |
* it */ |
|
pagesize = getpagesize(); |
|
pageshift = 0; |
|
while (pagesize > 1) { |
|
pageshift++; |
|
pagesize >>= 1; |
|
} |
|
|
pbase = NULL; |
/* we only need the amount of log(2)1024 for our conversion */ |
pref = NULL; |
pageshift -= LOG1024; |
onproc = -1; |
|
nproc = 0; |
|
|
|
/* get the page size with "getpagesize" and calculate pageshift from it */ |
/* fill in the statics information */ |
pagesize = getpagesize(); |
statics->procstate_names = procstatenames; |
pageshift = 0; |
statics->cpustate_names = cpustatenames; |
while (pagesize > 1) |
statics->memory_names = memorynames; |
{ |
|
pageshift++; |
|
pagesize >>= 1; |
|
} |
|
|
|
/* we only need the amount of log(2)1024 for our conversion */ |
|
pageshift -= LOG1024; |
|
|
|
/* fill in the statics information */ |
|
statics->procstate_names = procstatenames; |
|
statics->cpustate_names = cpustatenames; |
|
statics->memory_names = memorynames; |
|
#ifdef ORDER |
#ifdef ORDER |
statics->order_names = ordernames; |
statics->order_names = ordernames; |
#endif |
#endif |
|
return (0); |
/* all done! */ |
|
return(0); |
|
} |
} |
|
|
char *format_header(uname_field) |
char * |
|
format_header(uname_field) |
register char *uname_field; |
char *uname_field; |
|
|
{ |
{ |
register char *ptr; |
char *ptr; |
|
|
ptr = header + UNAME_START; |
ptr = header + UNAME_START; |
while (*uname_field != '\0') |
while (*uname_field != '\0') { |
{ |
*ptr++ = *uname_field++; |
*ptr++ = *uname_field++; |
} |
} |
return (header); |
|
|
return(header); |
|
} |
} |
|
|
void |
void |
get_system_info(si) |
get_system_info(si) |
|
struct system_info *si; |
struct system_info *si; |
|
|
|
{ |
{ |
int total; |
static int sysload_mib[] = {CTL_VM, VM_LOADAVG}; |
|
static int vmtotal_mib[] = {CTL_VM, VM_METER}; |
/* get the cp_time array */ |
|
(void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time), |
|
"_cp_time"); |
|
|
|
/* convert load averages to doubles */ |
|
{ |
|
register int i; |
|
register double *infoloadp; |
|
struct loadavg sysload; |
struct loadavg sysload; |
size_t size = sizeof(sysload); |
struct vmtotal vmtotal; |
static int mib[] = { CTL_VM, VM_LOADAVG }; |
double *infoloadp; |
|
int total, i; |
|
size_t size; |
|
|
if (sysctl(mib, 2, &sysload, &size, NULL, 0) < 0) { |
/* get the cp_time array */ |
warn("sysctl failed"); |
(void) getkval(cp_time_offset, (int *) cp_time, sizeof(cp_time), |
bzero(&total, sizeof(total)); |
"_cp_time"); |
} |
|
|
|
|
size = sizeof(sysload); |
|
if (sysctl(sysload_mib, 2, &sysload, &size, NULL, 0) < 0) { |
|
warn("sysctl failed"); |
|
bzero(&total, sizeof(total)); |
|
} |
infoloadp = si->load_avg; |
infoloadp = si->load_avg; |
for (i = 0; i < 3; i++) |
for (i = 0; i < 3; i++) |
*infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale; |
*infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale; |
} |
|
|
|
/* convert cp_time counts to percentages */ |
/* convert cp_time counts to percentages */ |
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); |
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); |
|
|
/* sum memory statistics */ |
|
{ |
|
struct vmtotal total; |
|
size_t size = sizeof(total); |
|
static int mib[] = { CTL_VM, VM_METER }; |
|
|
|
/* get total -- systemwide main memory usage structure */ |
/* get total -- systemwide main memory usage structure */ |
if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { |
size = sizeof(vmtotal); |
warn("sysctl failed"); |
if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0) { |
bzero(&total, sizeof(total)); |
warn("sysctl failed"); |
|
bzero(&vmtotal, sizeof(vmtotal)); |
} |
} |
/* convert memory stats to Kbytes */ |
/* convert memory stats to Kbytes */ |
memory_stats[0] = -1; |
memory_stats[0] = -1; |
memory_stats[1] = pagetok(total.t_arm); |
memory_stats[1] = pagetok(vmtotal.t_arm); |
memory_stats[2] = pagetok(total.t_rm); |
memory_stats[2] = pagetok(vmtotal.t_rm); |
memory_stats[3] = -1; |
memory_stats[3] = -1; |
memory_stats[4] = pagetok(total.t_free); |
memory_stats[4] = pagetok(vmtotal.t_free); |
memory_stats[5] = -1; |
memory_stats[5] = -1; |
#ifdef DOSWAP |
#ifdef DOSWAP |
if (!swapmode(&memory_stats[6], &memory_stats[7])) { |
if (!swapmode(&memory_stats[6], &memory_stats[7])) { |
memory_stats[6] = 0; |
memory_stats[6] = 0; |
memory_stats[7] = 0; |
memory_stats[7] = 0; |
} |
} |
#endif |
#endif |
} |
|
|
|
/* set arrays and strings */ |
/* set arrays and strings */ |
si->cpustates = cpu_states; |
si->cpustates = cpu_states; |
si->memory = memory_stats; |
si->memory = memory_stats; |
si->last_pid = -1; |
si->last_pid = -1; |
} |
} |
|
|
static struct handle handle; |
static struct handle handle; |
|
|
caddr_t get_process_info(si, sel, compare) |
caddr_t |
|
get_process_info(si, sel, compare) |
|
struct system_info *si; |
|
struct process_select *sel; |
|
int (*compare) __P((const void *, const void *)); |
|
|
struct system_info *si; |
|
struct process_select *sel; |
|
int (*compare) __P((const void *, const void *)); |
|
|
|
{ |
{ |
register int i; |
int show_idle, show_system, show_uid, show_command; |
register int total_procs; |
int total_procs, active_procs, i; |
register int active_procs; |
struct kinfo_proc **prefp, *pp; |
register struct kinfo_proc **prefp; |
|
register struct kinfo_proc *pp; |
|
|
|
/* these are copied out of sel for speed */ |
if ((pbase = kvm_getprocs(kd, KERN_PROC_KTHREAD, 0, &nproc)) == NULL) { |
int show_idle; |
warnx("%s", kvm_geterr(kd)); |
int show_system; |
quit(23); |
int show_uid; |
} |
int show_command; |
if (nproc > onproc) |
|
pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *) |
|
* (onproc = nproc)); |
|
if (pref == NULL) { |
|
warnx("Out of memory."); |
|
quit(23); |
|
} |
|
/* get a pointer to the states summary array */ |
|
si->procstates = process_states; |
|
|
|
/* set up flags which define what we are going to select */ |
if ((pbase = kvm_getprocs(kd, KERN_PROC_KTHREAD, 0, &nproc)) == NULL) { |
show_idle = sel->idle; |
warnx("%s", kvm_geterr(kd)); |
show_system = sel->system; |
quit(23); |
show_uid = sel->uid != -1; |
} |
show_command = sel->command != NULL; |
if (nproc > onproc) |
|
pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *) |
|
* (onproc = nproc)); |
|
if (pref == NULL) { |
|
warnx("Out of memory."); |
|
quit(23); |
|
} |
|
/* get a pointer to the states summary array */ |
|
si->procstates = process_states; |
|
|
|
/* set up flags which define what we are going to select */ |
/* count up process states and get pointers to interesting procs */ |
show_idle = sel->idle; |
total_procs = 0; |
show_system = sel->system; |
active_procs = 0; |
show_uid = sel->uid != -1; |
memset((char *) process_states, 0, sizeof(process_states)); |
show_command = sel->command != NULL; |
prefp = pref; |
|
for (pp = pbase, i = 0; i < nproc; pp++, i++) { |
|
/* |
|
* Place pointers to each valid proc structure in pref[]. |
|
* Process slots that are actually in use have a non-zero |
|
* status field. Processes with SSYS set are system |
|
* processes---these get ignored unless show_sysprocs is set. |
|
*/ |
|
if (PP(pp, p_stat) != 0 && |
|
(show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0))) { |
|
total_procs++; |
|
process_states[(unsigned char) PP(pp, p_stat)]++; |
|
if ((PP(pp, p_stat) != SZOMB) && |
|
(show_idle || (PP(pp, p_pctcpu) != 0) || |
|
(PP(pp, p_stat) == SRUN)) && |
|
(!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t) sel->uid)) { |
|
*prefp++ = pp; |
|
active_procs++; |
|
} |
|
} |
|
} |
|
|
/* count up process states and get pointers to interesting procs */ |
/* if requested, sort the "interesting" processes */ |
total_procs = 0; |
if (compare != NULL) { |
active_procs = 0; |
qsort((char *) pref, active_procs, sizeof(struct kinfo_proc *), compare); |
memset((char *)process_states, 0, sizeof(process_states)); |
|
prefp = pref; |
|
for (pp = pbase, i = 0; i < nproc; pp++, i++) |
|
{ |
|
/* |
|
* Place pointers to each valid proc structure in pref[]. |
|
* Process slots that are actually in use have a non-zero |
|
* status field. Processes with SSYS set are system |
|
* processes---these get ignored unless show_sysprocs is set. |
|
*/ |
|
if (PP(pp, p_stat) != 0 && |
|
(show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0))) |
|
{ |
|
total_procs++; |
|
process_states[(unsigned char) PP(pp, p_stat)]++; |
|
if ((PP(pp, p_stat) != SZOMB) && |
|
(show_idle || (PP(pp, p_pctcpu) != 0) || |
|
(PP(pp, p_stat) == SRUN)) && |
|
(!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t)sel->uid)) |
|
{ |
|
*prefp++ = pp; |
|
active_procs++; |
|
} |
|
} |
} |
} |
/* remember active and total counts */ |
|
si->p_total = total_procs; |
|
si->p_active = pref_len = active_procs; |
|
|
/* if requested, sort the "interesting" processes */ |
/* pass back a handle */ |
if (compare != NULL) |
handle.next_proc = pref; |
{ |
handle.remaining = active_procs; |
qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare); |
return ((caddr_t) & handle); |
} |
|
|
|
/* remember active and total counts */ |
|
si->p_total = total_procs; |
|
si->p_active = pref_len = active_procs; |
|
|
|
/* pass back a handle */ |
|
handle.next_proc = pref; |
|
handle.remaining = active_procs; |
|
return((caddr_t)&handle); |
|
} |
} |
|
|
char fmt[MAX_COLS]; /* static area where result is built */ |
char fmt[MAX_COLS]; /* static area where result is built */ |
|
|
char *format_next_process(handle, get_userid) |
char * |
|
format_next_process(handle, get_userid) |
|
caddr_t handle; |
|
char *(*get_userid)(); |
|
|
caddr_t handle; |
|
char *(*get_userid)(); |
|
|
|
{ |
{ |
register struct kinfo_proc *pp; |
char waddr[sizeof(void *) * 2 + 3]; /* Hexify void pointer */ |
register int cputime; |
struct kinfo_proc *pp; |
register double pct; |
struct handle *hp; |
struct handle *hp; |
char *p_wait; |
char waddr[sizeof(void *) * 2 + 3]; /* Hexify void pointer */ |
int cputime; |
char *p_wait; |
double pct; |
|
|
/* find and remember the next proc structure */ |
/* find and remember the next proc structure */ |
hp = (struct handle *)handle; |
hp = (struct handle *) handle; |
pp = *(hp->next_proc++); |
pp = *(hp->next_proc++); |
hp->remaining--; |
hp->remaining--; |
|
|
|
|
/* get the process's user struct and set cputime */ |
/* get the process's user struct and set cputime */ |
if ((PP(pp, p_flag) & P_INMEM) == 0) { |
if ((PP(pp, p_flag) & P_INMEM) == 0) { |
/* |
/* |
* Print swapped processes as <pname> |
* Print swapped processes as <pname> |
*/ |
*/ |
char *comm = PP(pp, p_comm); |
char *comm = PP(pp, p_comm); |
#define COMSIZ sizeof(PP(pp, p_comm)) |
#define COMSIZ sizeof(PP(pp, p_comm)) |
char buf[COMSIZ]; |
char buf[COMSIZ]; |
(void) strncpy(buf, comm, COMSIZ); |
(void) strncpy(buf, comm, COMSIZ); |
comm[0] = '<'; |
comm[0] = '<'; |
(void) strncpy(&comm[1], buf, COMSIZ - 2); |
(void) strncpy(&comm[1], buf, COMSIZ - 2); |
comm[COMSIZ - 2] = '\0'; |
comm[COMSIZ - 2] = '\0'; |
(void) strncat(comm, ">", COMSIZ - 1); |
(void) strncat(comm, ">", COMSIZ - 1); |
comm[COMSIZ - 1] = '\0'; |
comm[COMSIZ - 1] = '\0'; |
} |
} |
|
cputime = (PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks)) / stathz; |
|
|
cputime = (PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks)) / stathz; |
/* calculate the base for cpu percentages */ |
|
pct = pctdouble(PP(pp, p_pctcpu)); |
|
|
/* calculate the base for cpu percentages */ |
if (PP(pp, p_wchan)) |
pct = pctdouble(PP(pp, p_pctcpu)); |
if (PP(pp, p_wmesg)) |
|
p_wait = EP(pp, e_wmesg); |
|
else { |
|
snprintf(waddr, sizeof(waddr), "%lx", |
|
(unsigned long) (PP(pp, p_wchan)) & ~KERNBASE); |
|
p_wait = waddr; |
|
} |
|
else |
|
p_wait = "-"; |
|
|
if (PP(pp, p_wchan)) |
/* format this entry */ |
if (PP(pp, p_wmesg)) |
snprintf(fmt, MAX_COLS, |
p_wait = EP(pp, e_wmesg); |
|
else { |
|
snprintf(waddr, sizeof(waddr), "%lx", |
|
(unsigned long)(PP(pp, p_wchan)) & ~KERNBASE); |
|
p_wait = waddr; |
|
} |
|
else |
|
p_wait = "-"; |
|
|
|
/* format this entry */ |
|
snprintf(fmt, MAX_COLS, |
|
Proc_format, |
Proc_format, |
PP(pp, p_pid), |
PP(pp, p_pid), |
(*get_userid)(EP(pp, e_pcred.p_ruid)), |
(*get_userid) (EP(pp, e_pcred.p_ruid)), |
PP(pp, p_priority) - PZERO, |
PP(pp, p_priority) - PZERO, |
PP(pp, p_nice) - NZERO, |
PP(pp, p_nice) - NZERO, |
format_k(pagetok(PROCSIZE(pp))), |
format_k(pagetok(PROCSIZE(pp))), |
format_k(pagetok(VP(pp, vm_rssize))), |
format_k(pagetok(VP(pp, vm_rssize))), |
(PP(pp, p_stat) == SSLEEP && PP(pp, p_slptime) > MAXSLP) |
(PP(pp, p_stat) == SSLEEP && PP(pp, p_slptime) > MAXSLP) |
? "idle" : state_abbrev[(unsigned char) PP(pp, p_stat)], |
? "idle" : state_abbrev[(unsigned char) PP(pp, p_stat)], |
p_wait, |
p_wait, |
format_time(cputime), |
format_time(cputime), |
100.0 * pct, |
100.0 * pct, |
printable(PP(pp, p_comm))); |
printable(PP(pp, p_comm))); |
|
|
/* return the result */ |
/* return the result */ |
return(fmt); |
return (fmt); |
} |
} |
|
|
|
|
|
|
* message is printed to stderr. The routine returns the |
* message is printed to stderr. The routine returns the |
* number of symbols NOT found. |
* number of symbols NOT found. |
*/ |
*/ |
|
int |
static int check_nlist(nlst) |
check_nlist(nlst) |
|
struct nlist *nlst; |
register struct nlist *nlst; |
|
|
|
{ |
{ |
register int i; |
int i; |
|
|
/* check to see if we got ALL the symbols we requested */ |
/* check to see if we got ALL the symbols we requested */ |
/* this will write one line to stderr for every symbol not found */ |
/* this will write one line to stderr for every symbol not found */ |
|
|
i = 0; |
i = 0; |
while (nlst->n_name != NULL) |
while (nlst->n_name != NULL) { |
{ |
if (nlst->n_type == 0) { |
if (nlst->n_type == 0) |
/* this one wasn't found */ |
{ |
(void) fprintf(stderr, "kernel: no symbol named `%s'\n", |
/* this one wasn't found */ |
nlst->n_name); |
(void) fprintf(stderr, "kernel: no symbol named `%s'\n", |
i = 1; |
nlst->n_name); |
} |
i = 1; |
nlst++; |
} |
} |
nlst++; |
|
} |
|
|
|
return(i); |
return (i); |
} |
} |
|
|
|
|
|
|
* if "refstr" starts with a '!', then a failure on read will not |
* if "refstr" starts with a '!', then a failure on read will not |
* be fatal (this may seem like a silly way to do things, but I |
* be fatal (this may seem like a silly way to do things, but I |
* really didn't want the overhead of another argument). |
* really didn't want the overhead of another argument). |
* |
* |
*/ |
*/ |
|
int |
static int getkval(offset, ptr, size, refstr) |
getkval(offset, ptr, size, refstr) |
|
unsigned long offset; |
unsigned long offset; |
int *ptr; |
int *ptr; |
int size; |
int size; |
char *refstr; |
char *refstr; |
|
|
|
{ |
{ |
if (kvm_read(kd, offset, ptr, size) != size) |
if (kvm_read(kd, offset, ptr, size) != size) { |
{ |
if (*refstr == '!') { |
if (*refstr == '!') |
return (0); |
{ |
} else { |
return(0); |
warn("kvm_read for %s", refstr); |
|
quit(23); |
|
} |
} |
} |
else |
return (1); |
{ |
|
warn("kvm_read for %s", refstr); |
|
quit(23); |
|
} |
|
} |
|
return(1); |
|
} |
} |
|
|
/* comparison routine for qsort */ |
/* comparison routine for qsort */ |
|
|
static unsigned char sorted_state[] = |
static unsigned char sorted_state[] = |
{ |
{ |
0, /* not used */ |
0, /* not used */ |
4, /* start */ |
4, /* start */ |
5, /* run */ |
5, /* run */ |
2, /* sleep */ |
2, /* sleep */ |
3, /* stop */ |
3, /* stop */ |
1 /* zombie */ |
1 /* zombie */ |
}; |
}; |
|
|
#ifdef ORDER |
#ifdef ORDER |
|
|
/* |
/* |
|
|
#define ORDERKEY_MEM \ |
#define ORDERKEY_MEM \ |
if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0) |
if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0) |
|
|
|
|
/* compare_cpu - the comparison function for sorting by cpu percentage */ |
|
|
|
|
/* compare_cpu - the comparison function for sorting by cpu percentage */ |
int |
int |
compare_cpu(v1, v2) |
compare_cpu(v1, v2) |
|
const void *v1, *v2; |
const void *v1, *v2; |
|
|
|
{ |
{ |
register struct proc **pp1 = (struct proc **)v1; |
struct proc **pp1 = (struct proc **) v1; |
register struct proc **pp2 = (struct proc **)v2; |
struct proc **pp2 = (struct proc **) v2; |
register struct kinfo_proc *p1; |
struct kinfo_proc *p1; |
register struct kinfo_proc *p2; |
struct kinfo_proc *p2; |
register int result; |
int result; |
register pctcpu lresult; |
pctcpu lresult; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc **) pp2; |
|
|
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
ORDERKEY_CPUTIME |
ORDERKEY_CPUTIME |
ORDERKEY_STATE |
ORDERKEY_STATE |
ORDERKEY_PRIO |
ORDERKEY_PRIO |
ORDERKEY_RSSIZE |
ORDERKEY_RSSIZE |
ORDERKEY_MEM |
ORDERKEY_MEM |
; |
; |
return(result); |
return (result); |
} |
} |
|
|
/* compare_size - the comparison function for sorting by total memory usage */ |
/* compare_size - the comparison function for sorting by total memory usage */ |
|
|
int |
int |
compare_size(v1, v2) |
compare_size(v1, v2) |
|
const void *v1, *v2; |
const void *v1, *v2; |
|
|
|
{ |
{ |
register struct proc **pp1 = (struct proc **)v1; |
struct proc **pp1 = (struct proc **) v1; |
register struct proc **pp2 = (struct proc **)v2; |
struct proc **pp2 = (struct proc **) v2; |
register struct kinfo_proc *p1; |
struct kinfo_proc *p1; |
register struct kinfo_proc *p2; |
struct kinfo_proc *p2; |
register int result; |
int result; |
register pctcpu lresult; |
pctcpu lresult; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc **) pp2; |
|
|
ORDERKEY_MEM |
ORDERKEY_MEM |
ORDERKEY_RSSIZE |
ORDERKEY_RSSIZE |
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
ORDERKEY_CPUTIME |
ORDERKEY_CPUTIME |
ORDERKEY_STATE |
ORDERKEY_STATE |
ORDERKEY_PRIO |
ORDERKEY_PRIO |
; |
; |
|
return (result); |
return(result); |
|
} |
} |
|
|
/* compare_res - the comparison function for sorting by resident set size */ |
/* compare_res - the comparison function for sorting by resident set size */ |
|
|
int |
int |
compare_res(v1, v2) |
compare_res(v1, v2) |
|
const void *v1, *v2; |
const void *v1, *v2; |
|
|
|
{ |
{ |
register struct proc **pp1 = (struct proc **)v1; |
struct proc **pp1 = (struct proc **) v1; |
register struct proc **pp2 = (struct proc **)v2; |
struct proc **pp2 = (struct proc **) v2; |
register struct kinfo_proc *p1; |
struct kinfo_proc *p1; |
register struct kinfo_proc *p2; |
struct kinfo_proc *p2; |
register int result; |
int result; |
register pctcpu lresult; |
pctcpu lresult; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc **) pp2; |
|
|
ORDERKEY_RSSIZE |
ORDERKEY_RSSIZE |
ORDERKEY_MEM |
ORDERKEY_MEM |
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
ORDERKEY_CPUTIME |
ORDERKEY_CPUTIME |
ORDERKEY_STATE |
ORDERKEY_STATE |
ORDERKEY_PRIO |
ORDERKEY_PRIO |
; |
; |
|
return (result); |
return(result); |
|
} |
} |
|
|
/* compare_time - the comparison function for sorting by CPU time */ |
/* compare_time - the comparison function for sorting by CPU time */ |
|
|
int |
int |
compare_time(v1, v2) |
compare_time(v1, v2) |
|
const void *v1, *v2; |
const void *v1, *v2; |
|
|
|
{ |
{ |
register struct proc **pp1 = (struct proc **)v1; |
struct proc **pp1 = (struct proc **) v1; |
register struct proc **pp2 = (struct proc **)v2; |
struct proc **pp2 = (struct proc **) v2; |
register struct kinfo_proc *p1; |
struct kinfo_proc *p1; |
register struct kinfo_proc *p2; |
struct kinfo_proc *p2; |
register int result; |
int result; |
register pctcpu lresult; |
pctcpu lresult; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc **) pp2; |
|
|
ORDERKEY_CPUTIME |
ORDERKEY_CPUTIME |
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
ORDERKEY_STATE |
ORDERKEY_STATE |
ORDERKEY_PRIO |
ORDERKEY_PRIO |
ORDERKEY_MEM |
ORDERKEY_MEM |
ORDERKEY_RSSIZE |
ORDERKEY_RSSIZE |
; |
; |
|
return (result); |
return(result); |
|
} |
} |
|
|
/* compare_prio - the comparison function for sorting by CPU time */ |
/* compare_prio - the comparison function for sorting by CPU time */ |
|
|
int |
int |
compare_prio(v1, v2) |
compare_prio(v1, v2) |
|
const void *v1, *v2; |
const void *v1, *v2; |
|
|
|
{ |
{ |
register struct proc **pp1 = (struct proc **)v1; |
struct proc **pp1 = (struct proc **) v1; |
register struct proc **pp2 = (struct proc **)v2; |
struct proc **pp2 = (struct proc **) v2; |
register struct kinfo_proc *p1; |
struct kinfo_proc *p1; |
register struct kinfo_proc *p2; |
struct kinfo_proc *p2; |
register int result; |
int result; |
register pctcpu lresult; |
pctcpu lresult; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc **) pp2; |
|
|
ORDERKEY_PRIO |
ORDERKEY_PRIO |
ORDERKEY_PCTCPU |
ORDERKEY_PCTCPU |
ORDERKEY_CPUTIME |
ORDERKEY_CPUTIME |
ORDERKEY_STATE |
ORDERKEY_STATE |
ORDERKEY_RSSIZE |
ORDERKEY_RSSIZE |
ORDERKEY_MEM |
ORDERKEY_MEM |
; |
; |
|
return (result); |
return(result); |
|
} |
} |
|
|
int (*proc_compares[])() = { |
int (*proc_compares[]) () = { |
compare_cpu, |
compare_cpu, |
compare_size, |
compare_size, |
compare_res, |
compare_res, |
compare_time, |
compare_time, |
compare_prio, |
compare_prio, |
NULL |
NULL |
}; |
}; |
#else |
#else |
/* |
/* |
* proc_compare - comparison function for "qsort" |
* proc_compare - comparison function for "qsort" |
* Compares the resource consumption of two processes using five |
* Compares the resource consumption of two processes using five |
|
|
* declaration below maps a process state index into a number that |
* declaration below maps a process state index into a number that |
* reflects this ordering. |
* reflects this ordering. |
*/ |
*/ |
|
|
int |
int |
proc_compare(v1, v2) |
proc_compare(v1, v2) |
|
const void *v1, *v2; |
const void *v1, *v2; |
|
|
|
{ |
{ |
register struct proc **pp1 = (struct proc **)v1; |
struct proc **pp1 = (struct proc **) v1; |
register struct proc **pp2 = (struct proc **)v2; |
struct proc **pp2 = (struct proc **) v2; |
register struct kinfo_proc *p1; |
struct kinfo_proc *p1; |
register struct kinfo_proc *p2; |
struct kinfo_proc *p2; |
register int result; |
int result; |
register pctcpu lresult; |
pctcpu lresult; |
|
|
/* remove one level of indirection */ |
/* remove one level of indirection */ |
p1 = *(struct kinfo_proc **) pp1; |
p1 = *(struct kinfo_proc **) pp1; |
p2 = *(struct kinfo_proc **) pp2; |
p2 = *(struct kinfo_proc **) pp2; |
|
|
/* compare percent cpu (pctcpu) */ |
/* compare percent cpu (pctcpu) */ |
if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0) |
if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0) { |
{ |
/* use CPU usage to break the tie */ |
/* use CPU usage to break the tie */ |
if ((result = PP(p2, p_rtime).tv_sec - PP(p1, p_rtime).tv_sec) == 0) { |
if ((result = PP(p2, p_rtime).tv_sec - PP(p1, p_rtime).tv_sec) == 0) |
/* use process state to break the tie */ |
{ |
if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - |
/* use process state to break the tie */ |
sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) { |
if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - |
/* use priority to break the tie */ |
sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) |
if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0) { |
{ |
/* use resident set size (rssize) to |
/* use priority to break the tie */ |
* break the tie */ |
if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0) |
if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0) { |
{ |
/* use total memory to break |
/* use resident set size (rssize) to break the tie */ |
* the tie */ |
if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0) |
result = PROCSIZE(p2) - PROCSIZE(p1); |
{ |
} |
/* use total memory to break the tie */ |
} |
result = PROCSIZE(p2) - PROCSIZE(p1); |
} |
} |
|
} |
} |
} |
} else { |
|
result = lresult < 0 ? -1 : 1; |
} |
} |
} |
|
else |
|
{ |
|
result = lresult < 0 ? -1 : 1; |
|
} |
|
|
|
return(result); |
return (result); |
} |
} |
#endif |
#endif |
|
|
|
|
* security problem. It validates requests for the "kill" |
* security problem. It validates requests for the "kill" |
* and "renice" commands. |
* and "renice" commands. |
*/ |
*/ |
|
int |
int proc_owner(pid) |
proc_owner(pid) |
|
pid_t pid; |
pid_t pid; |
|
|
|
{ |
{ |
register int cnt; |
struct kinfo_proc **prefp, *pp; |
register struct kinfo_proc **prefp; |
int cnt; |
register struct kinfo_proc *pp; |
|
|
|
prefp = pref; |
prefp = pref; |
cnt = pref_len; |
cnt = pref_len; |
while (--cnt >= 0) |
while (--cnt >= 0) { |
{ |
pp = *prefp++; |
pp = *prefp++; |
if (PP(pp, p_pid) == pid) { |
if (PP(pp, p_pid) == pid) |
return ((int) EP(pp, e_pcred.p_ruid)); |
{ |
} |
return((int)EP(pp, e_pcred.p_ruid)); |
|
} |
} |
} |
return (-1); |
return(-1); |
|
} |
} |
|
|
#ifdef DOSWAP |
#ifdef DOSWAP |
/* |
/* |
* swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org> |
* swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org> |
|
|
*/ |
*/ |
static int |
static int |
swapmode(used, total) |
swapmode(used, total) |
int *used; |
int *used; |
int *total; |
int *total; |
{ |
{ |
int nswap, rnswap, i; |
int nswap, rnswap, i; |
struct swapent *swdev; |
struct swapent *swdev; |
|
|
nswap = swapctl(SWAP_NSWAP, 0, 0); |
nswap = swapctl(SWAP_NSWAP, 0, 0); |
if (nswap == 0) |
if (nswap == 0) |
return 0; |
return 0; |
|
|
swdev = malloc(nswap * sizeof(*swdev)); |
swdev = malloc(nswap * sizeof(*swdev)); |
if(swdev == NULL) |
if (swdev == NULL) |
return 0; |
return 0; |
|
|
rnswap = swapctl(SWAP_STATS, swdev, nswap); |
rnswap = swapctl(SWAP_STATS, swdev, nswap); |
if(rnswap == -1) |
if (rnswap == -1) |
return 0; |
return 0; |
|
|
/* if rnswap != nswap, then what? */ |
/* if rnswap != nswap, then what? */ |
|
|
*total = *used = 0; |
*total = *used = 0; |
for (i = 0; i < nswap; i++) { |
for (i = 0; i < nswap; i++) { |
if (swdev[i].se_flags & SWF_ENABLE) { |
if (swdev[i].se_flags & SWF_ENABLE) { |
*used += (swdev[i].se_inuse / (1024/DEV_BSIZE)); |
*used += (swdev[i].se_inuse / (1024 / DEV_BSIZE)); |
*total += (swdev[i].se_nblks / (1024/DEV_BSIZE)); |
*total += (swdev[i].se_nblks / (1024 / DEV_BSIZE)); |
} |
} |
} |
} |
|
|
free (swdev); |
free(swdev); |
return 1; |
return 1; |
} |
} |
#endif |
#endif |