Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / top / dist / machine / m_hpux9.c
blobb0ae7912914b4d19750018c669869cfd3c84099e
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.
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.
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.
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.
34 * top - a top users display for Unix
36 * SYNOPSIS: any hp9000 running hpux version 9
38 * DESCRIPTION:
39 * This is the machine-dependent module for HPUX 9.
40 * This makes top work on (at least) the following systems:
41 * hp9000s800
42 * hp9000s700
43 * This may make top work on the following, but we aren't sure:
44 * hp9000s300
46 * LIBS:
48 * CFLAGS: -DHAVE_GETOPT
50 * AUTHOR: Kevin Schmidt <kevin@mcl.ucsb.edu>
51 * adapted from Christos Zoulas <christos@ee.cornell.edu>
54 #include "config.h"
55 #include <sys/types.h>
56 #include <sys/signal.h>
57 #include <sys/param.h>
59 #include <stdio.h>
60 #include <nlist.h>
61 #include <math.h>
62 #include <sys/dir.h>
63 #include <sys/user.h>
64 #include <sys/proc.h>
65 #include <sys/dk.h>
66 #include <sys/vm.h>
67 #include <sys/file.h>
68 #include <sys/time.h>
69 #ifndef hpux
70 # define P_RSSIZE(p) (p)->p_rssize
71 # define P_TSIZE(p) (p)->p_tsize
72 # define P_DSIZE(p) (p)->p_dsize
73 # define P_SSIZE(p) (p)->p_ssize
74 #else
75 # include <sys/pstat.h>
76 # define __PST2P(p, field) \
77 ((p)->p_upreg ? ((struct pst_status *) (p)->p_upreg)->field : 0)
78 # define P_RSSIZE(p) __PST2P(p, pst_rssize)
79 # define P_TSIZE(p) __PST2P(p, pst_tsize)
80 # define P_DSIZE(p) __PST2P(p, pst_dsize)
81 # define P_SSIZE(p) __PST2P(p, pst_ssize)
82 # ifdef __hp9000s700
83 # define p_percentcpu(p) ((p)->p_pctcpu)
84 # define p_time_exact(p) ((p)->p_time)
85 # else
86 /* The following 4 #defines are per HPUX-9.0's <sys/proc.h> */
87 # define PCT_NORM 9 /* log2(PCT_BASE) */
88 # define PCT_BASE (1<<PCT_NORM)
89 # define p_percentcpu(p) ((p)->p_fractioncpu/(float)(PCT_BASE*HZ))
90 # define p_time_exact(p) (time.tv_sec-((p)->p_swaptime))
91 # endif /* __hp9000s700 */
92 #endif /* hpux */
94 #include "top.h"
95 #include "machine.h"
96 #include "utils.h"
98 #define VMUNIX "/hp-ux"
99 #define KMEM "/dev/kmem"
100 #define MEM "/dev/mem"
101 #ifdef DOSWAP
102 #define SWAP "/dev/dmem"
103 #endif
105 /* get_process_info passes back a handle. This is what it looks like: */
107 struct handle
109 struct proc **next_proc; /* points to next valid proc pointer */
110 int remaining; /* number of pointers remaining */
113 /* declarations for load_avg */
114 #include "loadavg.h"
116 /* define what weighted cpu is. */
117 #define weighted_cpu(pct, pp) ((p_time_exact(pp)) == 0 ? 0.0 : \
118 ((pct) / (1.0 - exp((p_time_exact(pp)) * logcpu))))
120 /* what we consider to be process size: */
121 #define PROCSIZE(pp) (P_TSIZE(pp) + P_DSIZE(pp) + P_SSIZE(pp))
123 /* definitions for indices in the nlist array */
124 #define X_AVENRUN 0
125 #define X_CCPU 1
126 #define X_NPROC 2
127 #define X_PROC 3
128 #define X_TOTAL 4
129 #define X_CP_TIME 5
130 #define X_MPID 6
133 * Steinar Haug from University of Trondheim, NORWAY pointed out that
134 * the HP 9000 system 800 doesn't have _hz defined in the kernel. He
135 * provided a patch to work around this. We've improved on this patch
136 * here and set the constant X_HZ only when _hz is available in the
137 * kernel. Code in this module that uses X_HZ is surrounded with
138 * appropriate ifdefs.
141 #ifndef hp9000s300
142 #define X_HZ 7
143 #endif
146 static struct nlist nlst[] = {
147 { "_avenrun" }, /* 0 */
148 { "_cexp" }, /* 1 */
149 { "_nproc" }, /* 2 */
150 { "_proc" }, /* 3 */
151 { "_total" }, /* 4 */
152 { "_cp_time" }, /* 5 */
153 { "_mpid" }, /* 6 */
154 #ifdef X_HZ
155 { "_hz" }, /* 7 */
156 #endif
157 { 0 }
161 * These definitions control the format of the per-process area
164 static char header[] =
165 " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
166 /* 0123456 -- field to fill in starts at header+6 */
167 #define UNAME_START 6
169 #define Proc_format \
170 "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %s"
172 /* process state names for the "STATE" column of the display */
173 /* the extra nulls in the string "run" are for adding a slash and
174 the processor number when needed */
176 char *state_abbrev[] =
178 "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
182 static int kmem;
184 /* values that we stash away in _init and use in later routines */
186 static double logcpu;
188 /* these are retrieved from the kernel in _init */
190 static unsigned long proc;
191 static int nproc;
192 static long hz;
193 static load_avg ccpu;
194 static int ncpu = 0;
196 /* these are offsets obtained via nlist and used in the get_ functions */
197 static unsigned long mpid_offset;
198 static unsigned long avenrun_offset;
199 static unsigned long total_offset;
200 static unsigned long cp_time_offset;
202 /* these are for calculating cpu state percentages */
204 static long cp_time[CPUSTATES];
205 static long cp_old[CPUSTATES];
206 static long cp_diff[CPUSTATES];
208 /* these are for detailing the process states */
210 int process_states[7];
211 char *procstatenames[] = {
212 "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
213 " zombie, ", " stopped, ",
214 NULL
217 /* these are for detailing the cpu states */
219 int cpu_states[9];
220 char *cpustatenames[] = {
221 "usr", "nice", "sys", "idle", "", "", "", "intr", "ker",
222 NULL
225 /* these are for detailing the memory statistics */
227 long memory_stats[8];
228 char *memorynames[] = {
229 "Real: ", "K act, ", "K tot ", "Virtual: ", "K act, ",
230 "K tot, ", "K free", NULL
233 /* these are for keeping track of the proc array */
235 static int bytes;
236 static int pref_len;
237 static struct proc *pbase;
238 static struct proc **pref;
239 static struct pst_status *pst;
241 /* these are for getting the memory statistics */
243 static int pageshift; /* log base 2 of the pagesize */
245 /* define pagetok in terms of pageshift */
247 #define pagetok(size) ((size) << pageshift)
249 /* useful externals */
250 extern int errno;
251 extern char *sys_errlist[];
253 long lseek();
254 long time();
256 machine_init(statics)
258 struct statics *statics;
261 register int i = 0;
262 register int pagesize;
264 if ((kmem = open(KMEM, O_RDONLY)) == -1) {
265 perror(KMEM);
266 return(-1);
268 #ifdef hp9000s800
269 /* 800 names don't have leading underscores */
270 for (i = 0; nlst[i].n_name; nlst[i++].n_name++)
271 continue;
272 #endif
274 /* get the list of symbols we want to access in the kernel */
275 (void) nlist(VMUNIX, nlst);
276 if (nlst[0].n_type == 0)
278 fprintf(stderr, "top: nlist failed\n");
279 return(-1);
282 /* make sure they were all found */
283 if (check_nlist(nlst) > 0)
285 return(-1);
288 /* get the symbol values out of kmem */
289 (void) getkval(nlst[X_PROC].n_value, (int *)(&proc), sizeof(proc),
290 nlst[X_PROC].n_name);
291 (void) getkval(nlst[X_NPROC].n_value, &nproc, sizeof(nproc),
292 nlst[X_NPROC].n_name);
293 (void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
294 nlst[X_CCPU].n_name);
295 #ifdef X_HZ
296 (void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz),
297 nlst[X_HZ].n_name);
298 #else
299 hz = HZ;
300 #endif
302 /* stash away certain offsets for later use */
303 mpid_offset = nlst[X_MPID].n_value;
304 avenrun_offset = nlst[X_AVENRUN].n_value;
305 total_offset = nlst[X_TOTAL].n_value;
306 cp_time_offset = nlst[X_CP_TIME].n_value;
308 /* this is used in calculating WCPU -- calculate it ahead of time */
309 logcpu = log(loaddouble(ccpu));
311 /* allocate space for proc structure array and array of pointers */
312 bytes = nproc * sizeof(struct proc);
313 pbase = (struct proc *)malloc(bytes);
314 pref = (struct proc **)malloc(nproc * sizeof(struct proc *));
315 pst = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));
317 /* Just in case ... */
318 if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
320 fprintf(stderr, "top: can't allocate sufficient memory\n");
321 return(-1);
324 /* get the page size with "getpagesize" and calculate pageshift from it */
325 pagesize = getpagesize();
326 pageshift = 0;
327 while (pagesize > 1)
329 pageshift++;
330 pagesize >>= 1;
333 /* we only need the amount of log(2)1024 for our conversion */
334 pageshift -= LOG1024;
336 /* fill in the statics information */
337 statics->procstate_names = procstatenames;
338 statics->cpustate_names = cpustatenames;
339 statics->memory_names = memorynames;
341 /* all done! */
342 return(0);
345 char *format_header(uname_field)
347 register char *uname_field;
350 register char *ptr;
352 ptr = header + UNAME_START;
353 while (*uname_field != '\0')
355 *ptr++ = *uname_field++;
358 return(header);
361 void
362 get_system_info(si)
364 struct system_info *si;
367 load_avg avenrun[3];
368 long total;
370 /* get the cp_time array */
371 (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
372 "_cp_time");
374 /* get load average array */
375 (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
376 "_avenrun");
378 /* get mpid -- process id of last process */
379 (void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
380 "_mpid");
382 /* convert load averages to doubles */
384 register int i;
385 register double *infoloadp;
386 register load_avg *sysloadp;
388 infoloadp = si->load_avg;
389 sysloadp = avenrun;
390 for (i = 0; i < 3; i++)
392 *infoloadp++ = loaddouble(*sysloadp++);
396 /* convert cp_time counts to percentages */
397 total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
399 /* sum memory statistics */
401 struct vmtotal total;
403 /* get total -- systemwide main memory usage structure */
404 (void) getkval(total_offset, (int *)(&total), sizeof(total),
405 "_total");
406 /* convert memory stats to Kbytes */
407 memory_stats[0] = -1;
408 memory_stats[1] = pagetok(total.t_arm);
409 memory_stats[2] = pagetok(total.t_rm);
410 memory_stats[3] = -1;
411 memory_stats[4] = pagetok(total.t_avm);
412 memory_stats[5] = pagetok(total.t_vm);
413 memory_stats[6] = pagetok(total.t_free);
416 /* set arrays and strings */
417 si->cpustates = cpu_states;
418 si->memory = memory_stats;
421 static struct handle handle;
423 caddr_t get_process_info(si, sel, i)
425 struct system_info *si;
426 struct process_select *sel;
427 int i;
430 register int i;
431 register int total_procs;
432 register int active_procs;
433 register struct proc **prefp;
434 register struct proc *pp;
436 /* these are copied out of sel for speed */
437 int show_idle;
438 int show_system;
439 int show_uid;
440 int show_command;
442 /* read all the proc structures in one fell swoop */
443 (void) getkval(proc, (int *)pbase, bytes, "proc array");
444 for (i = 0; i < nproc; ++i) {
445 if (pstat(PSTAT_PROC, &pst[i], sizeof(pst[i]), 0, pbase[i].p_pid) != 1)
446 pbase[i].p_upreg = (preg_t *) 0;
447 else
448 pbase[i].p_upreg = (preg_t *) &pst[i];
449 pbase[i].p_nice = pst[i].pst_nice;
450 pbase[i].p_cpticks = pst[i].pst_cpticks;
454 /* get a pointer to the states summary array */
455 si->procstates = process_states;
457 /* set up flags which define what we are going to select */
458 show_idle = sel->idle;
459 show_system = sel->system;
460 show_uid = sel->uid != -1;
461 show_command = sel->command != NULL;
463 /* count up process states and get pointers to interesting procs */
464 total_procs = 0;
465 active_procs = 0;
466 memset((char *)process_states, 0, sizeof(process_states));
467 prefp = pref;
468 for (pp = pbase, i = 0; i < nproc; pp++, i++)
471 * Place pointers to each valid proc structure in pref[].
472 * Process slots that are actually in use have a non-zero
473 * status field. Processes with SSYS set are system
474 * processes---these get ignored unless show_sysprocs is set.
476 if (pp->p_stat != 0 &&
477 (show_system || ((pp->p_flag & SSYS) == 0)))
479 total_procs++;
480 process_states[pp->p_stat]++;
482 * idle processes can be selectively ignored: a process is
483 * considered idle when cpticks is zero AND it is not in the run
484 * state. Zombies are always ignored. We also skip over
485 * processes that have been excluded via a uid selection
487 if ((pp->p_stat != SZOMB) &&
488 (show_idle || (pp->p_cpticks != 0) || (pp->p_stat == SRUN)) &&
489 (!show_uid || pp->p_uid == (uid_t)sel->uid))
491 *prefp++ = pp;
492 active_procs++;
497 /* if requested, sort the "interesting" processes */
498 if (compare != NULL)
500 qsort((char *)pref, active_procs, sizeof(struct proc *), proc_compare);
503 /* remember active and total counts */
504 si->p_total = total_procs;
505 si->p_active = pref_len = active_procs;
507 /* pass back a handle */
508 handle.next_proc = pref;
509 handle.remaining = active_procs;
510 return((caddr_t)&handle);
513 char fmt[MAX_COLS]; /* static area where result is built */
515 char *format_next_process(handle, get_userid)
517 caddr_t handle;
518 char *(*get_userid)();
521 register struct proc *pp;
522 register long cputime;
523 register double pct;
524 int where;
525 struct user u;
526 struct handle *hp;
527 struct timeval time;
528 struct timezone timezone;
530 /* find and remember the next proc structure */
531 hp = (struct handle *)handle;
532 pp = *(hp->next_proc++);
533 hp->remaining--;
536 /* get the process's user struct and set cputime */
537 where = getu(pp, &u);
538 if (where == -1)
540 (void) strcpy(u.u_comm, "<swapped>");
541 cputime = 0;
543 else
547 /* set u_comm for system processes */
548 if (u.u_comm[0] == '\0')
550 if (pp->p_pid == 0)
552 (void) strcpy(u.u_comm, "Swapper");
554 else if (pp->p_pid == 2)
556 (void) strcpy(u.u_comm, "Pager");
559 if (where == 1) {
561 * Print swapped processes as <pname>
563 char buf[sizeof(u.u_comm)];
564 (void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
565 u.u_comm[0] = '<';
566 (void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
567 u.u_comm[sizeof(u.u_comm) - 2] = '\0';
568 (void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
569 u.u_comm[sizeof(u.u_comm) - 1] = '\0';
572 cputime = __PST2P(pp, pst_cptickstotal) / hz;
575 /* calculate the base for cpu percentages */
576 pct = pctdouble(p_percentcpu(pp));
578 /* get time used for calculation in weighted_cpu */
579 gettimeofday(&time, &timezone);
581 /* format this entry */
582 sprintf(fmt,
583 Proc_format,
584 pp->p_pid,
585 (*get_userid)(pp->p_uid),
586 pp->p_pri - PZERO,
587 pp->p_nice - NZERO,
588 format_k(pagetok(PROCSIZE(pp))),
589 format_k(pagetok(P_RSSIZE(pp))),
590 state_abbrev[pp->p_stat],
591 format_time(cputime),
592 100.0 * weighted_cpu(pct, pp),
593 100.0 * pct,
594 printable(u.u_comm));
596 /* return the result */
597 return(fmt);
601 * getu(p, u) - get the user structure for the process whose proc structure
602 * is pointed to by p. The user structure is put in the buffer pointed
603 * to by u. Return 0 if successful, -1 on failure (such as the process
604 * being swapped out).
608 getu(p, u)
610 register struct proc *p;
611 struct user *u;
614 struct pst_status *ps;
615 char *s, *c;
616 int i;
618 if ((ps = (struct pst_status *) p->p_upreg) == NULL)
619 return -1;
621 memset(u, 0, sizeof(struct user));
622 c = ps->pst_cmd;
623 ps->pst_cmd[PST_CLEN - 1] = '\0'; /* paranoia */
624 s = strtok(ps->pst_cmd, "\t \n");
626 if (c = strrchr(s, '/'))
627 c++;
628 else
629 c = s;
630 if (*c == '-')
631 c++;
632 i = 0;
633 for (; i < MAXCOMLEN; i++) {
634 if (*c == '\0' || *c == ' ' || *c == '/')
635 break;
636 u->u_comm[i] = *c++;
638 #ifndef DOSWAP
639 return ((p->p_flag & SLOAD) == 0 ? 1 : 0);
640 #endif
641 return(0);
645 * check_nlist(nlst) - checks the nlist to see if any symbols were not
646 * found. For every symbol that was not found, a one-line
647 * message is printed to stderr. The routine returns the
648 * number of symbols NOT found.
651 int check_nlist(nlst)
653 register struct nlist *nlst;
656 register int i;
658 /* check to see if we got ALL the symbols we requested */
659 /* this will write one line to stderr for every symbol not found */
661 i = 0;
662 while (nlst->n_name != NULL)
664 if (nlst->n_type == 0)
666 /* this one wasn't found */
667 fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
668 i = 1;
670 nlst++;
673 return(i);
678 * getkval(offset, ptr, size, refstr) - get a value out of the kernel.
679 * "offset" is the byte offset into the kernel for the desired value,
680 * "ptr" points to a buffer into which the value is retrieved,
681 * "size" is the size of the buffer (and the object to retrieve),
682 * "refstr" is a reference string used when printing error meessages,
683 * if "refstr" starts with a '!', then a failure on read will not
684 * be fatal (this may seem like a silly way to do things, but I
685 * really didn't want the overhead of another argument).
689 getkval(offset, ptr, size, refstr)
691 unsigned long offset;
692 int *ptr;
693 int size;
694 char *refstr;
697 if (lseek(kmem, (long)offset, L_SET) == -1) {
698 if (*refstr == '!')
699 refstr++;
700 (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
701 refstr, strerror(errno));
702 quit(23);
704 if (read(kmem, (char *) ptr, size) == -1) {
705 if (*refstr == '!')
706 return(0);
707 else {
708 (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
709 refstr, strerror(errno));
710 quit(23);
713 return(1);
716 /* comparison routine for qsort */
719 * proc_compare - comparison function for "qsort"
720 * Compares the resource consumption of two processes using five
721 * distinct keys. The keys (in descending order of importance) are:
722 * percent cpu, cpu ticks, state, resident set size, total virtual
723 * memory usage. The process states are ordered as follows (from least
724 * to most important): WAIT, zombie, sleep, stop, start, run. The
725 * array declaration below maps a process state index into a number
726 * that reflects this ordering.
729 static unsigned char sorted_state[] =
731 0, /* not used */
732 3, /* sleep */
733 1, /* ABANDONED (WAIT) */
734 6, /* run */
735 5, /* start */
736 2, /* zombie */
737 4 /* stop */
740 proc_compare(pp1, pp2)
742 struct proc **pp1;
743 struct proc **pp2;
746 register struct proc *p1;
747 register struct proc *p2;
748 register int result;
749 register pctcpu lresult;
751 /* remove one level of indirection */
752 p1 = *pp1;
753 p2 = *pp2;
755 /* compare percent cpu (pctcpu) */
756 if ((lresult = p_percentcpu(p2) - p_percentcpu(p1)) == 0)
758 /* use cpticks to break the tie */
759 if ((result = p2->p_cpticks - p1->p_cpticks) == 0)
761 /* use process state to break the tie */
762 if ((result = sorted_state[p2->p_stat] -
763 sorted_state[p1->p_stat]) == 0)
765 /* use priority to break the tie */
766 if ((result = p2->p_pri - p1->p_pri) == 0)
768 /* use resident set size (rssize) to break the tie */
769 if ((result = P_RSSIZE(p2) - P_RSSIZE(p1)) == 0)
771 /* use total memory to break the tie */
772 result = PROCSIZE(p2) - PROCSIZE(p1);
778 else
780 result = lresult < 0 ? -1 : 1;
783 return(result);
787 void (*signal(sig, func))()
788 int sig;
789 void (*func)();
791 struct sigvec osv, sv;
794 * XXX: we should block the signal we are playing with,
795 * in case we get interrupted in here.
797 if (sigvector(sig, NULL, &osv) == -1)
798 return BADSIG;
799 sv = osv;
800 sv.sv_handler = func;
801 #ifdef SV_BSDSIG
802 sv.sv_flags |= SV_BSDSIG;
803 #endif
804 if (sigvector(sig, &sv, NULL) == -1)
805 return BADSIG;
806 return osv.sv_handler;
809 int getpagesize() { return 1 << PGSHIFT; }
811 int setpriority(a, b, c) { errno = ENOSYS; return -1; }
814 * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
815 * the process does not exist.
816 * It is EXTREMLY IMPORTANT that this function work correctly.
817 * If top runs setuid root (as in SVR4), then this function
818 * is the only thing that stands in the way of a serious
819 * security problem. It validates requests for the "kill"
820 * and "renice" commands.
823 int proc_owner(pid)
825 int pid;
828 register int cnt;
829 register struct proc **prefp;
830 register struct proc *pp;
832 prefp = pref;
833 cnt = pref_len;
834 while (--cnt >= 0)
836 if ((pp = *prefp++)->p_pid == (pid_t)pid)
838 return((int)pp->p_uid);
841 return(-1);