source: trunk/third/top/machine/m_ultrix4.c @ 16185

Revision 16185, 21.4 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16184, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * top - a top users display for Unix
3 *
4 * SYNOPSIS:  any DEC running ULTRIX V4.2 or later
5 *
6 * DESCRIPTION:
7 * This is the machine-dependent module for ULTRIX V4.x
8 * It should work on any DEC (mips or VAX) running V4.0 or later.
9 *
10 * LIBS:
11 *
12 * CFLAGS: -DORDER
13 *
14 * AUTHOR:  David S. Comay <dsc@seismo.css.gov>
15 * patches: Alex A. Sergejew <aas@swin.oz.au>
16 *          Jeff White <jwhite@isdpvbds1.isd.csc.com>
17 *          Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
18 */
19
20#include <sys/types.h>
21#include <sys/signal.h>
22#include <sys/param.h>
23
24#include <stdio.h>
25#include <nlist.h>
26#include <math.h>
27#include <sys/dir.h>
28#include <sys/user.h>
29#include <sys/proc.h>
30#include <sys/dk.h>
31#include <sys/vm.h>
32#include <sys/file.h>
33#include <sys/time.h>
34#include <machine/pte.h>
35#ifdef _SIZE_T_
36#include <sys/cpudata.h>
37#endif
38
39/* #define DOSWAP */
40
41#include "top.h"
42#include "machine.h"
43
44extern int errno, sys_nerr;
45extern char *sys_errlist[];
46#define strerror(e) (((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error")
47
48#define VMUNIX  "/vmunix"
49#define KMEM    "/dev/kmem"
50#define MEM     "/dev/mem"
51#ifdef DOSWAP
52#define SWAP    "/dev/drum"
53#endif
54
55/* get_process_info passes back a handle.  This is what it looks like: */
56
57struct handle
58{
59    struct proc **next_proc;    /* points to next valid proc pointer */
60    int remaining;              /* number of pointers remaining */
61};
62
63/* declarations for load_avg */
64#include "loadavg.h"
65
66/* define what weighted cpu is.  */
67#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
68                         ((pct) / (1.0 - exp((pp)->p_time * logcpu))))
69
70/* process time is only available in u area, so retrieve it from u.u_ru and
71   store a copy in unused (by top) p_ref field of struct proc
72   struct timeval field tv_sec is a long, p_ref is an int, but both are the
73   same size on VAX and MIPS, so this is safe */
74#define PROCTIME(pp) ((pp)->p_ref)
75
76/* what we consider to be process size: */
77#define PROCSIZE(pp) ((pp)->p_tsize + (pp)->p_dsize + (pp)->p_ssize)
78
79/* definitions for indices in the nlist array */
80#define X_AVENRUN       0
81#define X_CCPU          1
82#define X_NPROC         2
83#define X_PROC          3
84#define X_TOTAL         4
85#define X_CPUDATA       5
86#define X_MPID          6
87#define X_HZ            7
88#define X_LOWCPU        8
89#define X_HIGHCPU       9
90
91static struct nlist nlst[] = {
92    { "_avenrun" },             /* 0 */
93    { "_ccpu" },                /* 1 */
94    { "_nproc" },               /* 2 */
95    { "_proc" },                /* 3 */
96    { "_total" },               /* 4 */
97    { "_cpudata" },             /* 5 */
98    { "_mpid" },                /* 6 */
99    { "_hz" },                  /* 7 */
100    { "_lowcpu" },              /* 8 */
101    { "_highcpu" },             /* 9 */
102    { 0 }
103};
104
105/*
106 *  These definitions control the format of the per-process area
107 */
108
109static char header[] =
110  "  PID X        PRI NICE  SIZE   RES STATE   TIME   WCPU    CPU COMMAND";
111/* 0123456   -- field to fill in starts at header+6 */
112#define UNAME_START 6
113
114#define Proc_format \
115        "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s"
116
117
118/* process state names for the "STATE" column of the display */
119/* the extra nulls in the string "run" are for adding a slash and
120   the processor number when needed */
121
122char *state_abbrev[] =
123{
124    "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
125};
126
127
128static int kmem, mem;
129#ifdef DOSWAP
130static int swap;
131#endif
132
133/* values that we stash away in _init and use in later routines */
134
135static double logcpu;
136
137/* these are retrieved from the kernel in _init */
138
139static unsigned long proc;
140static          int  nproc;
141static          long hz;
142static load_avg  ccpu;
143static          int  lowcpu = 0;
144static          int  highcpu = 0;
145
146/* these are offsets obtained via nlist and used in the get_ functions */
147
148static unsigned long avenrun_offset;
149static unsigned long mpid_offset;
150static unsigned long total_offset;
151static unsigned long cpudata_offset;
152
153/* these are for calculating cpu state percentages */
154
155static long cp_time[CPUSTATES];
156static long cp_old[CPUSTATES];
157static long cp_diff[CPUSTATES];
158static struct cpudata *cpudata[MAXCPU];
159
160/* these are for detailing the process states */
161
162int process_states[7];
163char *procstatenames[] = {
164    "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
165    " zombie, ", " stopped, ",
166    NULL
167};
168
169/* these are for detailing the cpu states */
170
171int cpu_states[4];
172char *cpustatenames[] = {
173    "user", "nice", "system", "idle", NULL
174};
175
176/* these are for detailing the memory statistics */
177
178int memory_stats[8];
179char *memorynames[] = {
180    "Real: ", "K/", "K act/tot  ", "Virtual: ", "K/",
181    "K act/tot  ", "Free: ", "K", NULL
182};
183
184/* these are names given to allowed sorting orders -- first is default */
185char *ordernames[] = {
186      "cpu", "size", "res", "time", NULL
187};
188
189/* forward definitions for comparison functions */
190int compare_cpu();
191int compare_size();
192int compare_res();
193int compare_time();
194
195int (*proc_compares[])() = {
196      compare_cpu,
197      compare_size,
198      compare_res,
199      compare_time,
200      NULL
201};
202
203/* these are for keeping track of the proc array */
204
205static int bytes;
206static int pref_len;
207static struct proc *pbase;
208static struct proc **pref;
209
210/* these are for getting the memory statistics */
211
212static int pageshift;           /* log base 2 of the pagesize */
213
214/* define pagetok in terms of pageshift */
215
216#define pagetok(size) ((size) << pageshift)
217
218/* useful externals */
219extern int errno;
220extern char *sys_errlist[];
221
222long lseek();
223long percentages();
224
225machine_init(statics)
226
227struct statics *statics;
228
229{
230    int i = 0;
231    int pagesize;
232
233    if ((kmem = open(KMEM, O_RDONLY)) == -1) {
234        perror(KMEM);
235        return(-1);
236    }
237    if ((mem = open(MEM, O_RDONLY)) == -1) {
238        perror(MEM);
239        return(-1);
240    }
241
242#ifdef DOSWAP
243    if ((swap = open(SWAP, O_RDONLY)) == -1) {
244        perror(SWAP);
245        return(-1);
246    }
247#endif
248
249    /* get the list of symbols we want to access in the kernel */
250    (void) nlist(VMUNIX, nlst);
251    if (nlst[0].n_type == 0)
252    {
253        fprintf(stderr, "top: nlist failed\n");
254        return(-1);
255    }
256
257    /* make sure they were all found */
258    if (i > 0 && check_nlist(nlst) > 0)
259    {
260        return(-1);
261    }
262
263    /* get the symbol values out of kmem */
264    (void) getkval(nlst[X_PROC].n_value,   (int *)(&proc),      sizeof(proc),
265            nlst[X_PROC].n_name);
266    (void) getkval(nlst[X_NPROC].n_value,  &nproc,              sizeof(nproc),
267            nlst[X_NPROC].n_name);
268    (void) getkval(nlst[X_HZ].n_value,     (int *)(&hz),        sizeof(hz),
269            nlst[X_HZ].n_name);
270    (void) getkval(nlst[X_CCPU].n_value,   (int *)(&ccpu),      sizeof(ccpu),
271            nlst[X_CCPU].n_name);
272    (void) getkval(nlst[X_LOWCPU].n_value,   (int *)(&lowcpu),  sizeof(lowcpu),
273            nlst[X_LOWCPU].n_name);
274    (void) getkval(nlst[X_HIGHCPU].n_value,   (int *)(&highcpu),        sizeof(highcpu),
275            nlst[X_HIGHCPU].n_name);
276
277    /* stash away certain offsets for later use */
278    mpid_offset = nlst[X_MPID].n_value;
279    avenrun_offset = nlst[X_AVENRUN].n_value;
280    total_offset = nlst[X_TOTAL].n_value;
281    cpudata_offset = nlst[X_CPUDATA].n_value;
282
283    /* this is used in calculating WCPU -- calculate it ahead of time */
284    logcpu = log(loaddouble(ccpu));
285
286    /* allocate space for proc structure array and array of pointers */
287    bytes = nproc * sizeof(struct proc);
288    pbase = (struct proc *)malloc(bytes);
289    pref  = (struct proc **)malloc(nproc * sizeof(struct proc *));
290
291    /* Just in case ... */
292    if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
293    {
294        fprintf(stderr, "top: can't allocate sufficient memory\n");
295        return(-1);
296    }
297
298    /* get the page size with "getpagesize" and calculate pageshift from it */
299    pagesize = getpagesize();
300    pageshift = 0;
301    while (pagesize > 1)
302    {
303        pageshift++;
304        pagesize >>= 1;
305    }
306
307    /* we only need the amount of log(2)1024 for our conversion */
308    pageshift -= LOG1024;
309
310    /* fill in the statics information */
311    statics->procstate_names = procstatenames;
312    statics->cpustate_names = cpustatenames;
313    statics->memory_names = memorynames;
314    statics->order_names = ordernames;
315
316    /* all done! */
317    return(0);
318}
319
320char *format_header(uname_field)
321
322char *uname_field;
323
324{
325    char *ptr;
326
327    ptr = header + UNAME_START;
328    while (*uname_field != '\0')
329    {
330        *ptr++ = *uname_field++;
331    }
332
333    return(header);
334}
335
336get_system_info(si)
337
338struct system_info *si;
339
340{
341    load_avg avenrun[3];
342    long total;
343    int i;
344    int ncpu;
345    struct cpudata cpu;
346
347    for (i = 0; i < CPUSTATES; ++i)
348    {
349        cp_time[i] = 0;
350    }
351    (void) getkval(cpudata_offset, cpudata, sizeof(cpudata), "_cpudata");
352    for (ncpu = lowcpu; ncpu <= highcpu; ++ncpu)
353    {
354        if (cpudata[ncpu] != NULL) {
355                (void) getkval(cpudata[ncpu], &cpu, sizeof(cpu), "???");
356                if (cpu.cpu_state & CPU_RUN)
357                {
358                    for (i = 0; i < CPUSTATES; ++i)
359                    {
360                        cp_time[i] += cpu.cpu_cptime[i];
361                    }
362                }
363        }
364    }
365
366    /* get load average array */
367    (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
368                   "_avenrun");
369
370    /* get mpid -- process id of last process */
371    (void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
372                   "_mpid");
373
374    /* convert load averages to doubles */
375    {
376        int i;
377        double *infoloadp;
378        load_avg *sysloadp;
379
380        infoloadp = si->load_avg;
381        sysloadp = avenrun;
382        for (i = 0; i < 3; i++)
383        {
384            *infoloadp++ = loaddouble(*sysloadp++);
385        }
386    }
387
388    /* convert cp_time counts to percentages */
389    total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
390
391    /* sum memory statistics */
392    {
393        struct vmtotal total;
394
395        /* get total -- systemwide main memory usage structure */
396        (void) getkval(total_offset, (int *)(&total), sizeof(total),
397                       "_total");
398        /* convert memory stats to Kbytes */
399        memory_stats[0] = -1;
400        memory_stats[1] = pagetok(total.t_arm);
401        memory_stats[2] = pagetok(total.t_rm);
402        memory_stats[3] = -1;
403        memory_stats[4] = pagetok(total.t_avm);
404        memory_stats[5] = pagetok(total.t_vm);
405        memory_stats[6] = -1;
406        memory_stats[7] = pagetok(total.t_free);
407    }
408
409    /* set arrays and strings */
410    si->cpustates = cpu_states;
411    si->memory = memory_stats;
412}
413
414static struct handle handle;
415
416caddr_t get_process_info(si, sel, compare)
417
418struct system_info *si;
419struct process_select *sel;
420int (*compare)();
421
422{
423    int i;
424    int total_procs;
425    int active_procs;
426    struct proc **prefp;
427    struct proc *pp;
428    struct user u;
429
430    /* these are copied out of sel for speed */
431    int show_idle;
432    int show_system;
433    int show_uid;
434    int show_command;
435
436    /* read all the proc structures in one fell swoop */
437    (void) getkval(proc, (int *)pbase, bytes, "proc array");
438
439    /* get a pointer to the states summary array */
440    si->procstates = process_states;
441
442    /* set up flags which define what we are going to select */
443    show_idle = sel->idle;
444    show_system = sel->system;
445    show_uid = sel->uid != -1;
446    show_command = sel->command != NULL;
447
448    /* count up process states and get pointers to interesting procs */
449    total_procs = 0;
450    active_procs = 0;
451    memset((char *)process_states, 0, sizeof(process_states));
452    prefp = pref;
453    for (pp = pbase, i = 0; i < nproc; pp++, i++)
454    {
455        /*
456         *  Place pointers to each valid proc structure in pref[].
457         *  Process slots that are actually in use have a non-zero
458         *  status field.  Processes with SSYS set are system
459         *  processes---these get ignored unless show_sysprocs is set.
460         */
461        if (pp->p_stat != 0 && pp->p_stat != SIDL &&
462            (show_system || ((pp->p_type & SSYS) == 0)))
463        {
464#ifdef vax
465#define PCTCPU_NONZERO (pp->p_pctcpu != 0.0)
466#else
467#define PCTCPU_NONZERO (pp->p_pctcpu != 0)
468#endif
469            total_procs++;
470            process_states[pp->p_stat]++;
471            if ((pp->p_stat != SZOMB) &&
472                (pp->p_stat != SIDL) &&
473                (show_idle || PCTCPU_NONZERO || (pp->p_stat == SRUN)) &&
474                (!show_uid || pp->p_uid == (uid_t)sel->uid))
475            {
476                *prefp++ = pp;
477                active_procs++;
478
479                if (getu(pp, &u) == -1)
480                {
481                    PROCTIME(pp) = 0;
482                }
483                else
484                {
485                    PROCTIME(pp) = u.u_ru.ru_utime.tv_sec +
486                        u.u_ru.ru_stime.tv_sec;
487                }
488            }
489        }
490    }
491
492    /* if requested, sort the "interesting" processes */
493    if (compare != NULL)
494    {
495        qsort((char *)pref, active_procs, sizeof(struct proc *), compare);
496    }
497
498    /* remember active and total counts */
499    si->p_total = total_procs;
500    si->p_active = pref_len = active_procs;
501
502    /* pass back a handle */
503    handle.next_proc = pref;
504    handle.remaining = active_procs;
505    return((caddr_t)&handle);
506}
507
508char fmt[MAX_COLS];             /* static area where result is built */
509
510char *format_next_process(handle, get_userid)
511
512caddr_t handle;
513char *(*get_userid)();
514
515{
516    struct proc *pp;
517    double pct;
518    int where;
519    struct user u;
520    struct handle *hp;
521
522    /* find and remember the next proc structure */
523    hp = (struct handle *)handle;
524    pp = *(hp->next_proc++);
525    hp->remaining--;
526   
527    /* get the process's user struct */
528    where = getu(pp, &u);
529    if (where == -1)
530    {
531        (void) strcpy(u.u_comm, "<swapped>");
532    }
533    else
534    {
535        /* set u_comm for system processes */
536        if (u.u_comm[0] == '\0')
537        {
538            if (pp->p_pid == 0)
539            {
540                (void) strcpy(u.u_comm, "Swapper");
541            }
542            else if (pp->p_pid == 2)
543            {
544                (void) strcpy(u.u_comm, "Pager");
545            }
546        }
547        if (where == 1) {
548            /*
549             * Print swapped processes as <pname>
550             */
551            char buf[sizeof(u.u_comm)];
552            (void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
553            u.u_comm[0] = '<';
554            (void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
555            u.u_comm[sizeof(u.u_comm) - 2] = '\0';
556            (void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
557            u.u_comm[sizeof(u.u_comm) - 1] = '\0';
558        }
559    }
560
561    /* calculate the base for cpu percentages */
562    pct = pctdouble(pp->p_pctcpu);
563
564    /* format this entry */
565    sprintf(fmt,
566            Proc_format,
567            pp->p_pid,
568            (*get_userid)(pp->p_uid),
569            pp->p_pri - PZERO,
570            pp->p_nice - NZERO,
571            format_k(pagetok(PROCSIZE(pp))),
572            format_k(pagetok(pp->p_rssize)),
573            state_abbrev[pp->p_stat],
574            format_time(PROCTIME(pp)),
575            100.0 * weighted_cpu(pct, pp),
576            100.0 * pct,
577            printable(u.u_comm));
578
579    /* return the result */
580    return(fmt);
581}
582
583/*
584 *  getu(p, u) - get the user structure for the process whose proc structure
585 *      is pointed to by p.  The user structure is put in the buffer pointed
586 *      to by u.  Return 0 if successful, -1 on failure (such as the process
587 *      being swapped out).
588 */
589
590#ifdef ibm032
591static struct alignuser {
592    char userfill[UPAGES*NBPG-sizeof (struct user)];
593    struct user user;
594} au;
595# define USERSIZE sizeof(struct alignuser)
596# define GETUSER(b)     (&au)
597# define SETUSER(b)     *(b) = au.user
598#else
599# define USERSIZE sizeof(struct user)
600# define GETUSER(b)     (b)
601# define SETUSER(b)     /* Nothing */
602#endif
603
604getu(p, u)
605
606struct proc *p;
607struct user *u;
608
609{
610    struct pte uptes[UPAGES];
611    caddr_t upage;
612    struct pte *pte;
613    int nbytes, n;
614
615    /*
616     *  Check if the process is currently loaded or swapped out.  The way we
617     *  get the u area is totally different for the two cases.  For this
618     *  application, we just don't bother if the process is swapped out.
619     */
620    if ((p->p_sched & SLOAD) == 0) {
621#ifdef DOSWAP
622        if (lseek(swap, (long)dtob(p->p_swaddr), 0) == -1) {
623            perror("lseek(swap)");
624            return(-1);
625        }
626        if (read(swap, (char *) GETUSER(u), USERSIZE) != USERSIZE)  {
627            perror("read(swap)");
628            return(-1);
629        }
630        SETUSER(u);
631        return (1);
632#else
633        return(-1);
634#endif
635    }
636
637    /*
638     *  Process is currently in memory, we hope!
639     */
640    if (!getkval((unsigned long)p->p_addr, (int *)uptes, sizeof(uptes),
641                "!p->p_addr"))
642    {
643#ifdef DEBUG
644        perror("getkval(uptes)");
645#endif
646        /* we can't seem to get to it, so pretend it's swapped out */
647        return(-1);
648    }
649    upage = (caddr_t) GETUSER(u);
650    pte = uptes;
651    for (nbytes = USERSIZE; nbytes > 0; nbytes -= NBPG) {
652        (void) lseek(mem, (long)(pte++->pg_pfnum * NBPG), 0);
653#ifdef DEBUG
654        perror("lseek(mem)");
655#endif
656        n = MIN(nbytes, NBPG);
657        if (read(mem, upage, n) != n) {
658#ifdef DEBUG
659        perror("read(mem)");
660#endif
661            /* we can't seem to get to it, so pretend it's swapped out */
662            return(-1);
663        }
664        upage += n;
665    }
666    SETUSER(u);
667    return(0);
668}
669
670/*
671 * check_nlist(nlst) - checks the nlist to see if any symbols were not
672 *              found.  For every symbol that was not found, a one-line
673 *              message is printed to stderr.  The routine returns the
674 *              number of symbols NOT found.
675 */
676
677int check_nlist(nlst)
678
679struct nlist *nlst;
680
681{
682    int i;
683
684    /* check to see if we got ALL the symbols we requested */
685    /* this will write one line to stderr for every symbol not found */
686
687    i = 0;
688    while (nlst->n_name != NULL)
689    {
690        if (nlst->n_type == 0)
691        {
692            /* this one wasn't found */
693            fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
694            i = 1;
695        }
696        nlst++;
697    }
698
699    return(i);
700}
701
702
703/*
704 *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
705 *      "offset" is the byte offset into the kernel for the desired value,
706 *      "ptr" points to a buffer into which the value is retrieved,
707 *      "size" is the size of the buffer (and the object to retrieve),
708 *      "refstr" is a reference string used when printing error meessages,
709 *          if "refstr" starts with a '!', then a failure on read will not
710 *          be fatal (this may seem like a silly way to do things, but I
711 *          really didn't want the overhead of another argument).
712 *     
713 */
714
715getkval(offset, ptr, size, refstr)
716
717unsigned long offset;
718int *ptr;
719int size;
720char *refstr;
721
722{
723    if (lseek(kmem, (long)offset, L_SET) == -1) {
724        if (*refstr == '!')
725            refstr++;
726        (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
727                       refstr, strerror(errno));
728        quit(23);
729    }
730    if (read(kmem, (char *) ptr, size) == -1) {
731        if (*refstr == '!')
732            return(0);
733        else {
734            (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
735                           refstr, strerror(errno));
736            quit(23);
737        }
738    }
739    return(1);
740}
741   
742/* comparison routines for qsort */
743
744/*
745 * There are currently four possible comparison routines.  main selects
746 * one of these by indexing in to the array proc_compares.
747 *
748 * Possible keys are defined as macros below.  Currently these keys are
749 * defined:  percent cpu, cpu ticks, process state, resident set size,
750 * total virtual memory usage.  The process states are ordered as follows
751 * (from least to most important):  WAIT, zombie, sleep, stop, start, run.
752 * The array declaration below maps a process state index into a number
753 * that reflects this ordering.
754 */
755
756/* First, the possible comparison keys.  These are defined in such a way
757   that they can be merely listed in the source code to define the actual
758   desired ordering.
759 */
760
761#define ORDERKEY_PCTCPU  if (lresult = p2->p_pctcpu - p1->p_pctcpu,\
762                           (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
763#define ORDERKEY_CPTICKS if ((result = PROCTIME(p2) - PROCTIME(p1)) == 0)
764#define ORDERKEY_STATE   if ((result = sorted_state[p2->p_stat] - \
765                            sorted_state[p1->p_stat])  == 0)
766#define ORDERKEY_PRIO    if ((result = p2->p_pri - p1->p_pri) == 0)
767#define ORDERKEY_RSSIZE  if ((result = p2->p_rssize - p1->p_rssize) == 0)
768#define ORDERKEY_MEM     if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0)
769
770/* Now the array that maps process state to a weight */
771
772static unsigned char sorted_state[] =
773{
774    0,  /* not used             */
775    3,  /* sleep                */
776    1,  /* ABANDONED (WAIT)     */
777    6,  /* run                  */
778    5,  /* start                */
779    2,  /* zombie               */
780    4   /* stop                 */
781};
782 
783/* compare_cpu - the comparison function for sorting by cpu percentage */
784
785compare_cpu(pp1, pp2)
786
787struct proc **pp1;
788struct proc **pp2;
789
790{
791    register struct proc *p1;
792    register struct proc *p2;
793    register int result;
794    register pctcpu lresult;
795
796    /* remove one level of indirection */
797    p1 = *pp1;
798    p2 = *pp2;
799
800    ORDERKEY_PCTCPU
801    ORDERKEY_CPTICKS
802    ORDERKEY_STATE
803    ORDERKEY_PRIO
804    ORDERKEY_RSSIZE
805    ORDERKEY_MEM
806    ;
807
808    return(result);
809}
810
811/* compare_size - the comparison function for sorting by total memory usage */
812
813compare_size(pp1, pp2)
814
815struct proc **pp1;
816struct proc **pp2;
817
818{
819    register struct proc *p1;
820    register struct proc *p2;
821    register int result;
822    register pctcpu lresult;
823
824    /* remove one level of indirection */
825    p1 = *pp1;
826    p2 = *pp2;
827
828    ORDERKEY_MEM
829    ORDERKEY_RSSIZE
830    ORDERKEY_PCTCPU
831    ORDERKEY_CPTICKS
832    ORDERKEY_STATE
833    ORDERKEY_PRIO
834    ;
835
836    return(result);
837}
838
839/* compare_res - the comparison function for sorting by resident set size */
840
841compare_res(pp1, pp2)
842
843struct proc **pp1;
844struct proc **pp2;
845
846{
847    register struct proc *p1;
848    register struct proc *p2;
849    register int result;
850    register pctcpu lresult;
851
852    /* remove one level of indirection */
853    p1 = *pp1;
854    p2 = *pp2;
855
856    ORDERKEY_RSSIZE
857    ORDERKEY_MEM
858    ORDERKEY_PCTCPU
859    ORDERKEY_CPTICKS
860    ORDERKEY_STATE
861    ORDERKEY_PRIO
862    ;
863
864    return(result);
865}
866
867/* compare_time - the comparison function for sorting by total cpu time */
868
869compare_time(pp1, pp2)
870
871struct proc **pp1;
872struct proc **pp2;
873
874{
875    register struct proc *p1;
876    register struct proc *p2;
877    register int result;
878    register pctcpu lresult;
879
880    /* remove one level of indirection */
881    p1 = *pp1;
882    p2 = *pp2;
883
884    ORDERKEY_CPTICKS
885    ORDERKEY_PCTCPU
886    ORDERKEY_STATE
887    ORDERKEY_PRIO
888    ORDERKEY_RSSIZE
889    ORDERKEY_MEM
890    ;
891 
892    return(result);
893}
894
895/*
896 * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
897 *              the process does not exist.
898 *              It is EXTREMLY IMPORTANT that this function work correctly.
899 *              If top runs setuid root (as in SVR4), then this function
900 *              is the only thing that stands in the way of a serious
901 *              security problem.  It validates requests for the "kill"
902 *              and "renice" commands.
903 */
904
905int proc_owner(pid)
906
907int pid;
908
909{
910    int cnt;
911    struct proc **prefp;
912    struct proc *pp;
913
914    prefp = pref;
915    cnt = pref_len;
916    while (--cnt >= 0)
917    {
918        if ((pp = *prefp++)->p_pid == (pid_t)pid)
919        {
920            return((int)pp->p_uid);
921        }
922    }
923    return(-1);
924}
Note: See TracBrowser for help on using the repository browser.