"Fossies" - the Fresh Open Source Software Archive

Member "top-3.8beta1/machine/m_svr5.c" (7 May 2008, 36884 Bytes) of package /linux/misc/old/top-3.8beta1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "m_svr5.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.7_vs_3.8beta1.

    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@sco.com>
   48  *          David Cutter       <dpc@grail.com>
   49  *          Andrew Herbert     <andrew@werple.apana.org.au>
   50  *          Robert Boucher     <boucher@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