Newsgroups: comp.sources.unix From: wnl@groupsys.com (William Lefebvre) Subject: v29i107: top-3.4 - top process display, V3.4, Part06/22 References: <1.841608857.22962@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: wnl@groupsys.com (William Lefebvre) Posting-Number: Volume 29, Issue 107 Archive-Name: top-3.4/part06 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'top-3.4/machine/m_bsd44.c' <<'END_OF_FILE' X/* X * top - a top users display for Unix X * X * SYNOPSIS: For a 4.4BSD system X * Note process resident sizes could be wrong, but ps shows X * zero for them too.. X * X * DESCRIPTION: X * This is the machine-dependent module for BSD4.4 X * Works for: X * hp300 X * X * LIBS: -lkvm X * X * AUTHOR: Christos Zoulas X */ X X#include X#include X#include X X#include "os.h" X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X X#define DOSWAP X Xstatic int check_nlist __P((struct nlist *)); Xstatic int getkval __P((unsigned long, int *, int, char *)); Xextern char* printable __P((char *)); X X#include "top.h" X#include "machine.h" X#include "utils.h" X X#define VMUNIX "/vmunix" X#define KMEM "/dev/kmem" X#define MEM "/dev/mem" X#ifdef DOSWAP X#define SWAP "/dev/drum" X#endif X X/* get_process_info passes back a handle. This is what it looks like: */ X Xstruct handle X{ X struct kinfo_proc **next_proc; /* points to next valid proc pointer */ X int remaining; /* number of pointers remaining */ X}; X X/* declarations for load_avg */ X#include "loadavg.h" X X#define PP(pp, field) ((pp)->kp_proc . field) X#define EP(pp, field) ((pp)->kp_eproc . field) X#define VP(pp, field) ((pp)->kp_eproc.e_vm . field) X X/* define what weighted cpu is. */ X#define weighted_cpu(pct, pp) (PP((pp), p_time) == 0 ? 0.0 : \ X ((pct) / (1.0 - exp(PP((pp), p_time) * logcpu)))) X X/* what we consider to be process size: */ X#define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize)) X X/* definitions for indices in the nlist array */ X#define X_CCPU 0 X#define X_CP_TIME 1 X#define X_HZ 2 X#define X_AVENRUN 3 X Xstatic struct nlist nlst[] = { X { "_ccpu" }, /* 0 */ X { "_cp_time" }, /* 1 */ X { "_hz" }, /* 2 */ X { "_averunnable" }, /* 3 */ X { 0 } X}; X X/* X * These definitions control the format of the per-process area X */ X Xstatic char header[] = X " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; X/* 0123456 -- field to fill in starts at header+6 */ X#define UNAME_START 6 X X#define Proc_format \ X "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s" X X X/* process state names for the "STATE" column of the display */ X/* the extra nulls in the string "run" are for adding a slash and X the processor number when needed */ X Xchar *state_abbrev[] = X{ X "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop" X}; X X Xstatic kvm_t *kd; X X/* values that we stash away in _init and use in later routines */ X Xstatic double logcpu; X X/* these are retrieved from the kernel in _init */ X Xstatic long hz; Xstatic load_avg ccpu; X X/* these are offsets obtained via nlist and used in the get_ functions */ X Xstatic unsigned long cp_time_offset; Xstatic unsigned long avenrun_offset; X X/* these are for calculating cpu state percentages */ X Xstatic long cp_time[CPUSTATES]; Xstatic long cp_old[CPUSTATES]; Xstatic long cp_diff[CPUSTATES]; X X/* these are for detailing the process states */ X Xint process_states[7]; Xchar *procstatenames[] = { X "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ", X " zombie, ", " stopped, ", X NULL X}; X X/* these are for detailing the cpu states */ X Xint cpu_states[4]; Xchar *cpustatenames[] = { X "user", "nice", "system", "idle", NULL X}; X X/* these are for detailing the memory statistics */ X Xint memory_stats[8]; Xchar *memorynames[] = { X "Real: ", "K/", "K ", "Virt: ", "K/", X "K ", "Free: ", "K", NULL X}; X X/* these are for keeping track of the proc array */ X Xstatic int nproc; Xstatic int onproc = -1; Xstatic int pref_len; Xstatic struct kinfo_proc *pbase; Xstatic struct kinfo_proc **pref; X X/* these are for getting the memory statistics */ X Xstatic int pageshift; /* log base 2 of the pagesize */ X X/* define pagetok in terms of pageshift */ X X#define pagetok(size) ((size) << pageshift) X Xint Xmachine_init(statics) X Xstruct statics *statics; X X{ X register int i = 0; X register int pagesize; X X if ((kd = kvm_open(VMUNIX, MEM, SWAP, O_RDONLY, "kvm_open")) == NULL) X return -1; X X X /* get the list of symbols we want to access in the kernel */ X (void) kvm_nlist(kd, nlst); X if (nlst[0].n_type == 0) X { X fprintf(stderr, "top: nlist failed\n"); X return(-1); X } X X /* make sure they were all found */ X if (i > 0 && check_nlist(nlst) > 0) X { X return(-1); X } X X /* get the symbol values out of kmem */ X (void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz), X nlst[X_HZ].n_name); X (void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu), X nlst[X_CCPU].n_name); X X /* stash away certain offsets for later use */ X cp_time_offset = nlst[X_CP_TIME].n_value; X avenrun_offset = nlst[X_AVENRUN].n_value; X X /* this is used in calculating WCPU -- calculate it ahead of time */ X logcpu = log(loaddouble(ccpu)); X X pbase = NULL; X pref = NULL; X nproc = 0; X onproc = -1; X /* get the page size with "getpagesize" and calculate pageshift from it */ X pagesize = getpagesize(); X pageshift = 0; X while (pagesize > 1) X { X pageshift++; X pagesize >>= 1; X } X X /* we only need the amount of log(2)1024 for our conversion */ X pageshift -= LOG1024; X X /* fill in the statics information */ X statics->procstate_names = procstatenames; X statics->cpustate_names = cpustatenames; X statics->memory_names = memorynames; X X /* all done! */ X return(0); X} X Xchar *format_header(uname_field) X Xregister char *uname_field; X X{ X register char *ptr; X X ptr = header + UNAME_START; X while (*uname_field != '\0') X { X *ptr++ = *uname_field++; X } X X return(header); X} X Xvoid Xget_system_info(si) X Xstruct system_info *si; X X{ X long total; X load_avg avenrun[3]; X X /* get the cp_time array */ X (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time), X "_cp_time"); X (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun), X "_avenrun"); X X /* convert load averages to doubles */ X { X register int i; X register double *infoloadp; X load_avg *avenrunp; X X#ifdef notyet X struct loadavg sysload; X int size; X getkerninfo(KINFO_LOADAVG, &sysload, &size, 0); X#endif X X infoloadp = si->load_avg; X avenrunp = avenrun; X for (i = 0; i < 3; i++) X { X#ifdef notyet X *infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale; X#endif X *infoloadp++ = loaddouble(*avenrunp++); X } X } X X /* convert cp_time counts to percentages */ X total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); X X /* sum memory statistics */ X { X struct vmtotal total; X int size = sizeof(total); X static int mib[] = { CTL_VM, VM_METER }; X X /* get total -- systemwide main memory usage structure */ X if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { X (void) fprintf(stderr, "top: sysctl failed: %s\n", strerror(errno)); X bzero(&total, sizeof(total)); X } X /* convert memory stats to Kbytes */ X memory_stats[0] = -1; X memory_stats[1] = pagetok(total.t_arm); X memory_stats[2] = pagetok(total.t_rm); X memory_stats[3] = -1; X memory_stats[4] = pagetok(total.t_avm); X memory_stats[5] = pagetok(total.t_vm); X memory_stats[6] = -1; X memory_stats[7] = pagetok(total.t_free); X } X X /* set arrays and strings */ X si->cpustates = cpu_states; X si->memory = memory_stats; X si->last_pid = -1; X} X Xstatic struct handle handle; X Xcaddr_t get_process_info(si, sel, compare) X Xstruct system_info *si; Xstruct process_select *sel; Xint (*compare)(); X X{ X register int i; X register int total_procs; X register int active_procs; X register struct kinfo_proc **prefp; X register struct kinfo_proc *pp; X X /* these are copied out of sel for speed */ X int show_idle; X int show_system; X int show_uid; X int show_command; X X X pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); X if (nproc > onproc) X pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *) X * (onproc = nproc)); X if (pref == NULL || pbase == NULL) { X (void) fprintf(stderr, "top: Out of memory.\n"); X quit(23); X } X /* get a pointer to the states summary array */ X si->procstates = process_states; X X /* set up flags which define what we are going to select */ X show_idle = sel->idle; X show_system = sel->system; X show_uid = sel->uid != -1; X show_command = sel->command != NULL; X X /* count up process states and get pointers to interesting procs */ X total_procs = 0; X active_procs = 0; X memset((char *)process_states, 0, sizeof(process_states)); X prefp = pref; X for (pp = pbase, i = 0; i < nproc; pp++, i++) X { X /* X * Place pointers to each valid proc structure in pref[]. X * Process slots that are actually in use have a non-zero X * status field. Processes with SSYS set are system X * processes---these get ignored unless show_sysprocs is set. X */ X if (PP(pp, p_stat) != 0 && X (show_system || ((PP(pp, p_flag) & SSYS) == 0))) X { X total_procs++; X process_states[(unsigned char) PP(pp, p_stat)]++; X if ((PP(pp, p_stat) != SZOMB) && X (show_idle || (PP(pp, p_pctcpu) != 0) || X (PP(pp, p_stat) == SRUN)) && X (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t)sel->uid)) X { X *prefp++ = pp; X active_procs++; X } X } X } X X /* if requested, sort the "interesting" processes */ X if (compare != NULL) X { X qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare); X } X X /* remember active and total counts */ X si->p_total = total_procs; X si->p_active = pref_len = active_procs; X X /* pass back a handle */ X handle.next_proc = pref; X handle.remaining = active_procs; X return((caddr_t)&handle); X} X Xchar fmt[MAX_COLS]; /* static area where result is built */ X Xchar *format_next_process(handle, get_userid) X Xcaddr_t handle; Xchar *(*get_userid)(); X X{ X register struct kinfo_proc *pp; X register long cputime; X register double pct; X struct handle *hp; X X /* find and remember the next proc structure */ X hp = (struct handle *)handle; X pp = *(hp->next_proc++); X hp->remaining--; X X X /* get the process's user struct and set cputime */ X if ((PP(pp, p_flag) & SLOAD) == 0) { X /* X * Print swapped processes as X */ X char *comm = PP(pp, p_comm); X#define COMSIZ sizeof(PP(pp, p_comm)) X char buf[COMSIZ]; X (void) strncpy(buf, comm, COMSIZ); X comm[0] = '<'; X (void) strncpy(&comm[1], buf, COMSIZ - 2); X comm[COMSIZ - 2] = '\0'; X (void) strncat(comm, ">", COMSIZ - 1); X comm[COMSIZ - 1] = '\0'; X } X X#if 0 X /* This does not produce the correct results */ X cputime = PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks); X#endif X cputime = PP(pp, p_rtime).tv_sec; /* This does not count interrupts */ X X /* calculate the base for cpu percentages */ X pct = pctdouble(PP(pp, p_pctcpu)); X X /* format this entry */ X sprintf(fmt, X Proc_format, X PP(pp, p_pid), X (*get_userid)(EP(pp, e_pcred.p_ruid)), X PP(pp, p_pri) - PZERO, X PP(pp, p_nice) - NZERO, X format_k(pagetok(PROCSIZE(pp))), X format_k(pagetok(VP(pp, vm_rssize))), X state_abbrev[(unsigned char) PP(pp, p_stat)], X format_time(cputime), X 100.0 * weighted_cpu(pct, pp), X 100.0 * pct, X printable(PP(pp, p_comm))); X X /* return the result */ X return(fmt); X} X X X/* X * check_nlist(nlst) - checks the nlist to see if any symbols were not X * found. For every symbol that was not found, a one-line X * message is printed to stderr. The routine returns the X * number of symbols NOT found. X */ X Xstatic int check_nlist(nlst) X Xregister struct nlist *nlst; X X{ X register int i; X X /* check to see if we got ALL the symbols we requested */ X /* this will write one line to stderr for every symbol not found */ X X i = 0; X while (nlst->n_name != NULL) X { X if (nlst->n_type == 0) X { X /* this one wasn't found */ X (void) fprintf(stderr, "kernel: no symbol named `%s'\n", X nlst->n_name); X i = 1; X } X nlst++; X } X X return(i); X} X X X/* X * getkval(offset, ptr, size, refstr) - get a value out of the kernel. X * "offset" is the byte offset into the kernel for the desired value, X * "ptr" points to a buffer into which the value is retrieved, X * "size" is the size of the buffer (and the object to retrieve), X * "refstr" is a reference string used when printing error meessages, X * if "refstr" starts with a '!', then a failure on read will not X * be fatal (this may seem like a silly way to do things, but I X * really didn't want the overhead of another argument). X * X */ X Xstatic int getkval(offset, ptr, size, refstr) X Xunsigned long offset; Xint *ptr; Xint size; Xchar *refstr; X X{ X if (kvm_read(kd, offset, (char *) ptr, size) != size) X { X if (*refstr == '!') X { X return(0); X } X else X { X fprintf(stderr, "top: kvm_read for %s: %s\n", X refstr, strerror(errno)); X quit(23); X } X } X return(1); X} X X/* comparison routine for qsort */ X X/* X * proc_compare - comparison function for "qsort" X * Compares the resource consumption of two processes using five X * distinct keys. The keys (in descending order of importance) are: X * percent cpu, cpu ticks, state, resident set size, total virtual X * memory usage. The process states are ordered as follows (from least X * to most important): WAIT, zombie, sleep, stop, start, run. The X * array declaration below maps a process state index into a number X * that reflects this ordering. X */ X Xstatic unsigned char sorted_state[] = X{ X 0, /* not used */ X 3, /* sleep */ X 1, /* ABANDONED (WAIT) */ X 6, /* run */ X 5, /* start */ X 2, /* zombie */ X 4 /* stop */ X}; X Xint Xproc_compare(pp1, pp2) X Xstruct proc **pp1; Xstruct proc **pp2; X X{ X register struct kinfo_proc *p1; X register struct kinfo_proc *p2; X register int result; X register pctcpu lresult; X X /* remove one level of indirection */ X p1 = *(struct kinfo_proc **) pp1; X p2 = *(struct kinfo_proc **) pp2; X X /* compare percent cpu (pctcpu) */ X if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0) X { X /* use cpticks to break the tie */ X if ((result = PP(p2, p_cpticks) - PP(p1, p_cpticks)) == 0) X { X /* use process state to break the tie */ X if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - X sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) X { X /* use priority to break the tie */ X if ((result = PP(p2, p_pri) - PP(p1, p_pri)) == 0) X { X /* use resident set size (rssize) to break the tie */ X if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0) X { X /* use total memory to break the tie */ X result = PROCSIZE(p2) - PROCSIZE(p1); X } X } X } X } X } X else X { X result = lresult < 0 ? -1 : 1; X } X X return(result); X} X X X/* X * proc_owner(pid) - returns the uid that owns process "pid", or -1 if X * the process does not exist. X * It is EXTREMLY IMPORTANT that this function work correctly. X * If top runs setuid root (as in SVR4), then this function X * is the only thing that stands in the way of a serious X * security problem. It validates requests for the "kill" X * and "renice" commands. X */ X Xint proc_owner(pid) X Xint pid; X X{ X register int cnt; X register struct kinfo_proc **prefp; X register struct kinfo_proc *pp; X X prefp = pref; X cnt = pref_len; X while (--cnt >= 0) X { X pp = *prefp++; X if (PP(pp, p_pid) == (pid_t)pid) X { X return((int)EP(pp, e_pcred.p_ruid)); X } X } X return(-1); X} END_OF_FILE if test 15518 -ne `wc -c <'top-3.4/machine/m_bsd44.c'`; then echo shar: \"'top-3.4/machine/m_bsd44.c'\" unpacked with wrong size! fi # end of 'top-3.4/machine/m_bsd44.c' fi if test -f 'top-3.4/machine/m_bsdos2.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'top-3.4/machine/m_bsdos2.c'\" else echo shar: Extracting \"'top-3.4/machine/m_bsdos2.c'\" \(15520 characters\) sed "s/^X//" >'top-3.4/machine/m_bsdos2.c' <<'END_OF_FILE' X/* X * top - a top users display for Unix X * X * SYNOPSIS: For a BSD/OS 2.X system (based on the 4.4BSD Lite system) X * Note process resident sizes could be wrong, but ps shows X * zero for them too.. X * X * DESCRIPTION: X * This is the machine-dependent module for BSD/OS 2.X (based on 4.4BSD Lite) X * Works for: X * i386 and maybe sparc X * X * LIBS: -lkvm X * X * AUTHOR: Jeff Polk based on the m_44bsd.c code X * by Christos Zoulas X */ X X#include X#include X#include X X#include "os.h" X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X X#define DOSWAP X Xstatic int check_nlist __P((struct nlist *)); Xstatic int getkval __P((unsigned long, int *, int, char *)); Xextern char* printable __P((char *)); X X#include "top.h" X#include "machine.h" X#include "utils.h" X X#define VMUNIX "/bsd" X#define KMEM "/dev/kmem" X#define MEM "/dev/mem" X#ifdef DOSWAP X#define SWAP "/dev/drum" X#endif X X/* get_process_info passes back a handle. This is what it looks like: */ X Xstruct handle X{ X struct kinfo_proc **next_proc; /* points to next valid proc pointer */ X int remaining; /* number of pointers remaining */ X}; X X/* declarations for load_avg */ X#include "loadavg.h" X X#define PP(pp, field) ((pp)->kp_proc . field) X#define EP(pp, field) ((pp)->kp_eproc . field) X#define VP(pp, field) ((pp)->kp_eproc.e_vm . field) X X/* define what weighted cpu is. */ X#define weighted_cpu(pct, pp) (PP((pp), p_swtime) == 0 ? 0.0 : \ X ((pct) / (1.0 - exp(PP((pp), p_swtime) * logcpu)))) X X/* what we consider to be process size: */ X#define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ss Xize)) X X/* definitions for indices in the nlist array */ X#define X_CCPU 0 X#define X_HZ 1 X Xstatic struct nlist nlst[] = { X { "_ccpu" }, /* 0 */ X { "_hz" }, /* 1 */ X { 0 } X}; X X/* X * These definitions control the format of the per-process area X */ X Xstatic char header[] = X " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; X/* 0123456 -- field to fill in starts at header+6 */ X#define UNAME_START 6 X X#define Proc_format \ X "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s" X X X/* process state names for the "STATE" column of the display */ X/* the extra nulls in the string "run" are for adding a slash and X the processor number when needed */ X Xchar *state_abbrev[] = X{ X "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop" X}; X X Xstatic kvm_t *kd; X X/* values that we stash away in _init and use in later routines */ X Xstatic double logcpu; X X/* these are retrieved from the kernel in _init */ X Xstatic long hz; Xstatic load_avg ccpu; X X X/* these are for calculating cpu state percentages */ X Xstatic u_long cp_old[CPUSTATES]; Xstatic u_long cp_diff[CPUSTATES]; X X/* these are for detailing the process states */ X Xint process_states[7]; Xchar *procstatenames[] = { X "", " starting, ", " running, ", " sleeping, ", X " stopped, ", " zombie, ", X NULL X}; X X/* these are for detailing the cpu states */ X Xint cpu_states[6]; Xchar *cpustatenames[] = { X "user", "nice", "system", "interrupt", "idle", NULL X}; X X/* these are for detailing the memory statistics */ X Xint memory_stats[8]; Xchar *memorynames[] = { X "Real: ", "K/", "K ", "Virt: ", "K/", X "K ", "Free: ", "K", NULL X}; X X/* these are for keeping track of the proc array */ X Xstatic int nproc; Xstatic int onproc = -1; Xstatic int pref_len; Xstatic struct kinfo_proc *pbase; Xstatic struct kinfo_proc **pref; X X/* these are for getting the memory statistics */ X Xstatic int pageshift; /* log base 2 of the pagesize */ X X/* define pagetok in terms of pageshift */ X X#define pagetok(size) ((size) << pageshift) X Xint Xmachine_init(statics) X Xstruct statics *statics; X X{ X register int i = 0; X register int pagesize; X X if ((kd = kvm_open(VMUNIX, MEM, SWAP, O_RDONLY, "kvm_open")) == NULL) X return -1; X X X /* get the list of symbols we want to access in the kernel */ X (void) kvm_nlist(kd, nlst); X if (nlst[0].n_type == 0) X { X fprintf(stderr, "top: nlist failed\n"); X return(-1); X } X X /* make sure they were all found */ X if (i > 0 && check_nlist(nlst) > 0) X { X return(-1); X } X X /* get the symbol values out of kmem */ X (void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz), X nlst[X_HZ].n_name); X (void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu), X nlst[X_CCPU].n_name); X X /* this is used in calculating WCPU -- calculate it ahead of time */ X logcpu = log(loaddouble(ccpu)); X X pbase = NULL; X pref = NULL; X nproc = 0; X onproc = -1; X /* get the page size with "getpagesize" and calculate pageshift from it */ X pagesize = getpagesize(); X pageshift = 0; X while (pagesize > 1) X { X pageshift++; X pagesize >>= 1; X } X X /* we only need the amount of log(2)1024 for our conversion */ X pageshift -= LOG1024; X X /* fill in the statics information */ X statics->procstate_names = procstatenames; X statics->cpustate_names = cpustatenames; X statics->memory_names = memorynames; X X /* all done! */ X return(0); X} X Xchar *format_header(uname_field) X Xregister char *uname_field; X X{ X register char *ptr; X X ptr = header + UNAME_START; X while (*uname_field != '\0') X { X *ptr++ = *uname_field++; X } X X return(header); X} X Xvoid Xget_system_info(si) X Xstruct system_info *si; X X{ X u_long total; X struct cpustats cpu; X struct loadavg load; X X /* get load averages */ X { X size_t size = sizeof(load); X static int mib[] = { CTL_VM, VM_LOADAVG }; X X if (sysctl(mib, 2, &load, &size, NULL, 0) < 0) { X (void) fprintf(stderr, "top: sysctl failed: %s\n", strerror(errno)) X; X bzero(&load, sizeof(load)); X } X } X X /* convert load averages to doubles */ X { X register int i; X register double *infoloadp = si->load_avg; X X for (i = 0; i < 3; i++) X *infoloadp++ = ((double) load.ldavg[i]) / load.fscale; X } X X /* get cp_time counts */ X { X size_t size = sizeof(cpu); X static int mib[] = { CTL_KERN, KERN_CPUSTATS }; X X if (sysctl(mib, 2, &cpu, &size, NULL, 0) < 0) { X (void) fprintf(stderr, "top: sysctl failed: %s\n", strerror(errno)) X; X bzero(&cpu, sizeof(cpu)); X } X } X X /* convert cp_time counts to percentages */ X total = percentages(CPUSTATES, cpu_states, cpu.cp_time, cp_old, cp_diff); X X /* sum memory statistics */ X { X struct vmtotal total; X size_t size = sizeof(total); X static int mib[] = { CTL_VM, VM_TOTAL }; X X /* get total -- systemwide main memory usage structure */ X if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { X (void) fprintf(stderr, "top: sysctl failed: %s\n", strerror(errno)) X; X bzero(&total, sizeof(total)); X } X /* convert memory stats to Kbytes */ X memory_stats[0] = -1; X memory_stats[1] = pagetok(total.t_arm); X memory_stats[2] = pagetok(total.t_rm); X memory_stats[3] = -1; X memory_stats[4] = pagetok(total.t_avm); X memory_stats[5] = pagetok(total.t_vm); X memory_stats[6] = -1; X memory_stats[7] = pagetok(total.t_free); X } X X /* set arrays and strings */ X si->cpustates = cpu_states; X si->memory = memory_stats; X si->last_pid = -1; X} X Xstatic struct handle handle; X Xcaddr_t get_process_info(si, sel, compare) X Xstruct system_info *si; Xstruct process_select *sel; Xint (*compare)(); X X{ X register int i; X register int total_procs; X register int active_procs; X register struct kinfo_proc **prefp; X register struct kinfo_proc *pp; X X /* these are copied out of sel for speed */ X int show_idle; X int show_system; X int show_uid; X int show_command; X X X pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); X if (nproc > onproc) X pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *) X * (onproc = nproc)); X if (pref == NULL || pbase == NULL) { X (void) fprintf(stderr, "top: Out of memory.\n"); X quit(23); X } X /* get a pointer to the states summary array */ X si->procstates = process_states; X X /* set up flags which define what we are going to select */ X show_idle = sel->idle; X show_system = sel->system; X show_uid = sel->uid != -1; X show_command = sel->command != NULL; X X /* count up process states and get pointers to interesting procs */ X total_procs = 0; X active_procs = 0; X memset((char *)process_states, 0, sizeof(process_states)); X prefp = pref; X for (pp = pbase, i = 0; i < nproc; pp++, i++) X { X /* X * Place pointers to each valid proc structure in pref[]. X * Process slots that are actually in use have a non-zero X * status field. Processes with SSYS set are system X * processes---these get ignored unless show_sysprocs is set. X */ X if (PP(pp, p_stat) != 0 && X (show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0))) X { X total_procs++; X process_states[(unsigned char) PP(pp, p_stat)]++; X if ((PP(pp, p_stat) != SZOMB) && X (show_idle || (PP(pp, p_pctcpu) != 0) || X (PP(pp, p_stat) == SRUN)) && X (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t)sel->uid)) X { X *prefp++ = pp; X active_procs++; X } X } X } X X /* if requested, sort the "interesting" processes */ X if (compare != NULL) X { X qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare) X; X } X X /* remember active and total counts */ X si->p_total = total_procs; X si->p_active = pref_len = active_procs; X X /* pass back a handle */ X handle.next_proc = pref; X handle.remaining = active_procs; X return((caddr_t)&handle); X} X Xchar fmt[MAX_COLS]; /* static area where result is built */ X Xchar *format_next_process(handle, get_userid) X Xcaddr_t handle; Xchar *(*get_userid)(); X X{ X register struct kinfo_proc *pp; X register long cputime; X register double pct; X struct handle *hp; X X /* find and remember the next proc structure */ X hp = (struct handle *)handle; X pp = *(hp->next_proc++); X hp->remaining--; X X X /* get the process's user struct and set cputime */ X if ((PP(pp, p_flag) & P_INMEM) == 0) { X /* X * Print swapped processes as X */ X char *comm = PP(pp, p_comm); X#define COMSIZ sizeof(PP(pp, p_comm)) X char buf[COMSIZ]; X (void) strncpy(buf, comm, COMSIZ); X comm[0] = '<'; X (void) strncpy(&comm[1], buf, COMSIZ - 2); X comm[COMSIZ - 2] = '\0'; X (void) strncat(comm, ">", COMSIZ - 1); X comm[COMSIZ - 1] = '\0'; X } X X#if 0 X /* This does not produce the correct results */ X cputime = PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks); X#endif X cputime = PP(pp, p_rtime).tv_sec; /* This does not count interrupts */ X X /* calculate the base for cpu percentages */ X pct = pctdouble(PP(pp, p_pctcpu)); X X /* format this entry */ X sprintf(fmt, X Proc_format, X PP(pp, p_pid), X (*get_userid)(EP(pp, e_pcred.p_ruid)), X PP(pp, p_priority) - PZERO, X PP(pp, p_nice) - NZERO, X format_k(pagetok(PROCSIZE(pp))), X format_k(pagetok(VP(pp, vm_rssize))), X state_abbrev[(unsigned char) PP(pp, p_stat)], X format_time(cputime), X 100.0 * weighted_cpu(pct, pp), X 100.0 * pct, X printable(PP(pp, p_comm))); X X /* return the result */ X return(fmt); X} X X X/* X * check_nlist(nlst) - checks the nlist to see if any symbols were not X * found. For every symbol that was not found, a one-line X * message is printed to stderr. The routine returns the X * number of symbols NOT found. X */ X Xstatic int check_nlist(nlst) X Xregister struct nlist *nlst; X X{ X register int i; X X /* check to see if we got ALL the symbols we requested */ X /* this will write one line to stderr for every symbol not found */ X X i = 0; X while (nlst->n_name != NULL) X { X if (nlst->n_type == 0) X { X /* this one wasn't found */ X (void) fprintf(stderr, "kernel: no symbol named `%s'\n", X nlst->n_name); X i = 1; X } X nlst++; X } X X return(i); X} X X X/* X * getkval(offset, ptr, size, refstr) - get a value out of the kernel. X * "offset" is the byte offset into the kernel for the desired value, X * "ptr" points to a buffer into which the value is retrieved, X * "size" is the size of the buffer (and the object to retrieve), X * "refstr" is a reference string used when printing error meessages, X * if "refstr" starts with a '!', then a failure on read will not X * be fatal (this may seem like a silly way to do things, but I X * really didn't want the overhead of another argument). X * X */ X Xstatic int getkval(offset, ptr, size, refstr) X Xunsigned long offset; Xint *ptr; Xint size; Xchar *refstr; X X{ X if (kvm_read(kd, offset, (char *) ptr, size) != size) X { X if (*refstr == '!') X { X return(0); X } X else X { X fprintf(stderr, "top: kvm_read for %s: %s\n", X refstr, strerror(errno)); X quit(23); X } X } X return(1); X} X X/* comparison routine for qsort */ X X/* X * proc_compare - comparison function for "qsort" X * Compares the resource consumption of two processes using five X * distinct keys. The keys (in descending order of importance) are: X * percent cpu, cpu ticks, state, resident set size, total virtual X * memory usage. The process states are ordered as follows (from least X * to most important): WAIT, zombie, sleep, stop, start, run. The X * array declaration below maps a process state index into a number X * that reflects this ordering. X */ X Xstatic unsigned char sorted_state[] = X{ X 0, /* not used */ X 3, /* sleep */ X 1, /* ABANDONED (WAIT) */ X 6, /* run */ X 5, /* start */ X 2, /* zombie */ X 4 /* stop */ X}; X Xint Xproc_compare(pp1, pp2) X Xstruct proc **pp1; Xstruct proc **pp2; X X{ X register struct kinfo_proc *p1; X register struct kinfo_proc *p2; X register int result; X register pctcpu lresult; X X /* remove one level of indirection */ X p1 = *(struct kinfo_proc **) pp1; X p2 = *(struct kinfo_proc **) pp2; X X /* compare percent cpu (pctcpu) */ X if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0) X { X /* use cpticks to break the tie */ X if ((result = PP(p2, p_cpticks) - PP(p1, p_cpticks)) == 0) X { X /* use process state to break the tie */ X if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - X sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) X { X /* use priority to break the tie */ X if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0) X { X /* use resident set size (rssize) to break the tie */ X if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0) X { X /* use total memory to break the tie */ X result = PROCSIZE(p2) - PROCSIZE(p1); X } X } X } X } X } X else X { X result = lresult < 0 ? -1 : 1; X } X X return(result); X} X X X/* X * proc_owner(pid) - returns the uid that owns process "pid", or -1 if X * the process does not exist. X * It is EXTREMLY IMPORTANT that this function work correctly. X * If top runs setuid root (as in SVR4), then this function X * is the only thing that stands in the way of a serious X * security problem. It validates requests for the "kill" X * and "renice" commands. X */ X Xint proc_owner(pid) X Xint pid; X X{ X register int cnt; X register struct kinfo_proc **prefp; X register struct kinfo_proc *pp; X X prefp = pref; X cnt = pref_len; X while (--cnt >= 0) X { X pp = *prefp++; X if (PP(pp, p_pid) == (pid_t)pid) X { X return((int)EP(pp, e_pcred.p_ruid)); X } X } X return(-1); X} END_OF_FILE if test 15520 -ne `wc -c <'top-3.4/machine/m_bsdos2.c'`; then echo shar: \"'top-3.4/machine/m_bsdos2.c'\" unpacked with wrong size! fi # end of 'top-3.4/machine/m_bsdos2.c' fi if test -f 'top-3.4/machine/m_sco.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'top-3.4/machine/m_sco.c'\" else echo shar: Extracting \"'top-3.4/machine/m_sco.c'\" \(15648 characters\) sed "s/^X//" >'top-3.4/machine/m_sco.c' <<'END_OF_FILE' X/* X * top - a top users display for Unix X * X * SYNOPSIS: SCO UNIX X * X * DESCRIPTION: X * This is the machine-dependent module for SCO UNIX. X * Originally written for BSD4.3 system by Christos Zoulas. X * Works for: X * SCO UNIX 3.2v4.2 X * X * CFLAGS: -IBCS2 X * X * You HAVE to use compiler option: -IBCS2 X * (Enforces strict Intel Binary Compatibility Standard 2 conformance.) X * X * AUTHOR: Gregory Shilin X */ X X#include X#include X X#include X#include X#include X#include X#include X#include X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#include "top.h" X#include "machine.h" X#include "utils.h" X#include "loadavg.h" X Xtypedef unsigned long ulong; Xtypedef unsigned int uint; Xtypedef unsigned short ushort; Xtypedef unsigned char uchar; X X#define VMUNIX "/unix" X#define KMEM "/dev/kmem" X#define MEM "/dev/mem" X X/* get_process_info passes back a handle. This is what it looks like: */ Xstruct handle { X struct proc **next_proc; /* points to next valid proc pointer */ X int remaining; /* number of pointers remaining */ X}; X X/* define what weighted cpu is */ X#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \ X ((pct) / (1.0 - exp((pp)->p_time * logcpu)))) X X#define bytetok(bytes) ((bytes) >> 10) X X/* what we consider to be process size: */ X#define PROCSIZE(up) bytetok(ctob((up)->u_tsize + (up)->u_dsize +(up)->u_ssize)) X X/* definitions for indices in the nlist array */ X#define X_V 0 /* System configuration information */ X#define X_PROC 1 /* process tables */ X#define X_FREEMEM 2 /* current free memory */ X#define X_AVAILRMEM 3 /* available resident (not swappable) mem in pages */ X#define X_AVAILSMEM 4 /* available swappable memory in pages */ X#define X_MAXMEM 5 /* maximum available free memory in clicks */ X#define X_PHYSMEM 6 /* physical memory in clicks */ X#define X_NSWAP 7 /* size of swap space in blocks */ X#define X_HZ 8 /* ticks/second of the clock */ X#define X_MPID 9 /* last process id */ X#define X_SYSINFO 10 /* system information (cpu states) */ X#define X_CUR_CPU 11 X Xstatic struct nlist nlst[] = { X { "v" }, /* 0 */ X { "proc" }, /* 1 */ X { "freemem" }, /* 2 */ X { "availrmem" }, /* 3 */ X { "availsmem" }, /* 4 */ X { "maxmem" }, /* 5 */ X { "physmem" }, /* 6 */ X { "nswap" }, /* 7 */ X { "Hz" }, /* 8 */ X { "mpid" }, /* 9 */ X { "sysinfo" }, /* 10 */ X { "cur_cpu" }, /* 11 */ X { NULL } X}; X X/* X * These definitions control the format of the per-process area X */ X Xstatic char header[] = X " PID X PRI NICE SIZE RES STATE TIME COMMAND"; X/* 0123456 -- field to fill in starts at header+6 */ X#define UNAME_START 6 X X#define Proc_format \ X "%5d %-8.8s %3d %4d %5s %5dK %-5s %6s %.28s" X Xstatic int kmem, mem; X Xstatic double logcpu; X X/* these are retrieved from the kernel in _init */ Xstatic int Hz; Xstatic struct var v; Xstatic ulong proca; Xstatic load_avg cur_cpu; X X/* these are for detailing the process states */ Xint process_states[8]; Xchar *procstatenames[] = { X "", " sleeping, ", " running, ", " zombie, ", " stopped, ", X " created, ", " onproc, ", " xswapped, ", X NULL X}; X X/* process state names for the "STATE" column of the display */ Xchar *state_abbrev[] = { X "", "sleep", "run", "zomb", "stop", "create", "onpr", "swap" X}; X X/* these are for calculating cpu state percentages */ X#define CPUSTATES 5 /* definition from struct sysinfo */ Xstatic time_t cp_time[CPUSTATES]; Xstatic time_t cp_old[CPUSTATES]; Xstatic time_t cp_diff[CPUSTATES]; X X/* these are for detailing the cpu states */ Xint cpu_states[CPUSTATES]; Xchar *cpustatenames[] = { X "idle", "user", "system", "wait", "sxbrk", X NULL X}; X X/* these are for detailing the memory statistics */ Xint memory_stats[6]; Xchar *memorynames[] = { X "K phys, ", "K max, ", "K free, ", "K locked, ", "K unlocked, ", "K swap, ", NULL X}; X X/* these are for keeping track of the proc array */ Xstatic int bytes; Xstatic int pref_len; Xstatic struct proc *pbase; Xstatic struct proc **pref; X X/* useful externals */ Xextern int errno; Xextern char *sys_errlist[]; X Xlong time(); Xlong percentages(); X Xmachine_init(statics) Xstruct statics *statics; X{ Xulong ptr; X X if ((kmem = open(KMEM, O_RDONLY)) == -1) { X perror(KMEM); X return -1; X } X if ((mem = open(MEM, O_RDONLY)) == -1) { X perror(MEM); X return -1; X } X X /* get the list of symbols we want to access in the kernel */ X if (nlist(VMUNIX, nlst) == -1) { X fprintf(stderr, "top: nlist failed\n"); X return -1; X } X /* make sure they were all found */ X /*ZZ X if (check_nlist(nlst) > 0) X return -1; X */ X X proca = nlst[X_PROC].n_value; X X /* get the symbol values out of kmem */ X (void) getkval(nlst[X_CUR_CPU].n_value, (int *)(&cur_cpu), sizeof(cur_cpu), X nlst[X_CUR_CPU].n_name); X (void) getkval(nlst[X_HZ].n_value, (int *)(&Hz), sizeof(Hz), X nlst[X_HZ].n_name); X (void) getkval(nlst[X_V].n_value, (int *)(&v), sizeof(v), X nlst[X_V].n_name); X X /* this is used in calculating WCPU -- calculate it ahead of time */ X logcpu = log(fabs(loaddouble(cur_cpu))); X X /* allocate space for proc structure array and array of pointers */ X bytes = v.v_proc * sizeof(struct proc); X pbase = (struct proc *)malloc(bytes); X pref = (struct proc **)malloc(v.v_proc * sizeof(struct proc *)); X if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL) { X fprintf(stderr, "top: cannot allocate sufficient memory\n"); X return -1; X } X X /* fill in the statics information */ X statics->procstate_names = procstatenames; X statics->cpustate_names = cpustatenames; X statics->memory_names = memorynames; X X return 0; X} X Xchar *format_header(uname_field) Xregister char *uname_field; X{ X register char *ptr; X X ptr = header + UNAME_START; X while (*uname_field != '\0') X { X *ptr++ = *uname_field++; X } X X return(header); X} X Xget_system_info(si) Xstruct system_info *si; X{ Xlong total; X X /* get process id of the last process */ X (void) getkval(nlst[X_MPID].n_value, &(si->last_pid), sizeof(si->last_pid), X nlst[X_MPID].n_name); X /* get the cp_time array */ X (void) getkval(nlst[X_SYSINFO].n_value, (int *)cp_time, sizeof(cp_time), X nlst[X_SYSINFO].n_name); X X /* convert cp_time counts to persentages */ X total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); X X /* sum memory statistics */ X (void) getkval(nlst[X_PHYSMEM].n_value, &memory_stats[0], X sizeof(memory_stats[0]), nlst[X_PHYSMEM].n_name); X (void) getkval(nlst[X_MAXMEM].n_value, &memory_stats[1], X sizeof(memory_stats[1]), nlst[X_MAXMEM].n_name); X (void) getkval(nlst[X_FREEMEM].n_value, &memory_stats[2], X sizeof(memory_stats[2]), nlst[X_FREEMEM].n_name); X (void) getkval(nlst[X_AVAILRMEM].n_value, &memory_stats[3], X sizeof(memory_stats[3]), nlst[X_AVAILRMEM].n_name); X (void) getkval(nlst[X_AVAILSMEM].n_value, &memory_stats[4], X sizeof(memory_stats[4]), nlst[X_AVAILSMEM].n_name); X (void) getkval(nlst[X_NSWAP].n_value, &memory_stats[5], X sizeof(memory_stats[5]), nlst[X_NSWAP].n_name); X memory_stats[0] = bytetok(ctob(memory_stats[0])); /* clicks -> bytes */ X memory_stats[1] = bytetok(ctob(memory_stats[1])); /* clicks -> bytes */ X memory_stats[2] = bytetok(ctob(memory_stats[2])); /* clicks -> bytes */ X memory_stats[3] = bytetok(memory_stats[3] * NBPP); /* # bytes per page */ X memory_stats[4] = bytetok(memory_stats[4] * NBPP); /* # bytes per page */ X memory_stats[5] = bytetok(memory_stats[5] * NBPSCTR);/* # bytes per sector */ X X /* set arrays and strings */ X si->cpustates = cpu_states; X si->memory = memory_stats; X} X Xstatic struct handle handle; X Xcaddr_t get_process_info(si, sel, compare) X struct system_info *si; X struct process_select *sel; X int (*compare)(); X{ Xregister int i; Xregister int total_procs; Xregister int active_procs; Xregister struct proc **prefp; Xregister struct proc *pp; X X/* set up flags of what we are going to select */ X/* these are copied out of sel for simplicity */ Xint show_idle = sel->idle; Xint show_system = sel->system; Xint show_uid = sel->uid != -1; Xint show_command = sel->command != NULL; X X /* read all the proc structures in one fell swoop */ X (void) getkval(proca, (int *)pbase, bytes, "proc array"); X X /* get a pointer to the states summary array */ X si->procstates = process_states; X X /* count up process states and get pointers to interesting procs */ X total_procs = active_procs = 0; X memset((char *)process_states, 0, sizeof(process_states)); X prefp = pref; X for (pp = pbase, i = 0; i < v.v_proc; pp++, i++) { X /* X * Place pointers to each valid proc structure in pref[]. X * Process slots that are actually in use have a non-zero X * status field. Processes with SSYS set are system processes -- X * these are ignored unless show_system is set. X */ X if (pp->p_stat && (show_system || ((pp->p_flag & SSYS) == 0))) { X total_procs++; X process_states[pp->p_stat]++; X if ((pp->p_stat != SZOMB) && X (show_idle || (pp->p_stat == SRUN) || (pp->p_stat == SONPROC)) && X (!show_uid || pp->p_uid == (ushort)sel->uid)) { X *prefp++ = pp; X active_procs++; X } X } X } X X /* if requested, sort the "interesting" processes */ X if (compare) X qsort((char *)pref, active_procs, sizeof(struct proc *), compare); X X /* remember active and total counts */ X si->p_total = total_procs; X si->p_active = pref_len = active_procs; X X /* pass back a handle */ X handle.next_proc = pref; X handle.remaining = active_procs; X return((caddr_t)&handle); X} X Xchar fmt[128]; /* static area where result is built */ X Xchar *format_next_process(handle, get_userid) X caddr_t handle; X char *(*get_userid)(); X{ Xregister struct proc *pp; Xregister time_t cputime; Xregister double pct; Xint where; Xstruct user u; Xstruct handle *hp; Xchar command[29]; X X /* find and remember the next proc structure */ X hp = (struct handle *)handle; X pp = *(hp->next_proc++); X hp->remaining--; X X /* get the process's user struct and set cputime */ X if ((where = sysi86(RDUBLK, pp->p_pid, &u, sizeof(struct user))) != -1) X where = (pp->p_flag & SLOAD) ? 0 : 1; X if (where == -1) { X strcpy(command, ""); X cputime = 0; X } else { X /* set u_comm for system processes */ X if (u.u_comm[0] == '\0') { X if (pp->p_pid == 0) X strcpy(command, "Swapper"); X else if (pp->p_pid == 2) X strcpy(command, "Pager"); X else if (pp->p_pid == 3) X strcpy(command, "Sync'er"); X } else if (where == 1) { X /* print swapped processes as */ X register char *s1; X X u.u_psargs[28 - 3] = '\0'; X strcpy(command, "<"); X strcat(command, strtok(u.u_psargs, " ")); X strcat(command, ">"); X while (s1 = (char *)strtok(NULL, " ")) X strcat(command, s1); X } else { X sprintf(command, "%s", u.u_psargs); X } X cputime = u.u_utime + u.u_stime; X } X /* calculate the base for cpu percentages */ X pct = pctdouble(pp->p_cpu); X X /* format this entry */ X sprintf(fmt, X Proc_format, X pp->p_pid, X (*get_userid)(pp->p_uid), X pp->p_pri - PZERO, X pp->p_nice - NZERO, X format_k(PROCSIZE(&u)), X 0, X state_abbrev[pp->p_stat], X format_time(cputime / Hz), X printable(command)); X X return(fmt); X} X X/* X * Checks the nlist to see if any symbols were not found. X * For every symbol that was not found, a one-line message X * is printed to stderr. The routine returns the number of X * symbols NOT founded. X */ X Xint check_nlist(nlst) X register struct nlist *nlst; X{ Xregister int i = 0; X X while (nlst->n_name) { X if (nlst->n_type == 0) { X fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name); X i++; X } X nlst++; X } X return i; X} X X/* X * getkval(offset, ptr, size, refstr) - get a value out of the kernel. X * "offset" is the byte offset into the kernel for the desired value, X * "ptr" points to a buffer into which the value is retrieved, X * "size" is the size of the buffer (and the object to retrieve), X * "refstr" is a reference string used when printing error meessages, X * if "refstr" starts with a '!', then a failure on read will not X * be fatal (this may seem like a silly way to do things, but I X * really didn't want the overhead of another argument). X * X */ X Xgetkval(offset, ptr, size, refstr) Xunsigned long offset; Xint *ptr; Xint size; Xchar *refstr; X{ X if (lseek(kmem, (long)offset, SEEK_SET) == -1) { X if (*refstr == '!') X refstr++; X fprintf(stderr, "%s: lseek to %s: %s\n", KMEM, X refstr, errmsg(errno)); X quit(23); X } X if (read(kmem, (char *)ptr, size) == -1) { X if (*refstr == '!') X return 0; X fprintf(stderr, "%s: reading %s: %s\n", KMEM, X refstr, errmsg(errno)); X quit(23); X } X return(1); X} X X/* comparison routine for qsort */ X/* NOTE: this is specific to the BSD proc structure, but it should X give you a good place to start. */ X X/* X * proc_compare - comparison function for "qsort" X * Compares the resource consumption of two processes using five X * distinct keys. The keys (in descending order of importance) are: X * percent cpu, cpu ticks, state, resident set size, total virtual X * memory usage. The process states are ordered as follows (from least X * to most important): WAIT, zombie, sleep, stop, start, run. The X * array declaration below maps a process state index into a number X * that reflects this ordering. X */ X Xstatic unsigned char sorted_state[] = X{ X 0, /* not used */ X 5, /* sleep */ X 6, /* run */ X 2, /* zombie */ X 4, /* stop */ X 1, /* start */ X 7, /* onpr */ X 3, /* swap */ X}; X Xproc_compare(pp1, pp2) Xstruct proc **pp1; Xstruct proc **pp2; X X{ Xregister struct proc *p1; Xregister struct proc *p2; Xregister int result; Xregister ulong lresult; X X /* remove one level of indirection */ X p1 = *pp1; X p2 = *pp2; X X /* use process state to break the tie */ X if ((result = sorted_state[p2->p_stat] - X sorted_state[p1->p_stat]) == 0) X { X /* use priority to break the tie */ X if ((result = p2->p_pri - p1->p_pri) == 0) X { X /* use time to break the tie */ X if ((result = (p2->p_utime + p2->p_stime) - X (p1->p_utime + p1->p_stime)) == 0) X { X /* use resident set size (rssize) to break the tie */ X if ((result = p2->p_size - p1->p_size) == 0) X { X result = 0; X } X } X } X } X X return(result); X} X X/* returns uid of owner of process pid */ Xproc_owner(pid) Xint pid; X{ Xregister int cnt; Xregister struct proc **prefp; Xregister struct proc *pp; X X prefp = pref; X cnt = pref_len; X while (--cnt >= 0) { X if ((pp = *prefp++)->p_pid == (short)pid) X return ((int)pp->p_uid); X } X return(-1); X} X Xint setpriority(int dummy, int who, int nicewal) X{ X errno = 1; X return -1; X} X X/* sigblock is not POSIX conformant */ Xsigset_t sigblock (sigset_t mask) X{ Xsigset_t oset; X X sigemptyset(&oset); X sigprocmask(SIG_BLOCK, &mask, &oset); X return oset; X} X X/* sigsetmask is not POSIX conformant */ Xsigsetmask(sigset_t mask) X{ Xsigset_t oset; X X sigemptyset(&oset); X sigprocmask(SIG_SETMASK, &mask, &oset); X return oset; X} X END_OF_FILE if test 15648 -ne `wc -c <'top-3.4/machine/m_sco.c'`; then echo shar: \"'top-3.4/machine/m_sco.c'\" unpacked with wrong size! fi # end of 'top-3.4/machine/m_sco.c' fi echo shar: End of archive 6 \(of 22\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 22 archives. echo "Now read README and INSTALL, then run Configure" rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0