Home | History | Annotate | Line # | Download | only in machine
      1 /*
      2  * Copyright (c) 1984 through 2008, William LeFebvre
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *
     16  *     * Neither the name of William LeFebvre nor the names of other
     17  * contributors may be used to endorse or promote products derived from
     18  * this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*
     34  * top - a top users display for Unix
     35  *
     36  * SYNOPSIS:  For Intel based System V Release 5 (Unixware7)
     37  *
     38  * DESCRIPTION:
     39  * System V release 5 for i[3456]86
     40  * Works for:
     41  * i586-sco-sysv5uw7  i386 SCO UNIX_SVR5 (UnixWare 7)
     42  *
     43  * LIBS:  -lelf -lmas
     44  *
     45  * CFLAGS: -DHAVE_GETOPT -DORDER
     46  *
     47  * AUTHORS: Mike Hopkirk       <hops (at) sco.com>
     48  *          David Cutter       <dpc (at) grail.com>
     49  *          Andrew Herbert     <andrew (at) werple.apana.org.au>
     50  *          Robert Boucher     <boucher (at) sofkin.ca>
     51  */
     52 
     53 /* build config
     54  *  SHOW_NICE - process nice fields don't seem to be being updated so changed
     55  *     default to display # of threads in use instead.
     56  *     define this to display nice fields (values always 0)
     57  * #define SHOW_NICE 1
     58  */
     59 
     60 #define _KMEMUSER
     61 #define prpsinfo psinfo
     62 #include <sys/procfs.h>
     63 
     64 #define pr_state pr_lwp.pr_state
     65 #define pr_nice pr_lwp.pr_nice
     66 #define pr_pri pr_lwp.pr_pri
     67 #define pr_onpro pr_lwp.pr_onpro
     68 #define ZOMBIE(p)	((p)->pr_nlwp == 0)
     69 #define SIZE_K(p)	pagetok((p)->pr_size)
     70 #define RSS_K(p)	pagetok((p)->pr_rssize)
     71 
     72 
     73 #include <stdio.h>
     74 #include <fcntl.h>
     75 #include <unistd.h>
     76 #include <stdlib.h>
     77 #include <errno.h>
     78 #include <dirent.h>
     79 #include <nlist.h>
     80 #include <string.h>
     81 #include <sys/types.h>
     82 #include <sys/param.h>
     83 #include <sys/proc.h>
     84 #include <sys/sysmacros.h>
     85 #include <vm/anon.h>
     86 #include <sys/priocntl.h>
     87 #include <sys/tspriocntl.h>
     88 #include <sys/var.h>
     89 
     90 #include "top.h"
     91 #include "machine.h"
     92 #include "utils.h"
     93 
     94 #define UNIX "/stand/unix"
     95 #define KMEM "/dev/kmem"
     96 #define PROCFS "/proc"
     97 #define CPUSTATES	5
     98 
     99 #ifndef PRIO_MAX
    100 #define PRIO_MAX	20
    101 #endif
    102 #ifndef PRIO_MIN
    103 #define PRIO_MIN	-20
    104 #endif
    105 
    106 #ifndef FSCALE
    107 #define FSHIFT  8		/* bits to right of fixed binary point */
    108 #define FSCALE  (1<<FSHIFT)
    109 #endif
    110 
    111 #define loaddouble(x) ((double)x/FSCALE)
    112 #define pagetok(size) ((size) * pagesz) >> LOG1024
    113 
    114 /* definitions for the index in the nlist array */
    115 #define X_AVENRUN	0
    116 #define X_V		1
    117 #define X_MPID		2
    118 
    119 static struct nlist nlst[] =
    120 {
    121    {"avenrun"},		        /* 0 */
    122    {"v"},			/* 1 */
    123    {"nextpid"},                 /* 2 */
    124   {NULL}
    125 };
    126 
    127 static unsigned long avenrun_offset;
    128 static unsigned long mpid_offset;
    129 
    130 static unsigned int pagesz;
    131 
    132 static void reallocproc(int n);
    133 static int maxprocs;
    134 
    135 /* get_process_info passes back a handle.  This is what it looks like: */
    136 
    137 struct handle
    138 {
    139     struct prpsinfo **next_proc;/* points to next valid proc pointer */
    140     int remaining;		/* number of pointers remaining */
    141 };
    142 
    143 /*
    144  *  These definitions control the format of the per-process area
    145  */
    146 
    147 static char header[] =
    148 #ifdef SHOW_NICE
    149 "  PID X        PRI NICE  SIZE   RES STATE   TIME      CPU  COMMAND";
    150 #else
    151 "  PID X        PRI  THR  SIZE   RES STATE   TIME      CPU  COMMAND";
    152 #endif
    153 /* 0123456   -- field to fill in starts at header+6 */
    154 #define UNAME_START 6
    155 #define Proc_format \
    156 	"%5d %-8.8s %3d %4d %5s %5s %-5s %6s %8.4f%% %.16s"
    157 
    158 char *state_abbrev[] =
    159 {"oncpu", "run", "sleep",  "stop", "idle", "zombie"};
    160 
    161 #define sZOMB 5
    162 int process_states[8];
    163 char *procstatenames[] =
    164 {
    165   " on cpu, ", " running, ", " sleeping, ", " stopped, ",
    166   " idling ",  " zombie, ",
    167   NULL
    168 };
    169 
    170 int cpu_states[CPUSTATES];
    171 char *cpustatenames[] =
    172 {"idle", "user", "kernel", "wait", NULL};
    173 
    174 
    175 /* these are for detailing the memory statistics */
    176 long memory_stats[5];
    177 char *memorynames[] =
    178 {"K phys, ", "K used, ", "K free, ", "K swapUsed, ", "K swapFree", NULL};
    179 
    180 /* these are names given to allowed sorting orders -- first is default */
    181 char *ordernames[] =
    182 {"state", "cpu", "size", "res", "time", "pid", "uid", "rpid", "ruid", NULL};
    183 
    184 /* forward definitions for comparison functions */
    185 int proc_compare();
    186 int compare_cpu();
    187 int compare_size();
    188 int compare_res();
    189 int compare_time();
    190 int compare_pid();
    191 int compare_uid();
    192 int compare_rpid();
    193 int compare_ruid();
    194 
    195 int (*proc_compares[])() = {
    196     proc_compare,
    197     compare_cpu,
    198     compare_size,
    199     compare_res,
    200     compare_time,
    201     compare_pid,
    202     compare_uid,
    203     compare_rpid,
    204     compare_ruid,
    205     NULL };
    206 
    207 
    208 static int kmem = -1;
    209 static int nproc;
    210 static int bytes;
    211 static struct prpsinfo *pbase;
    212 static struct prpsinfo **pref;
    213 static DIR *procdir;
    214 
    215 /* useful externals */
    216 extern int errno;
    217 extern char *sys_errlist[];
    218 extern char *myname;
    219 extern long percentages ();
    220 extern int check_nlist ();
    221 extern int getkval ();
    222 extern void perror ();
    223 extern void getptable ();
    224 extern void quit ();
    225 extern int nlist ();
    226 
    227 /* fwd dcls */
    228 static int kmet_init(void );
    229 static int get_cpustates(int *new);
    230 
    231 
    232 int
    233 machine_init (struct statics *statics)
    234   {
    235     static struct var v;
    236     int i;
    237 
    238     /* fill in the statics information */
    239     statics->procstate_names = procstatenames;
    240     statics->cpustate_names = cpustatenames;
    241     statics->memory_names = memorynames;
    242     statics->order_names = ordernames;
    243 
    244     /* get the list of symbols we want to access in the kernel */
    245     if (nlist (UNIX, nlst))
    246       {
    247 	(void) fprintf (stderr, "Unable to nlist %s\n", UNIX);
    248 	return (-1);
    249       }
    250 
    251     /* make sure they were all found */
    252     if (check_nlist (nlst) > 0)
    253       return (-1);
    254 
    255     /* open kernel memory */
    256     if ((kmem = open (KMEM, O_RDONLY)) == -1)
    257       {
    258 	perror (KMEM);
    259 	return (-1);
    260       }
    261 
    262     v.v_proc=200;   /* arbitrary default */
    263     /* get the symbol values out of kmem */
    264     /* NPROC Tuning parameter for max number of processes */
    265     (void) getkval (nlst[X_V].n_value, &v, sizeof (struct var), nlst[X_V].n_name);
    266     nproc = v.v_proc;
    267     maxprocs = nproc;
    268 
    269     /* stash away certain offsets for later use */
    270     mpid_offset = nlst[X_MPID].n_value;
    271     avenrun_offset = nlst[X_AVENRUN].n_value;
    272 
    273     /* allocate space for proc structure array and array of pointers */
    274     bytes = nproc * sizeof (struct prpsinfo);
    275     pbase = (struct prpsinfo *) malloc (bytes);
    276     pref = (struct prpsinfo **) malloc (nproc * sizeof (struct prpsinfo *));
    277 
    278     pagesz = sysconf(_SC_PAGESIZE);
    279 
    280 
    281     /* Just in case ... */
    282     if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL)
    283       {
    284 	(void) fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
    285 	return (-1);
    286       }
    287 
    288     if (!(procdir = opendir (PROCFS)))
    289       {
    290 	(void) fprintf (stderr, "Unable to open %s\n", PROCFS);
    291 	return (-1);
    292       }
    293 
    294     if (chdir (PROCFS))
    295     {				/* handy for later on when we're reading it */
    296 	(void) fprintf (stderr, "Unable to chdir to %s\n", PROCFS);
    297 	return (-1);
    298     }
    299 
    300 
    301     kmet_init();
    302 
    303     /* all done! */
    304     return (0);
    305   }
    306 
    307 char *
    308 format_header (char *uname_field)
    309 {
    310   register char *ptr;
    311 
    312   ptr = header + UNAME_START;
    313   while (*uname_field != '\0')
    314     *ptr++ = *uname_field++;
    315 
    316   return (header);
    317 }
    318 
    319 void
    320 get_system_info (struct system_info *si)
    321 {
    322   long avenrun[3];
    323   long mem;
    324   static time_t cp_old[CPUSTATES];
    325   static time_t cp_diff[CPUSTATES];	/* for cpu state percentages */
    326   register int i;
    327   static long swap_total;
    328   static long swap_free;
    329   int new_states[CPUSTATES];
    330 
    331   get_cpustates(new_states);
    332 
    333   /* convert cp_time counts to percentages */
    334   (void) percentages (CPUSTATES, cpu_states, new_states, cp_old, cp_diff);
    335 
    336 
    337   si->last_pid = -1;
    338   /* get mpid -- process id of last process
    339    * svr5 is nextpid - next pid to be assigned (already incremented)
    340    */
    341    (void) getkval (mpid_offset, &(si->last_pid), sizeof (si->last_pid),
    342    		  "nextpid");
    343    (si->last_pid)--;    /* so we shld decrement for display */
    344 
    345 
    346   /* get load average array */
    347   (void) getkval (avenrun_offset, (int *) avenrun, sizeof (avenrun), "avenrun");
    348   /* convert load averages to doubles */
    349   for (i = 0; i < 3; i++)
    350     si->load_avg[i] = loaddouble(avenrun[i]);
    351 
    352   mem = sysconf(_SC_TOTAL_MEMORY);      /* physical mem */
    353   memory_stats[0] = pagetok (mem);
    354 
    355   mem = kmet_get_freemem();             /* free mem */
    356   memory_stats[2] = pagetok (mem);
    357 
    358   /* mem = sysconf(_SC_GENERAL_MEMORY);    */
    359   memory_stats[1] = memory_stats[0] - memory_stats[2]; /* active */
    360 
    361   get_swapinfo(&swap_total, &swap_free);
    362   memory_stats[3] = pagetok(swap_total - swap_free);
    363   memory_stats[4] = pagetok(swap_free);
    364 
    365 
    366   /* set arrays and strings */
    367   si->cpustates = cpu_states;
    368   si->memory = memory_stats;
    369 }
    370 
    371 static struct handle handle;
    372 
    373 caddr_t
    374 get_process_info (
    375 		   struct system_info *si,
    376 		   struct process_select *sel,
    377 		   int idx)
    378 {
    379   register int i;
    380   register int total_procs;
    381   register int active_procs;
    382   register struct prpsinfo **prefp;
    383   register struct prpsinfo *pp;
    384 
    385   /* these are copied out of sel for speed */
    386   int show_idle;
    387   int show_system;
    388   int show_uid;
    389 
    390   /* Get current number of processes */
    391 
    392   /* read all the proc structures */
    393   getptable (pbase);
    394 
    395   /* get a pointer to the states summary array */
    396   si->procstates = process_states;
    397 
    398   /* set up flags which define what we are going to select */
    399   show_idle   = sel->idle;
    400   show_system = sel->system;
    401   show_uid    = sel->uid != -1;
    402 
    403   nproc = kmet_get_nproc();
    404 
    405   /* count up process states and get pointers to interesting procs */
    406   total_procs = 0;
    407   active_procs = 0;
    408   (void) memset (process_states, 0, sizeof (process_states));
    409   prefp = pref;
    410 
    411   for (pp = pbase, i = 0; i < nproc; pp++, i++)
    412   {
    413       /*
    414 	 *  Place pointers to each valid proc structure in pref[].
    415 	 *  Process slots that are actually in use have a non-zero
    416 	 *  status field.  Processes with PR_ISSYS set are system
    417 	 *  processes---these get ignored unless show_sysprocs is set.
    418 	 */
    419       if ((pp->pr_state >= SONPROC && pp->pr_state <= SIDL)  &&
    420 	  (show_system || ((pp->pr_flag & PR_ISSYS) == 0)))
    421       {
    422 	  total_procs++;
    423 	  process_states[pp->pr_state]++;
    424 	  if ((!ZOMBIE(pp)) &&
    425 	      (show_idle || (pp->pr_state == SRUN) || (pp->pr_state == SONPROC)) &&
    426 	      (!show_uid || pp->pr_uid == (uid_t) sel->uid))
    427 	  {
    428 	      *prefp++ = pp;
    429 	      active_procs++;
    430 	  }
    431 	  if (ZOMBIE(pp))
    432     	    process_states[sZOMB]++;    /* invented */
    433 
    434       }
    435   }
    436 
    437   /* if requested, sort the "interesting" processes */
    438   qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *),
    439 	 proc_compares[idx]);
    440 
    441   /* remember active and total counts */
    442   si->p_total = total_procs;
    443   si->P_ACTIVE = active_procs;
    444 
    445   /* pass back a handle */
    446   handle.next_proc = pref;
    447   handle.remaining = active_procs;
    448   return ((caddr_t) & handle);
    449 }
    450 
    451 /*
    452  * cpu percentage calculation is as fm ps.c
    453  * seems to be ratio of (sys+user time used)/(elapsed time)
    454  * i.e percent of cpu utilised when on cpu
    455  */
    456 static double percent_cpu( struct prpsinfo *pp)
    457 {
    458     static time_t tim = 0L;
    459     time_t starttime;
    460     time_t ctime;
    461     time_t etime;
    462 
    463     /* if (tim == 0L) */
    464         tim = time((time_t *) 0);
    465     starttime = pp->pr_start.tv_sec;
    466     if (pp->pr_start.tv_nsec > 500000000)
    467             starttime++;
    468     etime = (tim - starttime);
    469     ctime = pp->pr_time.tv_sec;
    470     if (pp->pr_time.tv_nsec > 500000000)
    471     ctime++;
    472     if (etime)
    473     {
    474         /* return  (float)(ctime * 100) / (unsigned)etime; */
    475         /* this was ocasionally giving vals >100 for some
    476          * unknown reason so the below normalises it
    477          */
    478 
    479         double pct;
    480         pct = (float)(ctime * 100) / (unsigned)etime;
    481         return (pct < 100.0) ? pct : 100.00;
    482     }
    483     return 0.00;
    484 }
    485 
    486 
    487 char fmt[MAX_COLS];			/* static area where result is built */
    488 
    489 char *
    490 format_next_process (
    491 		      caddr_t handle,
    492 		      char *(*get_userid) ())
    493 {
    494   register struct prpsinfo *pp;
    495   struct handle *hp;
    496   register long cputime;
    497   register double pctcpu;
    498 
    499   /* find and remember the next proc structure */
    500   hp = (struct handle *) handle;
    501   pp = *(hp->next_proc++);
    502   hp->remaining--;
    503 
    504   /* get the cpu usage and calculate the cpu percentages */
    505   cputime = pp->pr_time.tv_sec;
    506   pctcpu = percent_cpu(pp);
    507 
    508 
    509   /* format this entry */
    510   (void) sprintf (fmt,
    511 		  Proc_format,
    512 		  pp->pr_pid,
    513 		  (*get_userid) (pp->pr_uid),
    514                   pp->pr_pri,
    515 #ifdef SHOW_NICE
    516 		  pp->pr_nice,
    517 #else
    518 	          (u_short)pp->pr_nlwp < 999 ? (u_short)pp->pr_nlwp : 999,
    519 #endif
    520 	          format_k(SIZE_K(pp)),
    521                   format_k(RSS_K(pp)),
    522 	          (ZOMBIE(pp))  ? state_abbrev[sZOMB]
    523                                 : state_abbrev[pp->pr_state],
    524 		  format_time(cputime),
    525 		  /* 100.0 * */ pctcpu,
    526 		  printable(pp->pr_fname));
    527 
    528   /* return the result */
    529   return (fmt);
    530 }
    531 
    532 /*
    533  * check_nlist(nlst) - checks the nlist to see if any symbols were not
    534  *		found.  For every symbol that was not found, a one-line
    535  *		message is printed to stderr.  The routine returns the
    536  *		number of symbols NOT found.
    537  */
    538 int
    539 check_nlist (register struct nlist *nlst)
    540 {
    541   register int i;
    542 
    543   /* check to see if we got ALL the symbols we requested */
    544   /* this will write one line to stderr for every symbol not found */
    545 
    546   i = 0;
    547   while (nlst->n_name != NULL)
    548     {
    549       if (nlst->n_value == 0)
    550 	{
    551 	  /* this one wasn't found */
    552 	  (void) fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
    553 	  i = 1;
    554 	}
    555       nlst++;
    556     }
    557   return (i);
    558 }
    559 
    560 
    561 /*
    562  *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
    563  *	"offset" is the byte offset into the kernel for the desired value,
    564  *  	"ptr" points to a buffer into which the value is retrieved,
    565  *  	"size" is the size of the buffer (and the object to retrieve),
    566  *  	"refstr" is a reference string used when printing error meessages,
    567  *	    if "refstr" starts with a '!', then a failure on read will not
    568  *  	    be fatal (this may seem like a silly way to do things, but I
    569  *  	    really didn't want the overhead of another argument).
    570  *
    571  */
    572 int
    573 getkval (
    574 	  unsigned long offset,
    575 	  int *ptr,
    576 	  int size,
    577 	  char *refstr)
    578 {
    579   if (lseek (kmem, (long) offset, 0) == -1)
    580     {
    581       if (*refstr == '!')
    582 	refstr++;
    583       (void) fprintf (stderr, "%s: lseek to %s: %s\n",
    584 		      myname, refstr, sys_errlist[errno]);
    585       quit (22);
    586     }
    587   if (read (kmem, (char *) ptr, size) == -1)
    588     if (*refstr == '!')
    589       /* we lost the race with the kernel, process isn't in memory */
    590       return (0);
    591     else
    592       {
    593 	(void) fprintf (stderr, "%s: reading %s: %s\n",
    594 			myname, refstr, sys_errlist[errno]);
    595 	quit (23);
    596       }
    597   return (1);
    598 }
    599 
    600 /* ----------------- comparison routines for qsort ---------------- */
    601 
    602 /* First, the possible comparison keys.  These are defined in such a way
    603    that they can be merely listed in the source code to define the actual
    604    desired ordering.
    605  */
    606 
    607 #define ORDERKEY_PCTCPU  if (dresult = percent_cpu (p2) - percent_cpu (p1),\
    608 			     (result = dresult > 0.0 ? 1 : \
    609 			     dresult < 0.0 ? -1 : 0) == 0)
    610 
    611 #define ORDERKEY_CPTICKS if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
    612 #define ORDERKEY_STATE   if ((result = (long) (sorted_state[p2->pr_state] - \
    613 			       sorted_state[p1->pr_state])) == 0)
    614 
    615 #define ORDERKEY_PRIO    if ((result = p2->pr_pri    - p1->pr_pri)    == 0)
    616 #define ORDERKEY_RSSIZE  if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
    617 #define ORDERKEY_MEM     if ((result = (p2->pr_size  - p1->pr_size))  == 0)
    618 
    619 #define ORDERKEY_PID     if ((result = (p2->pr_pid  - p1->pr_pid))  == 0)
    620 #define ORDERKEY_UID     if ((result = (p2->pr_uid  - p1->pr_uid))  == 0)
    621 #define ORDERKEY_RPID    if ((result = (p1->pr_pid  - p2->pr_pid))  == 0)
    622 #define ORDERKEY_RUID    if ((result = (p1->pr_uid  - p2->pr_uid))  == 0)
    623 
    624 /* states enum {SONPROC, SRUN, SSLEEP, SSTOP, SIDL}  */
    625 unsigned char sorted_state[] =
    626 {
    627   7,				/* onproc		*/
    628   6,				/* run		        */
    629   5,				/* sleep		*/
    630   4,				/* stop		        */
    631   3,				/* idle			*/
    632   2,				/* zombie		*/
    633   0,				/* unused               */
    634   0				/* unused	        */
    635 };
    636 
    637 #if 0
    638 /*
    639  *  proc_compare - original singleton comparison function for "qsort"
    640  *	Compares the resource consumption of two processes using five
    641  *  	distinct keys.  The keys (in descending order of importance) are:
    642  *  	percent cpu, cpu ticks, state, resident set size, total virtual
    643  *  	memory usage.  The process states are ordered as follows (from least
    644  *  	to most important):  WAIT, zombie, sleep, stop, start, run.  The
    645  *  	array declaration below maps a process state index into a number
    646  *  	that reflects this ordering.
    647  */
    648  /* default comparison rtn */
    649 int
    650 original_proc_compare (
    651 	       struct prpsinfo **pp1,
    652 	       struct prpsinfo **pp2)
    653   {
    654     register struct prpsinfo *p1;
    655     register struct prpsinfo *p2;
    656     register long result;
    657     double dresult;
    658 
    659     /* remove one level of indirection */
    660     p1 = *pp1;
    661     p2 = *pp2;
    662 
    663     /* compare percent cpu (pctcpu) */
    664     dresult = percent_cpu(p2) - percent_cpu (p1);
    665     result = dresult > 0.0 ?  1 :
    666              dresult < 0.0 ? -1 : 0;
    667     if (result)
    668     {
    669 	/* use cpticks to break the tie */
    670 	if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
    671 	  {
    672 	    /* use process state to break the tie */
    673 	    if ((result = (long) (sorted_state[p2->pr_state] -
    674 				  sorted_state[p1->pr_state])) == 0)
    675 	      {
    676 		/* use priority to break the tie */
    677 		if ((result = p2->pr_pri - p1->pr_pri) == 0)
    678 		  {
    679 		    /* use resident set size (rssize) to break the tie */
    680 		    if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
    681 		      {
    682 			/* use total memory to break the tie */
    683 			result = (p2->pr_size - p1->pr_size);
    684 		      }
    685 		  }
    686 	      }
    687 	  }
    688     }
    689     return (result);
    690   }
    691 #endif  /* original comparison rtn */
    692 
    693 /* compare_state - comparison function for sorting by state,pri,time,size */
    694 int
    695 proc_compare (
    696 	       struct prpsinfo **pp1,
    697 	       struct prpsinfo **pp2)
    698   {
    699     register struct prpsinfo *p1;
    700     register struct prpsinfo *p2;
    701     register long result;
    702     double dresult;
    703 
    704     /* remove one level of indirection */
    705     p1 = *pp1;
    706     p2 = *pp2;
    707 
    708     ORDERKEY_STATE
    709     ORDERKEY_PRIO
    710     ORDERKEY_CPTICKS
    711     ORDERKEY_RSSIZE
    712     ORDERKEY_MEM
    713     ORDERKEY_PCTCPU
    714     ;
    715 
    716     return (result);
    717   }
    718 
    719 
    720 /* compare_cpu - the comparison function for sorting by cpu % (deflt) */
    721 int
    722 compare_cpu (
    723 	       struct prpsinfo **pp1,
    724 	       struct prpsinfo **pp2)
    725   {
    726     register struct prpsinfo *p1;
    727     register struct prpsinfo *p2;
    728     register long result;
    729     double dresult;
    730 
    731     /* remove one level of indirection */
    732     p1 = *pp1;
    733     p2 = *pp2;
    734 
    735     ORDERKEY_PCTCPU
    736     ORDERKEY_CPTICKS
    737     ORDERKEY_STATE
    738     ORDERKEY_PRIO
    739     ORDERKEY_RSSIZE
    740     ORDERKEY_MEM
    741     ;
    742 
    743     return (result);
    744   }
    745 
    746 /* compare_size - the comparison function for sorting by total memory usage */
    747 int
    748 compare_size (
    749 	       struct prpsinfo **pp1,
    750 	       struct prpsinfo **pp2)
    751   {
    752     register struct prpsinfo *p1;
    753     register struct prpsinfo *p2;
    754     register long result;
    755     double dresult;
    756 
    757     /* remove one level of indirection */
    758     p1 = *pp1;
    759     p2 = *pp2;
    760 
    761     ORDERKEY_MEM
    762     ORDERKEY_RSSIZE
    763     ORDERKEY_PCTCPU
    764     ORDERKEY_CPTICKS
    765     ORDERKEY_STATE
    766     ORDERKEY_PRIO
    767     ;
    768 
    769     return (result);
    770   }
    771 
    772 /* compare_res - the comparison function for sorting by resident set size */
    773 int
    774 compare_res (
    775 	       struct prpsinfo **pp1,
    776 	       struct prpsinfo **pp2)
    777   {
    778     register struct prpsinfo *p1;
    779     register struct prpsinfo *p2;
    780     register long result;
    781     double dresult;
    782 
    783     /* remove one level of indirection */
    784     p1 = *pp1;
    785     p2 = *pp2;
    786 
    787     ORDERKEY_RSSIZE
    788     ORDERKEY_MEM
    789     ORDERKEY_PCTCPU
    790     ORDERKEY_CPTICKS
    791     ORDERKEY_STATE
    792     ORDERKEY_PRIO
    793     ;
    794 
    795     return (result);
    796   }
    797 
    798 /* compare_time - the comparison function for sorting by total cpu time */
    799 int
    800 compare_time (
    801 	       struct prpsinfo **pp1,
    802 	       struct prpsinfo **pp2)
    803   {
    804     register struct prpsinfo *p1;
    805     register struct prpsinfo *p2;
    806     register long result;
    807     double dresult;
    808 
    809     /* remove one level of indirection */
    810     p1 = *pp1;
    811     p2 = *pp2;
    812 
    813     ORDERKEY_CPTICKS
    814     ORDERKEY_PCTCPU
    815     ORDERKEY_STATE
    816     ORDERKEY_PRIO
    817     ORDERKEY_MEM
    818     ORDERKEY_RSSIZE
    819     ;
    820 
    821     return (result);
    822   }
    823 
    824 /* compare_pid - the comparison function for sorting by pid */
    825 int
    826 compare_pid (
    827 	       struct prpsinfo **pp1,
    828 	       struct prpsinfo **pp2)
    829   {
    830     register struct prpsinfo *p1;
    831     register struct prpsinfo *p2;
    832     register long result;
    833     double dresult;
    834 
    835     /* remove one level of indirection */
    836     p1 = *pp1;
    837     p2 = *pp2;
    838 
    839     ORDERKEY_PID
    840     ORDERKEY_CPTICKS
    841     ORDERKEY_PCTCPU
    842     ORDERKEY_STATE
    843     ORDERKEY_PRIO
    844     ORDERKEY_MEM
    845     ORDERKEY_RSSIZE
    846     ;
    847 
    848     return (result);
    849   }
    850 
    851 /* compare_uid - the comparison function for sorting by user ID */
    852 int
    853 compare_uid (
    854 	       struct prpsinfo **pp1,
    855 	       struct prpsinfo **pp2)
    856   {
    857     register struct prpsinfo *p1;
    858     register struct prpsinfo *p2;
    859     register long result;
    860     double dresult;
    861 
    862     /* remove one level of indirection */
    863     p1 = *pp1;
    864     p2 = *pp2;
    865 
    866     ORDERKEY_UID
    867     ORDERKEY_CPTICKS
    868     ORDERKEY_PCTCPU
    869     ORDERKEY_STATE
    870     ORDERKEY_PRIO
    871     ORDERKEY_MEM
    872     ORDERKEY_RSSIZE
    873     ;
    874 
    875     return (result);
    876   }
    877 
    878 /* compare_rpid - the comparison function for sorting by pid ascending */
    879 int
    880 compare_rpid (
    881 	       struct prpsinfo **pp1,
    882 	       struct prpsinfo **pp2)
    883   {
    884     register struct prpsinfo *p1;
    885     register struct prpsinfo *p2;
    886     register long result;
    887     double dresult;
    888 
    889     /* remove one level of indirection */
    890     p1 = *pp1;
    891     p2 = *pp2;
    892 
    893     ORDERKEY_RPID
    894     ORDERKEY_CPTICKS
    895     ORDERKEY_PCTCPU
    896     ORDERKEY_STATE
    897     ORDERKEY_PRIO
    898     ORDERKEY_MEM
    899     ORDERKEY_RSSIZE
    900     ;
    901 
    902     return (result);
    903   }
    904 
    905 /* compare_uid - the comparison function for sorting by user ID ascending */
    906 int
    907 compare_ruid (
    908 	       struct prpsinfo **pp1,
    909 	       struct prpsinfo **pp2)
    910   {
    911     register struct prpsinfo *p1;
    912     register struct prpsinfo *p2;
    913     register long result;
    914     double dresult;
    915 
    916     /* remove one level of indirection */
    917     p1 = *pp1;
    918     p2 = *pp2;
    919 
    920     ORDERKEY_RUID
    921     ORDERKEY_CPTICKS
    922     ORDERKEY_PCTCPU
    923     ORDERKEY_STATE
    924     ORDERKEY_PRIO
    925     ORDERKEY_MEM
    926     ORDERKEY_RSSIZE
    927     ;
    928 
    929     return (result);
    930   }
    931 
    932 
    933 /* ---------------- helper rtns ---------------- */
    934 
    935 /*
    936  * get process table
    937  */
    938 void
    939 getptable (struct prpsinfo *baseptr)
    940 {
    941   struct prpsinfo *currproc;	/* pointer to current proc structure	*/
    942   int numprocs = 0;
    943   struct dirent *direntp;
    944 
    945   currproc = baseptr;
    946   for (rewinddir (procdir); direntp = readdir (procdir);)
    947     {
    948       int fd;
    949       char buf[30];
    950 
    951       sprintf(buf,"%s/psinfo", direntp->d_name);
    952 
    953       if ((fd = open (buf, O_RDONLY)) < 0)
    954 	continue;
    955 
    956       if (read(fd, currproc, sizeof(psinfo_t)) != sizeof(psinfo_t))
    957       {
    958 	  (void) close (fd);
    959 	  continue;
    960       }
    961 
    962       numprocs++;
    963       currproc++;
    964 
    965       (void) close (fd);
    966 
    967       /* Atypical place for growth */
    968       if (numprocs >= maxprocs)
    969       {
    970 	    reallocproc(2 * numprocs);
    971 	    currproc = (struct prpsinfo *)
    972 		    ((char *)baseptr + sizeof(psinfo_t) * numprocs);
    973       }
    974 
    975     }
    976 
    977   if (nproc != numprocs)
    978     nproc = numprocs;
    979 }
    980 
    981 /* return the owner of the specified process, for use in commands.c as we're
    982    running setuid root */
    983 int
    984 proc_owner (int pid)
    985 {
    986   register struct prpsinfo *p;
    987   int i;
    988   for (i = 0, p = pbase; i < nproc; i++, p++)
    989     if (p->pr_pid == (pid_t)pid)
    990       return ((int)(p->pr_uid));
    991 
    992   return (-1);
    993 }
    994 
    995 int
    996 setpriority (int dummy, int who, int niceval)
    997 {
    998   int scale;
    999   int prio;
   1000   pcinfo_t pcinfo;
   1001   pcparms_t pcparms;
   1002   tsparms_t *tsparms;
   1003 
   1004   strcpy (pcinfo.pc_clname, "TS");
   1005   if (priocntl (0, 0, PC_GETCID, (caddr_t) & pcinfo) == -1)
   1006     return (-1);
   1007 
   1008   prio = niceval;
   1009   if (prio > PRIO_MAX)
   1010     prio = PRIO_MAX;
   1011   else if (prio < PRIO_MIN)
   1012     prio = PRIO_MIN;
   1013 
   1014   tsparms = (tsparms_t *) pcparms.pc_clparms;
   1015   scale = ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri;
   1016   tsparms->ts_uprilim = tsparms->ts_upri = -(scale * prio) / 20;
   1017   pcparms.pc_cid = pcinfo.pc_cid;
   1018 
   1019   if (priocntl (P_PID, who, PC_SETPARMS, (caddr_t) & pcparms) == -1)
   1020     return (-1);
   1021 
   1022   return (0);
   1023 }
   1024 
   1025 
   1026 get_swapinfo(long *total, long *fr)
   1027 {
   1028     register int cnt, i;
   1029     register long t, f;
   1030     struct swaptable *swt;
   1031     struct swapent *ste;
   1032     static char path[256];
   1033 
   1034     /* get total number of swap entries */
   1035     cnt = swapctl(SC_GETNSWP, 0);
   1036 
   1037     /* allocate enough space to hold count + n swapents */
   1038     swt = (struct swaptable *)malloc(sizeof(int) +
   1039 				     cnt * sizeof(struct swapent));
   1040     if (swt == NULL)
   1041     {
   1042 	*total = 0;
   1043 	*fr = 0;
   1044 	return;
   1045     }
   1046     swt->swt_n = cnt;
   1047 
   1048     /* fill in ste_path pointers: we don't care about the paths, so we point
   1049        them all to the same buffer */
   1050     ste = &(swt->swt_ent[0]);
   1051     i = cnt;
   1052     while (--i >= 0)
   1053     {
   1054 	ste++->ste_path = path;
   1055     }
   1056 
   1057     /* grab all swap info */
   1058     swapctl(SC_LIST, swt);
   1059 
   1060     /* walk thru the structs and sum up the fields */
   1061     t = f = 0;
   1062     ste = &(swt->swt_ent[0]);
   1063     i = cnt;
   1064     while (--i >= 0)
   1065     {
   1066 	/* dont count slots being deleted */
   1067 	if (!(ste->ste_flags & ST_INDEL) )
   1068 	{
   1069 	    t += ste->ste_pages;
   1070 	    f += ste->ste_free;
   1071 	}
   1072 	ste++;
   1073     }
   1074 
   1075     /* fill in the results */
   1076     *total = t;
   1077     *fr = f;
   1078     free(swt);
   1079 }
   1080 
   1081 
   1082 /*
   1083  * When we reach a proc limit, we need to realloc the stuff.
   1084  */
   1085 static void reallocproc(int n)
   1086 {
   1087     int bytes;
   1088     struct oldproc *op, *endbase;
   1089 
   1090     if (n < maxprocs)
   1091 	return;
   1092 
   1093     maxprocs = n;
   1094 
   1095     /* allocate space for proc structure array and array of pointers */
   1096     bytes = maxprocs * sizeof(psinfo_t) ;
   1097     pbase = (struct prpsinfo *) realloc(pbase, bytes);
   1098     pref = (struct prpsinfo **) realloc(pref,
   1099 			maxprocs * sizeof(struct prpsinfo *));
   1100 
   1101     /* Just in case ... */
   1102     if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL)
   1103     {
   1104 	fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
   1105 	quit(1);
   1106     }
   1107 }
   1108 
   1109 /* ---------------------------------------------------------------- */
   1110 /* Access kernel Metrics
   1111  * SVR5 uses metreg inteface to Kernel statistics (metrics)
   1112  *  see /usr/include/mas.h, /usr/include/metreg.h
   1113  */
   1114 
   1115 #include <sys/mman.h>
   1116 #include <sys/dl.h>
   1117 #include <mas.h>
   1118 #include <metreg.h>
   1119 
   1120 static int md;         /* metric descriptor handle */
   1121 static  uint32 ncpu;   /* number of processors in system */
   1122 
   1123 /* fwd dcls */
   1124 static uint32 kmet_get_cpu( int type, char *desc);
   1125 static void kmet_verify(
   1126     uint32 md,    metid_t id,  units_t units, type_t mettype,
   1127     uint32 metsz, uint32 nobj, uint32 nlocs,  resource_t res_id,
   1128     uint32 ressz ) ;
   1129 
   1130 
   1131 static int get_cpustates(int *new)
   1132 {
   1133     new[0] = (int)kmet_get_cpu( MPC_CPU_IDLE, "idle");
   1134     new[1] = (int)kmet_get_cpu( MPC_CPU_USR,  "usr");
   1135     new[2] = (int)kmet_get_cpu( MPC_CPU_SYS,  "sys");
   1136     new[3] = (int)kmet_get_cpu( MPC_CPU_WIO,  "wio");
   1137 }
   1138 
   1139 
   1140 /* initialises kernel metrics access and gets #cpus */
   1141 static int kmet_init()
   1142 {
   1143     uint32 *ncpu_p;
   1144 
   1145     /*  open (and map in) the metric access file and assoc data structures */
   1146     if( ( md = mas_open( MAS_FILE, MAS_MMAP_ACCESS ) ) < 0 )
   1147     {
   1148         (void)fprintf(stderr,"mas_open failed\n");
   1149         mas_perror();
   1150         quit(10);
   1151     }
   1152 
   1153     /* verify the NCPU metric is everything we expect */
   1154     kmet_verify(md, NCPU, CPUS, CONFIGURABLE, sizeof(short),
   1155                    1, 1, MAS_SYSTEM, sizeof(uint32) );
   1156 
   1157     /* get the number of cpu's on the system */
   1158     if( (ncpu_p = (uint32 *)mas_get_met( md, NCPU, 0 )) == NULL )
   1159     {
   1160         (void)fprintf(stderr,"mas_get_met of ncpu failed\n");
   1161         mas_perror();
   1162         quit(12);
   1163     }
   1164     ncpu = (uint32)(*(short *)ncpu_p);
   1165 
   1166     /* check that MPC_CPU_IDLE is of the form we expect
   1167      *      ( paranoically we should check the rest as well but ... )
   1168      */
   1169     kmet_verify( md, MPC_CPU_IDLE, TIX, PROFILE, sizeof(uint32),
   1170                     1,  ncpu, NCPU, sizeof(short) );
   1171 
   1172     kmet_verify( md, PROCUSE, PROCESSES, COUNT, sizeof(uint32),
   1173                     1,  1, MAS_SYSTEM, sizeof(uint32) );
   1174     nproc = kmet_get_nproc();
   1175 
   1176     return 0;
   1177 }
   1178 
   1179 /* done with kernel metrics access */
   1180 static int
   1181 kmet_done()
   1182 {
   1183     if ( mas_close( md ) < 0 )
   1184     {
   1185         (void)fprintf(stderr,"mas_close failed\n");
   1186         mas_perror();
   1187         quit(14);
   1188     }
   1189 }
   1190 
   1191 
   1192 static uint32
   1193 kmet_get_cpu( int type, char *desc)
   1194 {
   1195     int i;
   1196     uint32 r=0, rtot=0 ;
   1197 
   1198     for (i=0; i <ncpu; i++)
   1199     {
   1200         r=*(uint32 *)mas_get_met( md, (metid_t)type, 0 );
   1201         if ( !r)
   1202         {
   1203             (void)fprintf(stderr,"mas_get_met of %s failed\n", desc);
   1204             mas_perror();
   1205             quit(12);
   1206         }
   1207         rtot += r;      /* sum them for multi cpus */
   1208     }
   1209     return rtot /* /ncpu */ ;
   1210 }
   1211 
   1212 static int
   1213 kmet_get_freemem()
   1214 {
   1215     dl_t            *fm_p, fm, fmc, denom;
   1216     time_t          td1;
   1217     static time_t   td0;
   1218     static dl_t     fm_old;
   1219 
   1220 
   1221     td1 = time(NULL);
   1222     if ((fm_p = (dl_t *)mas_get_met( md, FREEMEM, 0 )) == NULL )
   1223     {
   1224         (void)fprintf(stderr,"mas_get_met of freemem failed\n");
   1225         mas_perror();
   1226         quit(12);
   1227     }
   1228     fm = *fm_p;
   1229 
   1230     denom.dl_hop = 0;
   1231     denom.dl_lop = (long) (td1 - td0);
   1232     td0 = td1;
   1233 
   1234     /* calculate the freemem difference divided by the time diff
   1235      * giving the freemem in that time sample
   1236      *  (new - old) / (time_between_samples)
   1237      */
   1238     fmc = lsub(fm, fm_old);
   1239     fm_old = fm;
   1240 
   1241     fmc = ldivide(fmc, denom);
   1242     return  fmc.dl_lop;
   1243 }
   1244 
   1245 /*
   1246  * return # of processes currently executing on system
   1247  */
   1248 static int
   1249 kmet_get_nproc()
   1250 {
   1251     uint32 *p;
   1252     if ((p = (uint32 *)mas_get_met( md, PROCUSE, 0 )) == NULL )
   1253     {
   1254         (void)fprintf(stderr,"mas_get_met of procuse failed\n");
   1255         mas_perror();
   1256         quit(11);
   1257     }
   1258     nproc = (int)*p;
   1259 }
   1260 
   1261 
   1262 /*
   1263  * Function: 	kmet_verify
   1264  * renamed from mas_usrtime example verify_met() fm Doug Souders
   1265  *
   1266  * Description:	Verify the registration data associated with this metric
   1267  *		match what are expected.  Cautious consumer applications
   1268  *		should do this sort of verification before using metrics.
   1269  */
   1270 static void
   1271 kmet_verify(
   1272      uint32     md,         /* metric descriptor                */
   1273      metid_t    id,         /* metric id number                 */
   1274      units_t    units,      /* expected units of metric         */
   1275      type_t     mettype,    /* expected type of metric          */
   1276      uint32     metsz,      /* expected object size of metric   */
   1277      uint32     nobj,       /* expected number of array elements */
   1278      uint32     nlocs,      /* expected number of instances     */
   1279      resource_t res_id,     /* expected resource id number      */
   1280      uint32     ressz       /* expected resource object size    */
   1281      )
   1282 {
   1283 
   1284     char		*name;		/* the name of the metric 	*/
   1285     units_t		*units_p;	/* the units of the metric	*/
   1286     type_t		*mettype_p;	/* type field of the metric	*/
   1287     uint32 		*objsz_p;	/* size of each element in met 	*/
   1288     uint32 		*nobj_p;	/* num of elements >1 then array*/
   1289     uint32 		*nlocs_p;	/* total number of instances	*/
   1290     uint32 		*status_p;	/* status word (update|avail)	*/
   1291     resource_t	        *resource_p;	/* the resource list of the met	*/
   1292     uint32		*resval_p;	/* pointer to resource		*/
   1293     uint32 		*ressz_p;	/* size of the resource met	*/
   1294 
   1295     if (!(name = mas_get_met_name( md, id )))
   1296     {
   1297             (void)fprintf(stderr,"mas_get_met_name failed\n");
   1298             mas_perror();
   1299             quit(11);
   1300     }
   1301 
   1302     if (!(status_p = mas_get_met_status( md, id )))
   1303     {
   1304             (void)fprintf(stderr,"mas_get_met_status of %s failed\n",
   1305                 name );
   1306             mas_perror();
   1307             quit(11);
   1308     }
   1309     if ( *status_p != MAS_AVAILABLE )
   1310     {
   1311         (void)fprintf(stderr,"unexpected status word for %s\n"
   1312                                 "- expected %u got %u\n",
   1313                 name, MAS_AVAILABLE, *status_p );
   1314         quit(11);
   1315     }
   1316     if (!(units_p = mas_get_met_units( md, id )))
   1317     {
   1318             (void)fprintf(stderr,"mas_get_met_units of %s failed\n",
   1319                 name );
   1320             mas_perror();
   1321             quit(11);
   1322     }
   1323     if (units != *units_p )
   1324     {
   1325             (void)fprintf(stderr,"unexpected units for %s\n"
   1326                                     "- expected %u got %u\n",
   1327                 name, units, *units_p );
   1328             quit(11);
   1329     }
   1330 
   1331     if (!(mettype_p = mas_get_met_type( md, id )))
   1332     {
   1333             (void)fprintf(stderr,"mas_get_met_type of %s failed\n",
   1334                 name );
   1335             mas_perror();
   1336             quit(11);
   1337     }
   1338     if (mettype != *mettype_p )
   1339     {
   1340             (void)fprintf(stderr,"unexpected metric type for %s\n"
   1341                                     "- expected %u got %u\n",
   1342                 name, mettype , *mettype_p );
   1343             quit(11);
   1344     }
   1345 
   1346     if (!(objsz_p = mas_get_met_objsz( md, id )))
   1347     {
   1348             (void)fprintf(stderr,"mas_get_met_objsz of %s failed\n", name );
   1349             mas_perror();
   1350             quit(11);
   1351     }
   1352     if (*objsz_p != metsz )
   1353     {
   1354             (void)fprintf(stderr,"unexpected object size for %s\n"
   1355                                     "- expected %u got %u\n",
   1356                 name, metsz, *objsz_p );
   1357             quit(11);
   1358     }
   1359 
   1360     if (!(nobj_p = mas_get_met_nobj( md, id )))
   1361     {
   1362             (void)fprintf(stderr,"mas_get_met_nobj of %s failed\n", name );
   1363             mas_perror();
   1364             quit(11);
   1365     }
   1366     if (nobj != *nobj_p )
   1367     {
   1368         (void)fprintf(stderr,"unexpected number of objects for %s\n"
   1369                                     "- expected %u got %u\n",
   1370                 name, nobj, *nobj_p );
   1371          quit(11);
   1372     }
   1373 
   1374     /* get the number of instances that libmas thinks it knows about  */
   1375     if (!(nlocs_p = mas_get_met_nlocs( md, id )))
   1376     {
   1377         (void)fprintf(stderr,"mas_get_met_nlocs of %s failed\n",  name );
   1378         mas_perror();
   1379         quit(11);
   1380     }
   1381     if (nlocs != *nlocs_p )
   1382     {
   1383         (void)fprintf(stderr,"unexpected number of instances for %s"
   1384                         " - expected %u got %u\n",
   1385                 name, nlocs, *nlocs_p );
   1386         quit(11);
   1387 
   1388     }
   1389     /*	get the resource list for the metric */
   1390     if (!(resource_p = mas_get_met_resources( md, id )))
   1391     {
   1392         (void)fprintf(stderr,"mas_get_met_resources of %s failed\n", name );
   1393         mas_perror();
   1394         quit(11);
   1395     }
   1396     if (*resource_p != res_id )
   1397     {
   1398         (void)fprintf(stderr,"unexpected resource id for %s\n"
   1399                                     "- expected %u got %u\n",
   1400                 name, res_id, *resource_p);
   1401         quit(11);
   1402     }
   1403     /*	get the size of the resource  */
   1404     if (!(ressz_p = mas_get_met_objsz( md, (metid_t)(*resource_p) )))
   1405     {
   1406         (void)fprintf(stderr,"mas_get_met_objsz of resource failed\n");
   1407         mas_perror();
   1408         quit(11);
   1409     }
   1410     if (*ressz_p != ressz )
   1411     {
   1412         (void)fprintf(stderr,"unexpected resource size for %s\n"
   1413                                     "- expected %u got %u\n",
   1414                 name, ressz, *ressz_p );
   1415         quit(11);
   1416     }
   1417 /*
   1418  *	get the address of the resource
   1419  */
   1420     if (!(resval_p = (uint32 *)mas_get_met( md, *resource_p, 0 )))
   1421     {
   1422             (void)fprintf(stderr,"mas_get_met of resource failed\n");
   1423             mas_perror();
   1424             quit(11);
   1425     }
   1426     if (ressz == sizeof( short ) )
   1427     {
   1428         if( (uint32)(*(short *)resval_p) != nlocs )
   1429         {
   1430             (void)fprintf(stderr,"unexpected resource value for %s\n"
   1431                                     "- expected %u got %u\n",
   1432                         name, nlocs, (uint32)(*(short *)resval_p) );
   1433             quit(11);
   1434         }
   1435     }
   1436     else
   1437     { /* assume size of uint32 */
   1438         if (*resval_p != nlocs )
   1439         {
   1440             (void)fprintf(stderr,"unexpected resource value for %s\n"
   1441                                     "- expected %u got %u\n",
   1442                         name, nlocs, *resval_p );
   1443             quit(11);
   1444         }
   1445     }
   1446     return;
   1447 }
   1448 
   1449