Here is yet another update version of  Marc Cohen <marc@aai.com>
and Robert Boucher <rob@asimov.uucp> top module for Solaris 2.X.
I have renamed it sunos5.c and added a m_sunos5.man. 
A shar file follows that contains sunos5.c, and m_sunos5.man and
a diff that should to be applied to commands.c
#! /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 <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  diff m_sunos5.c m_sunos5.man
# Wrapped by jones@hermes on Fri Mar  5 15:39:54 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'diff'\"
else
echo shar: Extracting \"'diff'\" \(1001 characters\)
sed "s/^X//" >'diff' <<'END_OF_FILE'
X*** commands.c.orig	Thu Mar  4 15:56:51 1993
X--- commands.c	Thu Mar  4 16:39:14 1993
X***************
X*** 21,26 ****
X--- 21,27 ----
X  #include <signal.h>
X  #include <sys/time.h>
X  #include <sys/resource.h>
X+ #include <sys/errno.h>
X  #include "sigdesc.h"		/* generated automatically */
X  #include "boolean.h"
X  
X***************
X*** 390,395 ****
X--- 391,400 ----
X  	{
X  	    ERROR(str, 0);
X  	}
X+ 	else if (check_secure(procnum) == -1)
X+ 	{
X+ 	    ERROR(str, EPERM);
X+ 	}
X  	else if (kill(procnum, signum) == -1)
X  	{
X  	    /* chalk up an error */
X***************
X*** 451,456 ****
X--- 456,465 ----
X      {
X  	if (scanint(str, &procnum) == -1)
X  	{
X+ 	}
X+ 	else if (check_secure(procnum) == -1)
X+ 	{
X+ 	    ERROR(str, EPERM);
X  	    ERROR(str, 0);
X  	}
X  	else if (setpriority(PRIO_PROCESS, procnum, prio) == -1)
X***************
X*** 465,468 ****
X--- 474,485 ----
X      return NULL;
X  #endif
X  }
X+ 
X+ #if !defined(SECURITY_OPTION)
X+ check_secure(procnum)
X+ int procnum;
X+ {
X+    return 0;
X+ }
X+ #endif
X  
END_OF_FILE
if test 1001 -ne `wc -c <'diff'`; then
    echo shar: \"'diff'\" unpacked with wrong size!
fi
# end of 'diff'
fi
if test -f 'm_sunos5.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'m_sunos5.c'\"
else
echo shar: Extracting \"'m_sunos5.c'\" \(19824 characters\)
sed "s/^X//" >'m_sunos5.c' <<'END_OF_FILE'
X/*
X * top - a top users display for Unix
X *
X * SYNOPSIS:  SunOS 5.1 (Solaris 2.1)
X *
X * DESCRIPTION:
X *
X * The following must be added to CFLAGS in the Makefile:
X * [From <ucbinclude/sys/resource.h>]
X * -DPRIO_MIN=-20 -DPRIO_MAX=20
X *
X * DEFINES: -DPRIO_MIN=-20 -DPRIO_MAX=20 -DSECURITY_OPTION
X * LIBS: -R/usr/lib:/usr/ucblib -lelf -lc -L/usr/ucblib -lucb
X *
X * AUTHORS:  Robert Boucher <boucher@sofkin.ca>
X * CONTRIBUTORS: To SunOS 5.1 prot:
X * 		 Marc Cohen <marc@aai.com>
X *		 Robert Boucher <rob@asimov.uucp>
X *	         William L. Jones <jones@chpc>
X */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/signal.h>
X#include <sys/fault.h>
X#include <sys/sysinfo.h>
X#include <sys/sysmacros.h>
X#include <sys/syscall.h>
X#include <dirent.h>
X#include <sys/user.h>
X#include <sys/proc.h>
X#include <sys/procfs.h>
X#include <sys/vm.h>
X#include <sys/var.h>
X#include <sys/cpuvar.h>
X#include <sys/file.h>
X#include <dirent.h>
X#include <stdio.h>
X#include <nlist.h>
X#include <fcntl.h>
X#include <math.h>
X#include <vm/anon.h>
X
X#include "top.h"
X#include "machine.h"
X
X
X#ifndef FSCALE
X/*
X * [From /usr/ucbinclude/sys/param.h]
X * Scale factor for scaled integers used to count
X * %cpu time and load averages.
X */
X#define FSHIFT  8		/* bits to right of fixed binary point */
X#define FSCALE  (1<<FSHIFT)
X#endif /* FSCALE */
X
X/* get_process_info passes back a handle.  This is what it looks like: */
X
Xstruct handle
X  {
X    struct prpsinfo **next_proc;/* points to next valid proc pointer */
X    int remaining;		/* number of pointers remaining */
X  };
X
X#define CPUSTATES	4
X
X/* declarations for load_avg */
Xtypedef long load_avg;
X#define loaddouble(la) ((double)(la) / FSCALE)
X
X/* define what weighted cpu is.  */
X#define percent_cpu(pp) ((double)(pp)->pr_cpu / FSCALE)
X
X#define weighted_cpu(pct, pp) ( ((pp)->pr_time.tv_sec) == 0 ? 0.0 : \
X        ((pp)->pr_cpu) / ((pp)->pr_time.tv_sec) )
X
X#undef ctob
X#define ctob(x) ((x) << 12)
X
X/* Convert clicks (kernel pages) to kbytes ... */
X#define pagetok(size) ctob(size) >> LOG1024
X
X/* definitions for indices in the nlist array */
X#define X_AVENRUN		 0
X#define X_MPID			 1
X#define X_CPU			 2
X#define X_V			 3
X#define X_NPROC			 4
X#define X_ANONINFO		 5
X#define X_FREEMEM		 6
X#define X_MAXMEM		 7
X#define X_AVAILRMEM		 8
X#define X_SWAPFS_MINFREE	 9
X#define X_NCPUS		   	10
X
Xstatic struct nlist nlst[] =
X{
X  {"avenrun"},			/* 0 */
X  {"mpid"},			/* 1 */
X  {"cpu"},			/* 2 */
X  {"v"},			/* 3 */
X  {"nproc"},			/* 4 */
X  {"anoninfo"},			/* 5 */
X  {"freemem"},			/* 6 */
X  {"maxmem"},			/* 7 */
X  {"availrmem"},		/* 8 */
X  {"swapfs_minfree"},		/* 9 */
X  {"ncpus"},			/* 10 */
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     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%6dK %4dK %-5s%4d:%02d  %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", "run", "zombie", "stop", "start", "cpu", "swap"
X};
X
X#define UNIX "/kernel/unix"
X#define KMEM "/dev/kmem"
X#define PROCFS "/proc"
X
Xstatic int kmem = -1;
Xstatic int mem = -1;
X
Xint freemem;
Xint maxmem;
Xint availrmem;
Xint swapfs_minfree;
X
Xstruct anoninfo anoninfo;
X
X/* these are retrieved from the kernel in _init */
X
Xstatic int nproc;
Xstatic int ncpus;
X
X/* these are offsets obtained via nlist and used in the get_ functions */
X
Xstatic unsigned long mpid_offset;
Xstatic unsigned long nproc_offset;
Xstatic unsigned long avenrun_offset;
Xstatic unsigned long freemem_offset;
Xstatic unsigned long maxmem_offset;
Xstatic unsigned long availrmem_offset;
Xstatic unsigned long swapfs_minfree_offset;
Xstatic unsigned long *cpu_offset;
Xstatic unsigned long anoninfo_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[8];
Xchar *procstatenames[] =
X{
X  "", " sleeping, ", " running, ", " zombie, ", " stopped, ",
X  " starting, ", " on cpu, ", " swapped, ",
X  NULL
X};
X
X/* these are for detailing the cpu states */
X
Xint cpu_states[CPUSTATES];
Xchar *cpustatenames[] =
X{
X  "idle", "user", "kernel", "wait", 
X  NULL
X};
X
X/* these are for detailing the memory statistics */
X
Xint memory_stats[5];
Xchar *memorynames[] =
X{
X  "K real, ", "K active, ", "K free, ", "K swap, ", "K free swap", NULL
X};
X
X/* these are for keeping track of the proc array */
X
Xstatic int bytes;
Xstatic struct prpsinfo *pbase;
Xstatic struct prpsinfo **pref;
Xstatic int nxxxx = 0;
X
X#define AVE 3.0
Xstatic struct xxxx {
X        double start;
X        double cpu;
X        double pct;
X        int    pid;
X	int    pr_start;
X	int    valid;
X} *xxxx = NULL;
X
X
X
X/* useful externals */
Xextern int errno;
Xextern char *sys_errlist[];
Xextern char *myname;
X
Xlong lseek ();
Xlong percentages ();
Xdouble xxxx_pct();
X
Xmachine_init (statics)
X     struct statics *statics;
X{
X  register int i;
X  static struct var v;
X
X  /* open kernel memory */
X  if ((kmem = open (KMEM, 0)) < 0)
X    {
X      perror (KMEM);
X      exit (20);
X    }
X
X  /* get the list of symbols we want to access in the kernel */
X  if ((i = nlist (UNIX, nlst)) < 0)
X    {
X      fprintf (stderr, "%s: nlist failed\n", myname);
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  /* NPROC Tuning parameter for max number of processes */
X  (void) getkval (nlst[X_V].n_value, &v, sizeof (struct var), nlst[X_V].n_name);
X  nproc = v.v_proc;
X
X  /* stash away certain offsets for later use */
X  mpid_offset = nlst[X_MPID].n_value;
X  nproc_offset = nlst[X_NPROC].n_value;
X  avenrun_offset = nlst[X_AVENRUN].n_value;
X  anoninfo_offset = nlst[X_ANONINFO].n_value;
X  freemem_offset = nlst[X_FREEMEM].n_value;
X  maxmem_offset = nlst[X_MAXMEM].n_value;
X  availrmem_offset = nlst[X_AVAILRMEM].n_value;
X  swapfs_minfree_offset = nlst[X_SWAPFS_MINFREE].n_value;
X  (void) getkval(nlst[X_NCPUS].n_value, (int *)(&ncpus),
X                 sizeof(nproc), "ncpus");
X  cpu_offset = (unsigned long *)malloc(ncpus*sizeof (unsigned long));
X  (void) getkval (nlst[X_CPU].n_value, cpu_offset, 
X		  ncpus*sizeof (unsigned long), nlst[X_CPU].n_name);
X
X  /* allocate space for proc structure array and array of pointers */
X  bytes = nproc * sizeof (struct prpsinfo);
X  pbase = (struct prpsinfo *) malloc (bytes);
X  pref = (struct prpsinfo **) malloc (nproc * sizeof (struct prpsinfo *));
X  xxxx = (struct xxxx *) malloc(sizeof(struct xxxx)*nproc);
X
X  /* Just in case ... */
X  if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL)
X    {
X      fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
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  /* all done! */
X  return (0);
X}
X
X
Xchar *
Xformat_header (uname_field)
X     register 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)
X     struct system_info *si;
X{
X  load_avg avenrun[3];
X  struct cpu cpu;
X  register int j, i;
X
X  /* get the cp_time array */
X  for (j = 0; j < CPUSTATES; j++)
X    cp_time[j] = 0L;
X  for (i=0; i<ncpus; i++)  {
X      (void) getkval (cpu_offset[i], &cpu, sizeof (struct cpu), "cpu");
X      for (j = 0; j < CPUSTATES; j++)
X      	  cp_time[j] += (long) cpu.cpu_stat.cpu_sysinfo.cpu[j];
X  }
X
X  /* get load average array */
X  (void) getkval (avenrun_offset, (int *) avenrun, sizeof (avenrun),
X		  "avenrun");
X
X  /* get mpid -- process id of last process */
X  (void) getkval (mpid_offset, &(si->last_pid), sizeof (si->last_pid),
X		  "mpid");
X
X  /* convert load averages to doubles */
X  {
X    register int i;
X    register double *infoloadp;
X    register load_avg *sysloadp;
X
X    infoloadp = si->load_avg;
X    sysloadp = avenrun;
X    for (i = 0; i < 3; i++)
X      {
X	*infoloadp++ = loaddouble (*sysloadp++);
X      }
X  }
X
X  /* convert cp_time counts to percentages */
X  (void) percentages (CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
X
X  (void) getkval (freemem_offset, (int *) (&freemem), sizeof (freemem), "freemem");
X  (void) getkval (maxmem_offset, (int *) (&maxmem), sizeof (maxmem), "maxmem");
X  memory_stats[0] = pagetok (maxmem);
X  memory_stats[1] = 0;
X  memory_stats[2] = pagetok (freemem);
X  (void) getkval (anoninfo_offset, (int *) (&anoninfo), sizeof (anoninfo),
X		  "anoninfo");
X  (void) getkval (availrmem_offset, (int *) (&availrmem), sizeof (availrmem), "availrmem");
X  (void) getkval (swapfs_minfree_offset, (int *) (&swapfs_minfree), sizeof (swapfs_minfree), "swapfs_minfree");
X  memory_stats[3] = pagetok (anoninfo.ani_resv);
X  memory_stats[4] = pagetok (MAX (anoninfo.ani_max - anoninfo.ani_resv, 0) + availrmem - swapfs_minfree);
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 
Xget_process_info (si, sel, compare)
X     struct system_info *si;
X     struct process_select *sel;
X     int (*compare) ();
X{
X  register int i;
X  register int total_procs;
X  register int active_procs;
X  register struct prpsinfo **prefp;
X  register struct prpsinfo *pp;
X
X  /* these are copied out of sel for speed */
X  int show_idle;
X  int show_system;
X  int show_uid;
X
X  /* Get current number of processes */
X  (void) getkval (nproc_offset, (int *) (&nproc), sizeof (nproc), "nproc");
X
X  /* read all the proc structures */
X  getptable (pbase);
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
X  /* count up process states and get pointers to interesting procs */
X  total_procs = 0;
X  active_procs = 0;
X  bzero ((char *) process_states, sizeof (process_states));
X  prefp = pref;
X
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->pr_state != 0 &&
X	  (show_system || ((pp->pr_flag & SSYS) == 0)))
X	{
X	  total_procs++;
X	  process_states[pp->pr_state]++;
X	  if ((!pp->pr_zomb) &&
X	      (show_idle || (pp->pr_state == SRUN) || (pp->pr_state == SONPROC)) &&
X	      (!show_uid || pp->pr_uid == (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 prpsinfo *), compare);
X    }
X
X  /* remember active and total counts */
X  si->p_total = total_procs;
X  si->p_active = 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 *
Xformat_next_process (handle, get_userid)
X     caddr_t handle;
X     char *(*get_userid) ();
X{
X  register struct prpsinfo *pp;
X  struct handle *hp;
X  register long cputime;
X  double pctcpu;
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 cpu usage and calculate the cpu percentages */
X  cputime = pp->pr_time.tv_sec;
X  pctcpu = xxxx_pct(pp->pr_pid)/100.0;
X
X  /* format this entry */
X  sprintf (fmt,
X	   Proc_format,
X	   pp->pr_pid,
X	   (*get_userid) (pp->pr_uid),
X	   pp->pr_pri - PZERO,
X	   pp->pr_nice - NZERO,
X	   pp->pr_bysize / 1024,
X	   pp->pr_byrssize / 1024,
X	   state_abbrev[pp->pr_state],
X	   cputime / 60l,
X	   cputime % 60l,
X	   pctcpu,
X	   pp->pr_fname);
X
X  /* return the result */
X  return (fmt);
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 */
Xint 
Xcheck_nlist (nlst)
X     register struct nlist *nlst;
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	  fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
X	  i = 1;
X	}
X      nlst++;
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 */
Xgetkval (offset, ptr, size, refstr)
X     unsigned long offset;
X     int *ptr;
X     int size;
X     char *refstr;
X{
X  if (lseek (kmem, (long) offset, 0) == -1)
X    {
X      if (*refstr == '!')
X	{
X	  refstr++;
X	}
X      fprintf (stderr, "%s: lseek to %s: %s\n",
X	       KMEM, refstr, sys_errlist[errno]);
X      quit (22);
X    }
X  if (read (kmem, (char *) ptr, size) == -1)
X    {
X      if (*refstr == '!')
X	{
X	  /* we lost the race with the kernel, process isn't in memory */
X	  return (0);
X	}
X      else
X	{
X	  fprintf (stderr, "%s: reading %s: %s\n",
X		   KMEM, refstr, sys_errlist[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
X
Xunsigned char sorted_state[] =
X{
X  0,				/* not used		*/
X  3,				/* sleep		*/
X  6,				/* run			*/
X  2,				/* zombie		*/
X  4,				/* stop			*/
X  5,				/* start		*/
X  7,				/* run on a processor   */
X  1				/* being swapped (WAIT)	*/
X};
X
Xproc_compare (pp1, pp2)
X     struct prpsinfo **pp1;
X     struct prpsinfo **pp2;
X{
X  register struct prpsinfo *p1;
X  register struct prpsinfo *p2;
X  register long result;
X
X  /* remove one level of indirection */
X  p1 = *pp1;
X  p2 = *pp2;
X
X  /* compare percent cpu (pctcpu) */
X  if ((result = (long) (xxxx_pct(p2->pr_pid) - xxxx_pct(p1->pr_pid))) == 0)
X    {
X      /* use cpticks to break the tie */
X      if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
X	{
X	  /* use process state to break the tie */
X	  if ((result = (long) (sorted_state[p2->pr_state] -
X				sorted_state[p1->pr_state])) == 0)
X	    {
X	      /* use priority to break the tie */
X	      if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0)
X		{
X		  /* use resident set size (rssize) to break the tie */
X		  if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
X		    {
X		      /* use total memory to break the tie */
X		      result = (p2->pr_size - p1->pr_size);
X		    }
X		}
X	    }
X	}
X    }
X  return (result);
X}
X
X/*
Xget process table
X V.4 only has a linked list of processes so we want to follow that
X linked list, get all the process structures, and put them in our own
X table
X*/
Xgetptable (baseptr)
X     struct prpsinfo *baseptr;
X{
X  struct prpsinfo *currproc;	/* pointer to current proc structure	*/
X  int numprocs = 0;
X  DIR *procdir;
X  struct dirent *direntp;
X  int fd;
X  char fname[40];
X  struct timeval t;
X  double now;
X
X  gettimeofday(&t, NULL);
X  now = t.tv_sec + t.tv_usec/1000000.0;
X  xxxx_init();
X  if ((procdir = opendir (PROCFS)) == NULL)
X    {
X      fprintf (stderr, "%s: Unable to open %s\n", myname, PROCFS);
X      exit (1);
X    }
X
X  while (((direntp = readdir (procdir)) != NULL) && (numprocs < nproc))
X    {
X      if ((!strcmp (direntp->d_name, ".")) || (!strcmp (direntp->d_name, "..")))
X	{
X	  continue;
X	}
X      strcpy (fname, PROCFS);
X      strcat (fname, "/");
X      strcat (fname, direntp->d_name);
X      if ((fd = open (fname, O_RDONLY)) < 0)
X	{
X/*	   fprintf(stderr,"%s: Unable to open %s\n",myname, direntp->d_name); */
X	  close (fd);
X	  continue;
X	}
X      currproc = &baseptr[numprocs];
X      if (ioctl (fd, PIOCPSINFO, currproc) < 0)
X	{
X/*  	 fprintf(stderr,"%s: Unable to get info from %s\n", myname, direntp->d_name); */
X	  close (fd);
X	  continue;
X	}
X      numprocs++;
X      xxxx_add(currproc, now);
X      close (fd);
X    }
X  closedir (procdir);
X  if (nproc != numprocs)
X    nproc = numprocs;
X  xxxx_sort();
X}
X
Xxxxx_add(proc, now)
Xstruct prpsinfo *proc;
Xdouble now;
X{
X    int i;
X    double cpu;
X    double diff;
X    double pct;
X
X    cpu =  proc->pr_time.tv_sec + proc->pr_time.tv_nsec/1000000000.0;
X    for (i=0; i<nxxxx; i++) {
X	if (proc->pr_pid == xxxx[i].pid) {
X	    if (proc->pr_start.tv_sec == xxxx[i].pr_start) {
X		diff = now - xxxx[i].start;
X		pct =  (cpu - xxxx[i].cpu)/diff;
X		if (pct > 1.0) pct = 1.0;
X		xxxx[i].pct = ((AVE-1.0)*pct + xxxx[i].pct)/AVE;
X		xxxx[i].start = now;
X		xxxx[i].cpu = cpu;
X		xxxx[i].valid = 1;
X	        return;
X	    } else {
X    		xxxx[i].pct =  0;
X    		xxxx[i].start = now;
X    		xxxx[i].cpu = cpu;
X    		xxxx[i].valid = 1;
X    		xxxx[i].pr_start = proc->pr_start.tv_sec;
X		return;
X	    }
X	}
X    }
X    xxxx[i].pct =  0;
X    xxxx[i].start = now;
X    xxxx[i].cpu = cpu;
X    xxxx[i].valid = 1;
X    xxxx[i].pr_start = proc->pr_start.tv_sec;
X    xxxx[i].pid = proc->pr_pid;
X    nxxxx++;
X}
X		
Xxxxx_init()
X{
X    int i;
X
X    for (i=0; i<nproc; i++) {
X         xxxx[i].valid = 0;
X    }
X}
X
Xdouble
Xxxxx_pct(pid)
Xint pid;
X{
X    int i;
X    
X    for (i=0; i<nxxxx; i++) {
X 	if (xxxx[i].pid > pid) return 0.0;
X	/*
X 	 * We return pct*10000 so that proc_compare can make a finer
X	 * compareson by pct.
X	 */
X	if (xxxx[i].pid == pid)  return (10000.0*xxxx[i].pct);
X    }
X    return 0.0;
X}
X
X
Xxxxx_compare(a,b)
Xstruct xxxx *a;
Xstruct xxxx *b;
X{
X     if (a->valid > b->valid) return -1;
X     if (a->valid < b->valid) return 1;
X
X     if (a->pid < b->pid) return -1;
X     if (a->pid > b->pid) return 1;
X     return 0;
X}
X     
Xxxxx_sort()
X{
X    int i;
X
X    if (!nxxxx) return;
X    qsort((char *)xxxx,  nxxxx, sizeof(struct xxxx), xxxx_compare);
X    for (i=0; i<nxxxx; i++) {
X	if (!xxxx[i].valid) break;
X    }
X    nxxxx = i;
X}
X
X
X#ifdef SECURITY_OPTION
X#include <sys/resource.h>	/* for PRIO_PROCESS */
X
X#define ROOT_ID		 0
X#define NICE_VALUE	10
X#define TRUE		 1
X#define FALSE		 0
X
Xint not_su = -1;
Xint real_uid;
X
X/* if su return ok, else check to see if it's our process */
X/* if it's ours ok, else -1				  */
Xcheck_secure(procnum)
Xint procnum;
X{
Xregister struct prpsinfo *p;
Xregister int i;
X
X	if (not_su == -1) init_secure();
X	if (not_su) {
X	   for (i=0,p=pbase;i<nproc;i++,p++) 
X		if ( p->pr_pid == procnum ) 
X		    return( (p->pr_uid == real_uid) ? 0 : -1);
X	} else return(0);
X}
X
X/* find out if we're really the superuser or just pretending */
Xinit_secure()
X{
X	/* get real uid and find out if it's really root */
X	real_uid=getuid();
X
X	not_su = (real_uid != ROOT_ID) ? TRUE : FALSE;
X}
X
Xnice_us()
X{
X	setpriority(PRIO_PROCESS, getpid(), NICE_VALUE);
X}
X#endif /* SECURITY_OPTION */
X
X
X
END_OF_FILE
if test 19824 -ne `wc -c <'m_sunos5.c'`; then
    echo shar: \"'m_sunos5.c'\" unpacked with wrong size!
fi
# end of 'm_sunos5.c'
fi
if test -f 'm_sunos5.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'m_sunos5.man'\"
else
echo shar: Extracting \"'m_sunos5.man'\" \(402 characters\)
sed "s/^X//" >'m_sunos5.man' <<'END_OF_FILE'
X.SH "SunOS 5.1 DIFFERENCES"
X
XSunOS 5.1 does compute an usefully WCPU so only the %CPU is displayed.
X
XMost of the SunOS 5.1 port is based on the System V Release 4 
Xport of Robert Boucher <boucher@ncs.dnd.ca>. This port was modified
Xby Marc Cohen <marc@aai.com>,  Robert Boucher <rob@asimov.uucp> 
Xwho correct the cpu and memory stats and  William L. Jones 
Xwho added multi cpu support and better %CPU.
END_OF_FILE
if test 402 -ne `wc -c <'m_sunos5.man'`; then
    echo shar: \"'m_sunos5.man'\" unpacked with wrong size!
fi
# end of 'm_sunos5.man'
fi
echo shar: End of shell archive.
exit 0
This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:07:34 CDT