home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / top-3.2 / part04 < prev    next >
Text File  |  1993-08-08  |  51KB  |  1,961 lines

  1. Newsgroups: comp.sources.unix
  2. From: phil@eecs.nwu.edu (William LeFebvre)
  3. Subject: v27i004: top - a top process display, version 3.2, Part04/13
  4. References: <1.744843136.4744@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: phil@eecs.nwu.edu (William LeFebvre)
  9. Posting-Number: Volume 27, Issue 4
  10. Archive-Name: top-3.2/part04
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 4 (of 13)."
  19. # Contents:  machine/m_bsd44.c machine/m_bsd44a.c machine/m_svr42.c
  20. # Wrapped by phil@pex on Wed Aug  4 14:22:42 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'machine/m_bsd44.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'machine/m_bsd44.c'\"
  24. else
  25. echo shar: Extracting \"'machine/m_bsd44.c'\" \(15537 characters\)
  26. sed "s/^X//" >'machine/m_bsd44.c' <<'END_OF_FILE'
  27. X/*
  28. X * top - a top users display for Unix
  29. X *
  30. X * SYNOPSIS:  For a 4.4BSD system
  31. X *          Note process resident sizes could be wrong, but ps shows
  32. X *          zero for them too..
  33. X *
  34. X * DESCRIPTION:
  35. X * This is the machine-dependent module for BSD4.4 
  36. X * Works for:
  37. X *    hp300
  38. X *
  39. X * LIBS: -lkvm
  40. X *
  41. X * AUTHOR:  Christos Zoulas <christos@ee.cornell.edu>
  42. X */
  43. X
  44. X#include <sys/types.h>
  45. X#include <sys/signal.h>
  46. X#include <sys/param.h>
  47. X
  48. X#include "os.h"
  49. X#include <stdio.h>
  50. X#include <nlist.h>
  51. X#include <math.h>
  52. X#include <kvm.h>
  53. X#include <sys/errno.h>
  54. X#include <sys/sysctl.h>
  55. X#include <sys/dir.h>
  56. X#include <sys/dkstat.h>
  57. X#include <sys/file.h>
  58. X#include <sys/time.h>
  59. X
  60. X
  61. X#define DOSWAP
  62. X
  63. Xstatic int check_nlist __P((struct nlist *));
  64. Xstatic int getkval __P((unsigned long, int *, int, char *));
  65. Xextern char* printable __P((char *));
  66. X
  67. X#include "top.h"
  68. X#include "machine.h"
  69. X
  70. X#define VMUNIX    "/vmunix"
  71. X#define KMEM    "/dev/kmem"
  72. X#define MEM    "/dev/mem"
  73. X#ifdef DOSWAP
  74. X#define SWAP    "/dev/drum"
  75. X#endif
  76. X
  77. X/* get_process_info passes back a handle.  This is what it looks like: */
  78. X
  79. Xstruct handle
  80. X{
  81. X    struct kinfo_proc **next_proc;    /* points to next valid proc pointer */
  82. X    int remaining;        /* number of pointers remaining */
  83. X};
  84. X
  85. X/* declarations for load_avg */
  86. X#include "loadavg.h"
  87. X
  88. X#define PP(pp, field) ((pp)->kp_proc . field)
  89. X#define EP(pp, field) ((pp)->kp_eproc . field)
  90. X#define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
  91. X
  92. X/* define what weighted cpu is.  */
  93. X#define weighted_cpu(pct, pp) (PP((pp), p_time) == 0 ? 0.0 : \
  94. X             ((pct) / (1.0 - exp(PP((pp), p_time) * logcpu))))
  95. X
  96. X/* what we consider to be process size: */
  97. X#define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
  98. X
  99. X/* definitions for indices in the nlist array */
  100. X#define X_CCPU        0
  101. X#define X_CP_TIME    1
  102. X#define X_HZ        2
  103. X#define X_AVENRUN    3
  104. X
  105. Xstatic struct nlist nlst[] = {
  106. X    { "_ccpu" },        /* 0 */
  107. X    { "_cp_time" },        /* 1 */
  108. X    { "_hz" },            /* 2 */
  109. X    { "_averunnable" },        /* 3 */
  110. X    { 0 }
  111. X};
  112. X
  113. X/*
  114. X *  These definitions control the format of the per-process area
  115. X */
  116. X
  117. Xstatic char header[] =
  118. X  "  PID X        PRI NICE   SIZE   RES STATE   TIME   WCPU    CPU COMMAND";
  119. X/* 0123456   -- field to fill in starts at header+6 */
  120. X#define UNAME_START 6
  121. X
  122. X#define Proc_format \
  123. X    "%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %.14s"
  124. X
  125. X
  126. X/* process state names for the "STATE" column of the display */
  127. X/* the extra nulls in the string "run" are for adding a slash and
  128. X   the processor number when needed */
  129. X
  130. Xchar *state_abbrev[] =
  131. X{
  132. X    "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
  133. X};
  134. X
  135. X
  136. Xstatic kvm_t *kd;
  137. X
  138. X/* values that we stash away in _init and use in later routines */
  139. X
  140. Xstatic double logcpu;
  141. X
  142. X/* these are retrieved from the kernel in _init */
  143. X
  144. Xstatic          long hz;
  145. Xstatic load_avg  ccpu;
  146. X
  147. X/* these are offsets obtained via nlist and used in the get_ functions */
  148. X
  149. Xstatic unsigned long cp_time_offset;
  150. Xstatic unsigned long avenrun_offset;
  151. X
  152. X/* these are for calculating cpu state percentages */
  153. X
  154. Xstatic long cp_time[CPUSTATES];
  155. Xstatic long cp_old[CPUSTATES];
  156. Xstatic long cp_diff[CPUSTATES];
  157. X
  158. X/* these are for detailing the process states */
  159. X
  160. Xint process_states[7];
  161. Xchar *procstatenames[] = {
  162. X    "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
  163. X    " zombie, ", " stopped, ",
  164. X    NULL
  165. X};
  166. X
  167. X/* these are for detailing the cpu states */
  168. X
  169. Xint cpu_states[4];
  170. Xchar *cpustatenames[] = {
  171. X    "user", "nice", "system", "idle", NULL
  172. X};
  173. X
  174. X/* these are for detailing the memory statistics */
  175. X
  176. Xint memory_stats[8];
  177. Xchar *memorynames[] = {
  178. X    "Real: ", "K/", "K ", "Virt: ", "K/",
  179. X    "K ", "Free: ", "K", NULL
  180. X};
  181. X
  182. X/* these are for keeping track of the proc array */
  183. X
  184. Xstatic int nproc;
  185. Xstatic int onproc = -1;
  186. Xstatic int pref_len;
  187. Xstatic struct kinfo_proc *pbase;
  188. Xstatic struct kinfo_proc **pref;
  189. X
  190. X/* these are for getting the memory statistics */
  191. X
  192. Xstatic int pageshift;        /* log base 2 of the pagesize */
  193. X
  194. X/* define pagetok in terms of pageshift */
  195. X
  196. X#define pagetok(size) ((size) << pageshift)
  197. X
  198. X/* useful externals */
  199. Xlong percentages();
  200. X
  201. Xint
  202. Xmachine_init(statics)
  203. X
  204. Xstruct statics *statics;
  205. X
  206. X{
  207. X    register int i = 0;
  208. X    register int pagesize;
  209. X
  210. X    if ((kd = kvm_open(VMUNIX, MEM, SWAP, O_RDONLY, "kvm_open")) == NULL)
  211. X    return -1;
  212. X
  213. X
  214. X    /* get the list of symbols we want to access in the kernel */
  215. X    (void) kvm_nlist(kd, nlst);
  216. X    if (nlst[0].n_type == 0)
  217. X    {
  218. X    fprintf(stderr, "top: nlist failed\n");
  219. X    return(-1);
  220. X    }
  221. X
  222. X    /* make sure they were all found */
  223. X    if (i > 0 && check_nlist(nlst) > 0)
  224. X    {
  225. X    return(-1);
  226. X    }
  227. X
  228. X    /* get the symbol values out of kmem */
  229. X    (void) getkval(nlst[X_HZ].n_value,     (int *)(&hz),    sizeof(hz),
  230. X        nlst[X_HZ].n_name);
  231. X    (void) getkval(nlst[X_CCPU].n_value,   (int *)(&ccpu),    sizeof(ccpu),
  232. X        nlst[X_CCPU].n_name);
  233. X
  234. X    /* stash away certain offsets for later use */
  235. X    cp_time_offset = nlst[X_CP_TIME].n_value;
  236. X    avenrun_offset = nlst[X_AVENRUN].n_value;
  237. X
  238. X    /* this is used in calculating WCPU -- calculate it ahead of time */
  239. X    logcpu = log(loaddouble(ccpu));
  240. X
  241. X    pbase = NULL;
  242. X    pref = NULL;
  243. X    nproc = 0;
  244. X    onproc = -1;
  245. X    /* get the page size with "getpagesize" and calculate pageshift from it */
  246. X    pagesize = getpagesize();
  247. X    pageshift = 0;
  248. X    while (pagesize > 1)
  249. X    {
  250. X    pageshift++;
  251. X    pagesize >>= 1;
  252. X    }
  253. X
  254. X    /* we only need the amount of log(2)1024 for our conversion */
  255. X    pageshift -= LOG1024;
  256. X
  257. X    /* fill in the statics information */
  258. X    statics->procstate_names = procstatenames;
  259. X    statics->cpustate_names = cpustatenames;
  260. X    statics->memory_names = memorynames;
  261. X
  262. X    /* all done! */
  263. X    return(0);
  264. X}
  265. X
  266. Xchar *format_header(uname_field)
  267. X
  268. Xregister char *uname_field;
  269. X
  270. X{
  271. X    register char *ptr;
  272. X
  273. X    ptr = header + UNAME_START;
  274. X    while (*uname_field != '\0')
  275. X    {
  276. X    *ptr++ = *uname_field++;
  277. X    }
  278. X
  279. X    return(header);
  280. X}
  281. X
  282. Xvoid
  283. Xget_system_info(si)
  284. X
  285. Xstruct system_info *si;
  286. X
  287. X{
  288. X    long total;
  289. X    load_avg avenrun[3];
  290. X
  291. X    /* get the cp_time array */
  292. X    (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
  293. X           "_cp_time");
  294. X    (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
  295. X           "_avenrun");
  296. X
  297. X    /* convert load averages to doubles */
  298. X    {
  299. X    register int i;
  300. X    register double *infoloadp;
  301. X    load_avg *avenrunp;
  302. X
  303. X#ifdef notyet
  304. X    struct loadavg sysload;
  305. X    int size;
  306. X    getkerninfo(KINFO_LOADAVG, &sysload, &size, 0);
  307. X#endif
  308. X
  309. X    infoloadp = si->load_avg;
  310. X    avenrunp = avenrun;
  311. X    for (i = 0; i < 3; i++)
  312. X    {
  313. X#ifdef notyet
  314. X        *infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
  315. X#endif
  316. X        *infoloadp++ = loaddouble(*avenrunp++);
  317. X    }
  318. X    }
  319. X
  320. X    /* convert cp_time counts to percentages */
  321. X    total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
  322. X
  323. X    /* sum memory statistics */
  324. X    {
  325. X    struct vmtotal total;
  326. X    int size = sizeof(total);
  327. X    static int mib[] = { CTL_VM, VM_METER };
  328. X
  329. X    /* get total -- systemwide main memory usage structure */
  330. X    if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
  331. X        (void) fprintf(stderr, "top: sysctl failed: %s\n", strerror(errno));
  332. X        bzero(&total, sizeof(total));
  333. X    }
  334. X    /* convert memory stats to Kbytes */
  335. X    memory_stats[0] = -1;
  336. X    memory_stats[1] = pagetok(total.t_arm);
  337. X    memory_stats[2] = pagetok(total.t_rm);
  338. X    memory_stats[3] = -1;
  339. X    memory_stats[4] = pagetok(total.t_avm);
  340. X    memory_stats[5] = pagetok(total.t_vm);
  341. X    memory_stats[6] = -1;
  342. X    memory_stats[7] = pagetok(total.t_free);
  343. X    }
  344. X
  345. X    /* set arrays and strings */
  346. X    si->cpustates = cpu_states;
  347. X    si->memory = memory_stats;
  348. X    si->last_pid = -1;
  349. X}
  350. X
  351. Xstatic struct handle handle;
  352. X
  353. Xcaddr_t get_process_info(si, sel, compare)
  354. X
  355. Xstruct system_info *si;
  356. Xstruct process_select *sel;
  357. Xint (*compare)();
  358. X
  359. X{
  360. X    register int i;
  361. X    register int total_procs;
  362. X    register int active_procs;
  363. X    register struct kinfo_proc **prefp;
  364. X    register struct kinfo_proc *pp;
  365. X
  366. X    /* these are copied out of sel for speed */
  367. X    int show_idle;
  368. X    int show_system;
  369. X    int show_uid;
  370. X    int show_command;
  371. X
  372. X    
  373. X    pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
  374. X    if (nproc > onproc)
  375. X    pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
  376. X        * (onproc = nproc));
  377. X    if (pref == NULL || pbase == NULL) {
  378. X    (void) fprintf(stderr, "top: Out of memory.\n");
  379. X    quit(23);
  380. X    }
  381. X    /* get a pointer to the states summary array */
  382. X    si->procstates = process_states;
  383. X
  384. X    /* set up flags which define what we are going to select */
  385. X    show_idle = sel->idle;
  386. X    show_system = sel->system;
  387. X    show_uid = sel->uid != -1;
  388. X    show_command = sel->command != NULL;
  389. X
  390. X    /* count up process states and get pointers to interesting procs */
  391. X    total_procs = 0;
  392. X    active_procs = 0;
  393. X    memset((char *)process_states, 0, sizeof(process_states));
  394. X    prefp = pref;
  395. X    for (pp = pbase, i = 0; i < nproc; pp++, i++)
  396. X    {
  397. X    /*
  398. X     *  Place pointers to each valid proc structure in pref[].
  399. X     *  Process slots that are actually in use have a non-zero
  400. X     *  status field.  Processes with SSYS set are system
  401. X     *  processes---these get ignored unless show_sysprocs is set.
  402. X     */
  403. X    if (PP(pp, p_stat) != 0 &&
  404. X        (show_system || ((PP(pp, p_flag) & SSYS) == 0)))
  405. X    {
  406. X        total_procs++;
  407. X        process_states[(unsigned char) PP(pp, p_stat)]++;
  408. X        if ((PP(pp, p_stat) != SZOMB) &&
  409. X        (show_idle || (PP(pp, p_pctcpu) != 0) || 
  410. X         (PP(pp, p_stat) == SRUN)) &&
  411. X        (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t)sel->uid))
  412. X        {
  413. X        *prefp++ = pp;
  414. X        active_procs++;
  415. X        }
  416. X    }
  417. X    }
  418. X
  419. X    /* if requested, sort the "interesting" processes */
  420. X    if (compare != NULL)
  421. X    {
  422. X    qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare);
  423. X    }
  424. X
  425. X    /* remember active and total counts */
  426. X    si->p_total = total_procs;
  427. X    si->p_active = pref_len = active_procs;
  428. X
  429. X    /* pass back a handle */
  430. X    handle.next_proc = pref;
  431. X    handle.remaining = active_procs;
  432. X    return((caddr_t)&handle);
  433. X}
  434. X
  435. Xchar fmt[128];        /* static area where result is built */
  436. X
  437. Xchar *format_next_process(handle, get_userid)
  438. X
  439. Xcaddr_t handle;
  440. Xchar *(*get_userid)();
  441. X
  442. X{
  443. X    register struct kinfo_proc *pp;
  444. X    register long cputime;
  445. X    register double pct;
  446. X    struct handle *hp;
  447. X
  448. X    /* find and remember the next proc structure */
  449. X    hp = (struct handle *)handle;
  450. X    pp = *(hp->next_proc++);
  451. X    hp->remaining--;
  452. X    
  453. X
  454. X    /* get the process's user struct and set cputime */
  455. X    if ((PP(pp, p_flag) & SLOAD) == 0) {
  456. X    /*
  457. X     * Print swapped processes as <pname>
  458. X     */
  459. X    char *comm = PP(pp, p_comm);
  460. X#define COMSIZ sizeof(PP(pp, p_comm))
  461. X    char buf[COMSIZ];
  462. X    (void) strncpy(buf, comm, COMSIZ);
  463. X    comm[0] = '<';
  464. X    (void) strncpy(&comm[1], buf, COMSIZ - 2);
  465. X    comm[COMSIZ - 2] = '\0';
  466. X    (void) strncat(comm, ">", COMSIZ - 1);
  467. X    comm[COMSIZ - 1] = '\0';
  468. X    }
  469. X
  470. X#if 0
  471. X    /* This does not produce the correct results */
  472. X    cputime = PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks);
  473. X#endif
  474. X    cputime = PP(pp, p_rtime).tv_sec;    /* This does not count interrupts */
  475. X
  476. X    /* calculate the base for cpu percentages */
  477. X    pct = pctdouble(PP(pp, p_pctcpu));
  478. X
  479. X    /* format this entry */
  480. X    sprintf(fmt,
  481. X        Proc_format,
  482. X        PP(pp, p_pid),
  483. X        (*get_userid)(EP(pp, e_pcred.p_ruid)),
  484. X        PP(pp, p_pri) - PZERO,
  485. X        PP(pp, p_nice) - NZERO,
  486. X        pagetok(PROCSIZE(pp)),
  487. X        pagetok(VP(pp, vm_rssize)),
  488. X        state_abbrev[(unsigned char) PP(pp, p_stat)],
  489. X        cputime / 60l,
  490. X        cputime % 60l,
  491. X        100.0 * weighted_cpu(pct, pp),
  492. X        100.0 * pct,
  493. X        printable(PP(pp, p_comm)));
  494. X
  495. X    /* return the result */
  496. X    return(fmt);
  497. X}
  498. X
  499. X
  500. X/*
  501. X * check_nlist(nlst) - checks the nlist to see if any symbols were not
  502. X *        found.  For every symbol that was not found, a one-line
  503. X *        message is printed to stderr.  The routine returns the
  504. X *        number of symbols NOT found.
  505. X */
  506. X
  507. Xstatic int check_nlist(nlst)
  508. X
  509. Xregister struct nlist *nlst;
  510. X
  511. X{
  512. X    register int i;
  513. X
  514. X    /* check to see if we got ALL the symbols we requested */
  515. X    /* this will write one line to stderr for every symbol not found */
  516. X
  517. X    i = 0;
  518. X    while (nlst->n_name != NULL)
  519. X    {
  520. X    if (nlst->n_type == 0)
  521. X    {
  522. X        /* this one wasn't found */
  523. X        (void) fprintf(stderr, "kernel: no symbol named `%s'\n",
  524. X               nlst->n_name);
  525. X        i = 1;
  526. X    }
  527. X    nlst++;
  528. X    }
  529. X
  530. X    return(i);
  531. X}
  532. X
  533. X
  534. X/*
  535. X *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
  536. X *    "offset" is the byte offset into the kernel for the desired value,
  537. X *      "ptr" points to a buffer into which the value is retrieved,
  538. X *      "size" is the size of the buffer (and the object to retrieve),
  539. X *      "refstr" is a reference string used when printing error meessages,
  540. X *        if "refstr" starts with a '!', then a failure on read will not
  541. X *          be fatal (this may seem like a silly way to do things, but I
  542. X *          really didn't want the overhead of another argument).
  543. X *      
  544. X */
  545. X
  546. Xstatic int getkval(offset, ptr, size, refstr)
  547. X
  548. Xunsigned long offset;
  549. Xint *ptr;
  550. Xint size;
  551. Xchar *refstr;
  552. X
  553. X{
  554. X    if (kvm_read(kd, offset, (char *) ptr, size) != size)
  555. X    {
  556. X    if (*refstr == '!')
  557. X    {
  558. X        return(0);
  559. X    }
  560. X    else
  561. X    {
  562. X        fprintf(stderr, "top: kvm_read for %s: %s\n",
  563. X        refstr, strerror(errno));
  564. X        quit(23);
  565. X    }
  566. X    }
  567. X    return(1);
  568. X}
  569. X    
  570. X/* comparison routine for qsort */
  571. X
  572. X/*
  573. X *  proc_compare - comparison function for "qsort"
  574. X *    Compares the resource consumption of two processes using five
  575. X *      distinct keys.  The keys (in descending order of importance) are:
  576. X *      percent cpu, cpu ticks, state, resident set size, total virtual
  577. X *      memory usage.  The process states are ordered as follows (from least
  578. X *      to most important):  WAIT, zombie, sleep, stop, start, run.  The
  579. X *      array declaration below maps a process state index into a number
  580. X *      that reflects this ordering.
  581. X */
  582. X
  583. Xstatic unsigned char sorted_state[] =
  584. X{
  585. X    0,    /* not used        */
  586. X    3,    /* sleep        */
  587. X    1,    /* ABANDONED (WAIT)    */
  588. X    6,    /* run            */
  589. X    5,    /* start        */
  590. X    2,    /* zombie        */
  591. X    4    /* stop            */
  592. X};
  593. Xint
  594. Xproc_compare(pp1, pp2)
  595. X
  596. Xstruct proc **pp1;
  597. Xstruct proc **pp2;
  598. X
  599. X{
  600. X    register struct kinfo_proc *p1;
  601. X    register struct kinfo_proc *p2;
  602. X    register int result;
  603. X    register pctcpu lresult;
  604. X
  605. X    /* remove one level of indirection */
  606. X    p1 = *(struct kinfo_proc **) pp1;
  607. X    p2 = *(struct kinfo_proc **) pp2;
  608. X
  609. X    /* compare percent cpu (pctcpu) */
  610. X    if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0)
  611. X    {
  612. X    /* use cpticks to break the tie */
  613. X    if ((result = PP(p2, p_cpticks) - PP(p1, p_cpticks)) == 0)
  614. X    {
  615. X        /* use process state to break the tie */
  616. X        if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] -
  617. X              sorted_state[(unsigned char) PP(p1, p_stat)])  == 0)
  618. X        {
  619. X        /* use priority to break the tie */
  620. X        if ((result = PP(p2, p_pri) - PP(p1, p_pri)) == 0)
  621. X        {
  622. X            /* use resident set size (rssize) to break the tie */
  623. X            if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
  624. X            {
  625. X            /* use total memory to break the tie */
  626. X            result = PROCSIZE(p2) - PROCSIZE(p1);
  627. X            }
  628. X        }
  629. X        }
  630. X    }
  631. X    }
  632. X    else
  633. X    {
  634. X    result = lresult < 0 ? -1 : 1;
  635. X    }
  636. X
  637. X    return(result);
  638. X}
  639. X
  640. X
  641. X/*
  642. X * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
  643. X *        the process does not exist.
  644. X *        It is EXTREMLY IMPORTANT that this function work correctly.
  645. X *        If top runs setuid root (as in SVR4), then this function
  646. X *        is the only thing that stands in the way of a serious
  647. X *        security problem.  It validates requests for the "kill"
  648. X *        and "renice" commands.
  649. X */
  650. X
  651. Xint proc_owner(pid)
  652. X
  653. Xint pid;
  654. X
  655. X{
  656. X    register int cnt;
  657. X    register struct kinfo_proc **prefp;
  658. X    register struct kinfo_proc *pp;
  659. X
  660. X    prefp = pref;
  661. X    cnt = pref_len;
  662. X    while (--cnt >= 0)
  663. X    {
  664. X    pp = *prefp++;    
  665. X    if (PP(pp, p_pid) == (pid_t)pid)
  666. X    {
  667. X        return((int)EP(pp, e_pcred.p_ruid));
  668. X    }
  669. X    }
  670. X    return(-1);
  671. X}
  672. END_OF_FILE
  673. if test 15537 -ne `wc -c <'machine/m_bsd44.c'`; then
  674.     echo shar: \"'machine/m_bsd44.c'\" unpacked with wrong size!
  675. fi
  676. # end of 'machine/m_bsd44.c'
  677. fi
  678. if test -f 'machine/m_bsd44a.c' -a "${1}" != "-c" ; then 
  679.   echo shar: Will not clobber existing file \"'machine/m_bsd44a.c'\"
  680. else
  681. echo shar: Extracting \"'machine/m_bsd44a.c'\" \(15274 characters\)
  682. sed "s/^X//" >'machine/m_bsd44a.c' <<'END_OF_FILE'
  683. X/*
  684. X * top - a top users display for Unix
  685. X *
  686. X * SYNOPSIS:  For a pre-release 4.4BSD system
  687. X *          Note memory statistisc and process sizes could be wrong,
  688. X *          by ps gets them wrong too...
  689. X *
  690. X * DESCRIPTION:
  691. X * This is the machine-dependent module for BSD4.4 (prerelease alpha)
  692. X * Works for:
  693. X *    hp300
  694. X *
  695. X * LIBS: -lkvm
  696. X *
  697. X * AUTHOR:  Christos Zoulas <christos@ee.cornell.edu>
  698. X */
  699. X
  700. X#include <sys/types.h>
  701. X#include <sys/signal.h>
  702. X#include <sys/param.h>
  703. X
  704. X#include "os.h"
  705. X#include <stdio.h>
  706. X#include <nlist.h>
  707. X#include <math.h>
  708. X#include <kvm.h>
  709. X#include <sys/errno.h>
  710. X#include <sys/kinfo.h>
  711. X#include <sys/kinfo_proc.h>
  712. X#ifdef notyet
  713. X#define time __time
  714. X#define hz __hz
  715. X#include <sys/kernel.h>
  716. X#undef time
  717. X#undef hz
  718. X#endif
  719. X#include <sys/dir.h>
  720. X#include <sys/dkstat.h>
  721. X#include <sys/file.h>
  722. X#include <sys/time.h>
  723. X
  724. X
  725. X#define DOSWAP
  726. X
  727. Xstatic int check_nlist __P((struct nlist *));
  728. Xstatic int getkval __P((unsigned long, int *, int, char *));
  729. X
  730. X#include "top.h"
  731. X#include "machine.h"
  732. X
  733. X#define VMUNIX    "/vmunix"
  734. X#define KMEM    "/dev/kmem"
  735. X#define MEM    "/dev/mem"
  736. X#ifdef DOSWAP
  737. X#define SWAP    "/dev/drum"
  738. X#endif
  739. X
  740. X/* get_process_info passes back a handle.  This is what it looks like: */
  741. X
  742. Xstruct handle
  743. X{
  744. X    struct kinfo_proc **next_proc;    /* points to next valid proc pointer */
  745. X    int remaining;        /* number of pointers remaining */
  746. X};
  747. X
  748. X/* declarations for load_avg */
  749. X#include "loadavg.h"
  750. X
  751. X#define PP(pp, field) ((pp)->kp_proc . field)
  752. X#define EP(pp, field) ((pp)->kp_eproc . field)
  753. X#define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
  754. X
  755. X/* define what weighted cpu is.  */
  756. X#define weighted_cpu(pct, pp) (PP((pp), p_time) == 0 ? 0.0 : \
  757. X             ((pct) / (1.0 - exp(PP((pp), p_time) * logcpu))))
  758. X
  759. X/* what we consider to be process size: */
  760. X#define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
  761. X
  762. X/* definitions for indices in the nlist array */
  763. X#define X_CCPU        0
  764. X#define X_CP_TIME    1
  765. X#define X_HZ        2
  766. X#define X_AVENRUN    3
  767. X
  768. Xstatic struct nlist nlst[] = {
  769. X    { "_ccpu" },        /* 0 */
  770. X    { "_cp_time" },        /* 1 */
  771. X    { "_hz" },            /* 2 */
  772. X    { "_averunnable" },        /* 3 */
  773. X    { 0 }
  774. X};
  775. X
  776. X/*
  777. X *  These definitions control the format of the per-process area
  778. X */
  779. X
  780. Xstatic char header[] =
  781. X  "  PID X        PRI NICE   SIZE   RES STATE   TIME   WCPU    CPU COMMAND";
  782. X/* 0123456   -- field to fill in starts at header+6 */
  783. X#define UNAME_START 6
  784. X
  785. X#define Proc_format \
  786. X    "%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %.14s"
  787. X
  788. X
  789. X/* process state names for the "STATE" column of the display */
  790. X/* the extra nulls in the string "run" are for adding a slash and
  791. X   the processor number when needed */
  792. X
  793. Xchar *state_abbrev[] =
  794. X{
  795. X    "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
  796. X};
  797. X
  798. X
  799. Xstatic kvm_t *kd;
  800. X
  801. X/* values that we stash away in _init and use in later routines */
  802. X
  803. Xstatic double logcpu;
  804. X
  805. X/* these are retrieved from the kernel in _init */
  806. X
  807. Xstatic          long hz;
  808. Xstatic load_avg  ccpu;
  809. Xstatic          int  ncpu = 0;
  810. X
  811. X/* these are offsets obtained via nlist and used in the get_ functions */
  812. X
  813. Xstatic unsigned long cp_time_offset;
  814. Xstatic unsigned long avenrun_offset;
  815. X
  816. X/* these are for calculating cpu state percentages */
  817. X
  818. Xstatic long cp_time[CPUSTATES];
  819. Xstatic long cp_old[CPUSTATES];
  820. Xstatic long cp_diff[CPUSTATES];
  821. X
  822. X/* these are for detailing the process states */
  823. X
  824. Xint process_states[7];
  825. Xchar *procstatenames[] = {
  826. X    "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
  827. X    " zombie, ", " stopped, ",
  828. X    NULL
  829. X};
  830. X
  831. X/* these are for detailing the cpu states */
  832. X
  833. Xint cpu_states[4];
  834. Xchar *cpustatenames[] = {
  835. X    "user", "nice", "system", "idle", NULL
  836. X};
  837. X
  838. X/* these are for detailing the memory statistics */
  839. X
  840. Xint memory_stats[8];
  841. Xchar *memorynames[] = {
  842. X    "Real: ", "K/", "K ", "Virt: ", "K/",
  843. X    "K ", "Free: ", "K", NULL
  844. X};
  845. X
  846. X/* these are for keeping track of the proc array */
  847. X
  848. Xstatic int bytes;
  849. Xstatic int nproc;
  850. Xstatic int onproc = -1;
  851. Xstatic int pref_len;
  852. Xstatic struct kinfo_proc *pbase;
  853. Xstatic struct kinfo_proc **pref;
  854. X
  855. X/* these are for getting the memory statistics */
  856. X
  857. Xstatic int pageshift;        /* log base 2 of the pagesize */
  858. X
  859. X/* define pagetok in terms of pageshift */
  860. X
  861. X#define pagetok(size) ((size) << pageshift)
  862. X
  863. X/* useful externals */
  864. Xlong percentages();
  865. X
  866. Xmachine_init(statics)
  867. X
  868. Xstruct statics *statics;
  869. X
  870. X{
  871. X    register int i = 0;
  872. X    register int pagesize;
  873. X
  874. X    if ((kd = kvm_open(VMUNIX, MEM, SWAP, O_RDONLY, "kvm_open")) == NULL)
  875. X    return -1;
  876. X
  877. X
  878. X    /* get the list of symbols we want to access in the kernel */
  879. X    (void) kvm_nlist(kd, nlst);
  880. X    if (nlst[0].n_type == 0)
  881. X    {
  882. X    fprintf(stderr, "top: nlist failed\n");
  883. X    return(-1);
  884. X    }
  885. X
  886. X    /* make sure they were all found */
  887. X    if (i > 0 && check_nlist(nlst) > 0)
  888. X    {
  889. X    return(-1);
  890. X    }
  891. X
  892. X    /* get the symbol values out of kmem */
  893. X    (void) getkval(nlst[X_HZ].n_value,     (int *)(&hz),    sizeof(hz),
  894. X        nlst[X_HZ].n_name);
  895. X    (void) getkval(nlst[X_CCPU].n_value,   (int *)(&ccpu),    sizeof(ccpu),
  896. X        nlst[X_CCPU].n_name);
  897. X
  898. X    /* stash away certain offsets for later use */
  899. X    cp_time_offset = nlst[X_CP_TIME].n_value;
  900. X    avenrun_offset = nlst[X_AVENRUN].n_value;
  901. X
  902. X    /* this is used in calculating WCPU -- calculate it ahead of time */
  903. X    logcpu = log(loaddouble(ccpu));
  904. X
  905. X    pbase = NULL;
  906. X    pref = NULL;
  907. X    nproc = 0;
  908. X    onproc = -1;
  909. X    /* get the page size with "getpagesize" and calculate pageshift from it */
  910. X    pagesize = getpagesize();
  911. X    pageshift = 0;
  912. X    while (pagesize > 1)
  913. X    {
  914. X    pageshift++;
  915. X    pagesize >>= 1;
  916. X    }
  917. X
  918. X    /* we only need the amount of log(2)1024 for our conversion */
  919. X    pageshift -= LOG1024;
  920. X
  921. X    /* fill in the statics information */
  922. X    statics->procstate_names = procstatenames;
  923. X    statics->cpustate_names = cpustatenames;
  924. X    statics->memory_names = memorynames;
  925. X
  926. X    /* all done! */
  927. X    return(0);
  928. X}
  929. X
  930. Xchar *format_header(uname_field)
  931. X
  932. Xregister char *uname_field;
  933. X
  934. X{
  935. X    register char *ptr;
  936. X
  937. X    ptr = header + UNAME_START;
  938. X    while (*uname_field != '\0')
  939. X    {
  940. X    *ptr++ = *uname_field++;
  941. X    }
  942. X
  943. X    return(header);
  944. X}
  945. X
  946. Xget_system_info(si)
  947. X
  948. Xstruct system_info *si;
  949. X
  950. X{
  951. X    long total;
  952. X    load_avg avenrun[3];
  953. X
  954. X    /* get the cp_time array */
  955. X    (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
  956. X           "_cp_time");
  957. X    (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
  958. X           "_avenrun");
  959. X
  960. X    /* convert load averages to doubles */
  961. X    {
  962. X    register int i;
  963. X    register double *infoloadp;
  964. X    load_avg *avenrunp;
  965. X
  966. X#ifdef notyet
  967. X    struct loadavg sysload;
  968. X    int size;
  969. X    getkerninfo(KINFO_LOADAVG, &sysload, &size, 0);
  970. X#endif
  971. X
  972. X    infoloadp = si->load_avg;
  973. X    avenrunp = avenrun;
  974. X    for (i = 0; i < 3; i++)
  975. X    {
  976. X#ifdef notyet
  977. X        *infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
  978. X#endif
  979. X        *infoloadp++ = loaddouble(*avenrunp++);
  980. X    }
  981. X    }
  982. X
  983. X    /* convert cp_time counts to percentages */
  984. X    total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
  985. X
  986. X    /* sum memory statistics */
  987. X    {
  988. X    struct vmtotal total;
  989. X    int size;
  990. X
  991. X    /* get total -- systemwide main memory usage structure */
  992. X    getkerninfo(KINFO_METER, &total, &size, 0);
  993. X    /* convert memory stats to Kbytes */
  994. X    memory_stats[0] = -1;
  995. X    memory_stats[1] = pagetok(total.t_arm);
  996. X    memory_stats[2] = pagetok(total.t_rm);
  997. X    memory_stats[3] = -1;
  998. X    memory_stats[4] = pagetok(total.t_avm);
  999. X    memory_stats[5] = pagetok(total.t_vm);
  1000. X    memory_stats[6] = -1;
  1001. X    memory_stats[7] = pagetok(total.t_free);
  1002. X    }
  1003. X
  1004. X    /* set arrays and strings */
  1005. X    si->cpustates = cpu_states;
  1006. X    si->memory = memory_stats;
  1007. X    si->last_pid = -1;
  1008. X}
  1009. X
  1010. Xstatic struct handle handle;
  1011. X
  1012. Xcaddr_t get_process_info(si, sel, compare)
  1013. X
  1014. Xstruct system_info *si;
  1015. Xstruct process_select *sel;
  1016. Xint (*compare)();
  1017. X
  1018. X{
  1019. X    register int i;
  1020. X    register int total_procs;
  1021. X    register int active_procs;
  1022. X    register struct kinfo_proc **prefp;
  1023. X    register struct kinfo_proc *pp;
  1024. X
  1025. X    /* these are copied out of sel for speed */
  1026. X    int show_idle;
  1027. X    int show_system;
  1028. X    int show_uid;
  1029. X    int show_command;
  1030. X
  1031. X    
  1032. X    pbase = kvm_getprocs(kd, KINFO_PROC_ALL, 0, &nproc);
  1033. X    if (nproc > onproc)
  1034. X    pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
  1035. X        * (onproc = nproc));
  1036. X    if (pref == NULL || pbase == NULL) {
  1037. X    (void) fprintf(stderr, "top: Out of memory.\n");
  1038. X    quit(23);
  1039. X    }
  1040. X    /* get a pointer to the states summary array */
  1041. X    si->procstates = process_states;
  1042. X
  1043. X    /* set up flags which define what we are going to select */
  1044. X    show_idle = sel->idle;
  1045. X    show_system = sel->system;
  1046. X    show_uid = sel->uid != -1;
  1047. X    show_command = sel->command != NULL;
  1048. X
  1049. X    /* count up process states and get pointers to interesting procs */
  1050. X    total_procs = 0;
  1051. X    active_procs = 0;
  1052. X    memset((char *)process_states, 0, sizeof(process_states));
  1053. X    prefp = pref;
  1054. X    for (pp = pbase, i = 0; i < nproc; pp++, i++)
  1055. X    {
  1056. X    /*
  1057. X     *  Place pointers to each valid proc structure in pref[].
  1058. X     *  Process slots that are actually in use have a non-zero
  1059. X     *  status field.  Processes with SSYS set are system
  1060. X     *  processes---these get ignored unless show_sysprocs is set.
  1061. X     */
  1062. X    if (PP(pp, p_stat) != 0 &&
  1063. X        (show_system || ((PP(pp, p_flag) & SSYS) == 0)))
  1064. X    {
  1065. X        total_procs++;
  1066. X        process_states[PP(pp, p_stat)]++;
  1067. X        if ((PP(pp, p_stat) != SZOMB) &&
  1068. X        (show_idle || (PP(pp, p_pctcpu) != 0) || 
  1069. X         (PP(pp, p_stat) == SRUN)) &&
  1070. X        (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t)sel->uid))
  1071. X        {
  1072. X        *prefp++ = pp;
  1073. X        active_procs++;
  1074. X        }
  1075. X    }
  1076. X    }
  1077. X
  1078. X    /* if requested, sort the "interesting" processes */
  1079. X    if (compare != NULL)
  1080. X    {
  1081. X    qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare);
  1082. X    }
  1083. X
  1084. X    /* remember active and total counts */
  1085. X    si->p_total = total_procs;
  1086. X    si->p_active = pref_len = active_procs;
  1087. X
  1088. X    /* pass back a handle */
  1089. X    handle.next_proc = pref;
  1090. X    handle.remaining = active_procs;
  1091. X    return((caddr_t)&handle);
  1092. X}
  1093. X
  1094. Xchar fmt[128];        /* static area where result is built */
  1095. X
  1096. Xchar *format_next_process(handle, get_userid)
  1097. X
  1098. Xcaddr_t handle;
  1099. Xchar *(*get_userid)();
  1100. X
  1101. X{
  1102. X    register struct kinfo_proc *pp;
  1103. X    register long cputime;
  1104. X    register double pct;
  1105. X    int where;
  1106. X    struct handle *hp;
  1107. X
  1108. X    /* find and remember the next proc structure */
  1109. X    hp = (struct handle *)handle;
  1110. X    pp = *(hp->next_proc++);
  1111. X    hp->remaining--;
  1112. X    
  1113. X
  1114. X    /* get the process's user struct and set cputime */
  1115. X    if ((PP(pp, p_flag) & SLOAD) == 0) {
  1116. X    /*
  1117. X     * Print swapped processes as <pname>
  1118. X     */
  1119. X    char *comm = PP(pp, p_comm);
  1120. X#define COMSIZ sizeof(PP(pp, p_comm))
  1121. X    char buf[COMSIZ];
  1122. X    (void) strncpy(buf, comm, COMSIZ);
  1123. X    comm[0] = '<';
  1124. X    (void) strncpy(&comm[1], buf, COMSIZ - 2);
  1125. X    comm[COMSIZ - 2] = '\0';
  1126. X    (void) strncat(comm, ">", COMSIZ - 1);
  1127. X    comm[COMSIZ - 1] = '\0';
  1128. X    }
  1129. X
  1130. X    cputime = PP(pp, p_utime.tv_sec) + PP(pp, p_stime.tv_sec);
  1131. X
  1132. X    /* calculate the base for cpu percentages */
  1133. X    pct = pctdouble(PP(pp, p_pctcpu));
  1134. X
  1135. X    /* format this entry */
  1136. X    sprintf(fmt,
  1137. X        Proc_format,
  1138. X        PP(pp, p_pid),
  1139. X        (*get_userid)(EP(pp, e_pcred.p_ruid)),
  1140. X        PP(pp, p_pri) - PZERO,
  1141. X        PP(pp, p_nice) - NZERO,
  1142. X        pagetok(PROCSIZE(pp)),
  1143. X        pagetok(VP(pp, vm_rssize)),
  1144. X        state_abbrev[PP(pp, p_stat)],
  1145. X        cputime / 60l,
  1146. X        cputime % 60l,
  1147. X        100.0 * weighted_cpu(pct, pp),
  1148. X        100.0 * pct,
  1149. X        printable(PP(pp, p_comm)));
  1150. X
  1151. X    /* return the result */
  1152. X    return(fmt);
  1153. X}
  1154. X
  1155. X
  1156. X/*
  1157. X * check_nlist(nlst) - checks the nlist to see if any symbols were not
  1158. X *        found.  For every symbol that was not found, a one-line
  1159. X *        message is printed to stderr.  The routine returns the
  1160. X *        number of symbols NOT found.
  1161. X */
  1162. X
  1163. Xstatic int check_nlist(nlst)
  1164. X
  1165. Xregister struct nlist *nlst;
  1166. X
  1167. X{
  1168. X    register int i;
  1169. X
  1170. X    /* check to see if we got ALL the symbols we requested */
  1171. X    /* this will write one line to stderr for every symbol not found */
  1172. X
  1173. X    i = 0;
  1174. X    while (nlst->n_name != NULL)
  1175. X    {
  1176. X    if (nlst->n_type == 0)
  1177. X    {
  1178. X        /* this one wasn't found */
  1179. X        fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
  1180. X        i = 1;
  1181. X    }
  1182. X    nlst++;
  1183. X    }
  1184. X
  1185. X    return(i);
  1186. X}
  1187. X
  1188. X
  1189. X/*
  1190. X *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
  1191. X *    "offset" is the byte offset into the kernel for the desired value,
  1192. X *      "ptr" points to a buffer into which the value is retrieved,
  1193. X *      "size" is the size of the buffer (and the object to retrieve),
  1194. X *      "refstr" is a reference string used when printing error meessages,
  1195. X *        if "refstr" starts with a '!', then a failure on read will not
  1196. X *          be fatal (this may seem like a silly way to do things, but I
  1197. X *          really didn't want the overhead of another argument).
  1198. X *      
  1199. X */
  1200. X
  1201. Xstatic int getkval(offset, ptr, size, refstr)
  1202. X
  1203. Xunsigned long offset;
  1204. Xint *ptr;
  1205. Xint size;
  1206. Xchar *refstr;
  1207. X
  1208. X{
  1209. X    if (kvm_read(kd, offset, (char *) ptr, size) != size)
  1210. X    {
  1211. X    if (*refstr == '!')
  1212. X    {
  1213. X        return(0);
  1214. X    }
  1215. X    else
  1216. X    {
  1217. X        fprintf(stderr, "top: kvm_read for %s: %s\n",
  1218. X        refstr, strerror(errno));
  1219. X        quit(23);
  1220. X    }
  1221. X    }
  1222. X    return(1);
  1223. X}
  1224. X    
  1225. X/* comparison routine for qsort */
  1226. X
  1227. X/*
  1228. X *  proc_compare - comparison function for "qsort"
  1229. X *    Compares the resource consumption of two processes using five
  1230. X *      distinct keys.  The keys (in descending order of importance) are:
  1231. X *      percent cpu, cpu ticks, state, resident set size, total virtual
  1232. X *      memory usage.  The process states are ordered as follows (from least
  1233. X *      to most important):  WAIT, zombie, sleep, stop, start, run.  The
  1234. X *      array declaration below maps a process state index into a number
  1235. X *      that reflects this ordering.
  1236. X */
  1237. X
  1238. Xstatic unsigned char sorted_state[] =
  1239. X{
  1240. X    0,    /* not used        */
  1241. X    3,    /* sleep        */
  1242. X    1,    /* ABANDONED (WAIT)    */
  1243. X    6,    /* run            */
  1244. X    5,    /* start        */
  1245. X    2,    /* zombie        */
  1246. X    4    /* stop            */
  1247. X};
  1248. Xproc_compare(pp1, pp2)
  1249. X
  1250. Xstruct kinfo_proc **pp1;
  1251. Xstruct kinfo_proc **pp2;
  1252. X
  1253. X{
  1254. X    register struct kinfo_proc *p1;
  1255. X    register struct kinfo_proc *p2;
  1256. X    register int result;
  1257. X    register pctcpu lresult;
  1258. X
  1259. X    /* remove one level of indirection */
  1260. X    p1 = *pp1;
  1261. X    p2 = *pp2;
  1262. X
  1263. X    /* compare percent cpu (pctcpu) */
  1264. X    if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0)
  1265. X    {
  1266. X    /* use cpticks to break the tie */
  1267. X    if ((result = PP(p2, p_cpticks) - PP(p1, p_cpticks)) == 0)
  1268. X    {
  1269. X        /* use process state to break the tie */
  1270. X        if ((result = sorted_state[PP(p2, p_stat)] -
  1271. X              sorted_state[PP(p1, p_stat)])  == 0)
  1272. X        {
  1273. X        /* use priority to break the tie */
  1274. X        if ((result = PP(p2, p_pri) - PP(p1, p_pri)) == 0)
  1275. X        {
  1276. X            /* use resident set size (rssize) to break the tie */
  1277. X            if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
  1278. X            {
  1279. X            /* use total memory to break the tie */
  1280. X            result = PROCSIZE(p2) - PROCSIZE(p1);
  1281. X            }
  1282. X        }
  1283. X        }
  1284. X    }
  1285. X    }
  1286. X    else
  1287. X    {
  1288. X    result = lresult < 0 ? -1 : 1;
  1289. X    }
  1290. X
  1291. X    return(result);
  1292. X}
  1293. X
  1294. X
  1295. X/*
  1296. X * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
  1297. X *        the process does not exist.
  1298. X *        It is EXTREMLY IMPORTANT that this function work correctly.
  1299. X *        If top runs setuid root (as in SVR4), then this function
  1300. X *        is the only thing that stands in the way of a serious
  1301. X *        security problem.  It validates requests for the "kill"
  1302. X *        and "renice" commands.
  1303. X */
  1304. X
  1305. Xint proc_owner(pid)
  1306. X
  1307. Xint pid;
  1308. X
  1309. X{
  1310. X    register int cnt;
  1311. X    register struct proc **prefp;
  1312. X    register struct proc *pp;
  1313. X
  1314. X    prefp = pref;
  1315. X    cnt = pref_len;
  1316. X    while (--cnt >= 0)
  1317. X    {
  1318. X    pp = *prefp++;    
  1319. X    if (PP(pp, p_pid) == (pid_t)pid)
  1320. X    {
  1321. X        return((int)EP(pp, e_pcred.p_ruid));
  1322. X    }
  1323. X    }
  1324. X    return(-1);
  1325. X}
  1326. END_OF_FILE
  1327. if test 15274 -ne `wc -c <'machine/m_bsd44a.c'`; then
  1328.     echo shar: \"'machine/m_bsd44a.c'\" unpacked with wrong size!
  1329. fi
  1330. # end of 'machine/m_bsd44a.c'
  1331. fi
  1332. if test -f 'machine/m_svr42.c' -a "${1}" != "-c" ; then 
  1333.   echo shar: Will not clobber existing file \"'machine/m_svr42.c'\"
  1334. else
  1335. echo shar: Extracting \"'machine/m_svr42.c'\" \(15173 characters\)
  1336. sed "s/^X//" >'machine/m_svr42.c' <<'END_OF_FILE'
  1337. X/*
  1338. X * top - a top users display for Unix
  1339. X *
  1340. X * SYNOPSIS:  For Intel based System V Release 4.2 (DESTINY)
  1341. X *
  1342. X * DESCRIPTION:
  1343. X *      System V release 4.2.x for i[3][4]86
  1344. X *
  1345. X * LIBS:  -lelf
  1346. X *
  1347. X * AUTHORS:  David Cutter       <dpc@grail.com>
  1348. X *           Andrew Herbert     <andrew@werple.apana.org.au>
  1349. X *           Robert Boucher     <boucher@sofkin.ca>
  1350. X */
  1351. X
  1352. X#include "top.h"
  1353. X#include "machine.h"
  1354. X#include <stdio.h>
  1355. X#include <fcntl.h>
  1356. X#include <unistd.h>
  1357. X#include <stdlib.h>
  1358. X#include <errno.h>
  1359. X#include <dirent.h>
  1360. X#include <nlist.h>
  1361. X#include <string.h>
  1362. X#include <sys/types.h>
  1363. X#include <sys/param.h>
  1364. X#include <sys/proc.h>
  1365. X#include <sys/procfs.h>
  1366. X#include <sys/sysinfo.h>
  1367. X#include <sys/sysmacros.h>
  1368. X#include <sys/vmmeter.h>
  1369. X#include <vm/anon.h>
  1370. X#include <sys/priocntl.h>
  1371. X#include <sys/rtpriocntl.h>
  1372. X#include <sys/tspriocntl.h>
  1373. X#include <sys/procset.h>
  1374. X#include <sys/var.h>
  1375. X
  1376. X#define UNIX "/stand/unix"
  1377. X#define KMEM "/dev/kmem"
  1378. X#define PROCFS "/proc"
  1379. X#define CPUSTATES    5
  1380. X
  1381. X#ifndef PRIO_MAX
  1382. X#define PRIO_MAX    20
  1383. X#endif
  1384. X#ifndef PRIO_MIN
  1385. X#define PRIO_MIN    -20
  1386. X#endif
  1387. X
  1388. X#ifndef FSCALE
  1389. X#define FSHIFT  8        /* bits to right of fixed binary point */
  1390. X#define FSCALE  (1<<FSHIFT)
  1391. X#endif
  1392. X
  1393. X#define loaddouble(x) ((double)(x) / FSCALE)
  1394. X#define percent_cpu(x) ((double)(x)->pr_cpu / FSCALE)
  1395. X#define weighted_cpu(pct, pp) ( ((pp)->pr_time.tv_sec) == 0 ? 0.0 : \
  1396. X        ((pp)->pr_cpu) / ((pp)->pr_time.tv_sec) )
  1397. X#define pagetok(size) ctob(size) >> LOG1024
  1398. X
  1399. X/* definitions for the index in the nlist array */
  1400. X#define X_AVENRUN    0
  1401. X#define X_MPID        1
  1402. X#define X_V        2
  1403. X#define X_NPROC        3
  1404. X#define X_ANONINFO    4
  1405. X#define X_TOTAL        5
  1406. X#define X_SYSINFO    6
  1407. X
  1408. Xstatic struct nlist nlst[] =
  1409. X{
  1410. X  {"avenrun"},            /* 0 */
  1411. X  {"mpid"},            /* 1 */
  1412. X  {"v"},            /* 2 */
  1413. X  {"nproc"},            /* 3 */
  1414. X  {"anoninfo"},            /* 4 */
  1415. X  {"total"},            /* 5 */
  1416. X  {"sysinfo"},            /* 6 */
  1417. X  {NULL}
  1418. X};
  1419. X
  1420. Xstatic unsigned long avenrun_offset;
  1421. Xstatic unsigned long mpid_offset;
  1422. Xstatic unsigned long nproc_offset;
  1423. Xstatic unsigned long anoninfo_offset;
  1424. Xstatic unsigned long total_offset;
  1425. Xstatic unsigned long sysinfo_offset;
  1426. X
  1427. X/* get_process_info passes back a handle.  This is what it looks like: */
  1428. X
  1429. Xstruct handle
  1430. X  {
  1431. X    struct prpsinfo **next_proc;/* points to next valid proc pointer */
  1432. X    int remaining;        /* number of pointers remaining */
  1433. X  };
  1434. X
  1435. X/*
  1436. X *  These definitions control the format of the per-process area
  1437. X */
  1438. X
  1439. Xstatic char header[] =
  1440. X"  PID X        PRI NICE   SIZE   RES STATE   TIME   WCPU    CPU COMMAND";
  1441. X/* 0123456   -- field to fill in starts at header+6 */
  1442. X#define UNAME_START 6
  1443. X#define Proc_format \
  1444. X    "%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %3d.0%% %5.2f%% %.16s"
  1445. X
  1446. Xchar *state_abbrev[] =
  1447. X{"", "sleep", "run", "zombie", "stop", "start", "cpu", "swap"};
  1448. X
  1449. Xint process_states[8];
  1450. Xchar *procstatenames[] =
  1451. X{
  1452. X  "", " sleeping, ", " running, ", " zombie, ", " stopped, ",
  1453. X  " starting, ", " on cpu, ", " swapped, ",
  1454. X  NULL
  1455. X};
  1456. X
  1457. Xint cpu_states[CPUSTATES];
  1458. Xchar *cpustatenames[] =
  1459. X{"idle", "user", "kernel", "wait", "swap", NULL};
  1460. X
  1461. X/* these are for detailing the memory statistics */
  1462. X
  1463. Xint memory_stats[5];
  1464. Xchar *memorynames[] =
  1465. X{"K real, ", "K active, ", "K free, ", "K swap, ", "K free swap", NULL};
  1466. X
  1467. Xstatic int kmem = -1;
  1468. Xstatic int nproc;
  1469. Xstatic int bytes;
  1470. Xstatic struct prpsinfo *pbase;
  1471. Xstatic struct prpsinfo **pref;
  1472. Xstatic DIR *procdir;
  1473. X
  1474. X/* useful externals */
  1475. Xextern int errno;
  1476. Xextern char *sys_errlist[];
  1477. Xextern char *myname;
  1478. Xextern long percentages ();
  1479. Xextern int check_nlist ();
  1480. Xextern int getkval ();
  1481. Xextern void perror ();
  1482. Xextern void getptable ();
  1483. Xextern void quit ();
  1484. Xextern int nlist ();
  1485. X
  1486. Xint
  1487. Xmachine_init (struct statics *statics)
  1488. X  {
  1489. X    static struct var v;
  1490. X
  1491. X    /* fill in the statics information */
  1492. X    statics->procstate_names = procstatenames;
  1493. X    statics->cpustate_names = cpustatenames;
  1494. X    statics->memory_names = memorynames;
  1495. X
  1496. X    /* get the list of symbols we want to access in the kernel */
  1497. X    if (nlist (UNIX, nlst))
  1498. X      {
  1499. X    (void) fprintf (stderr, "Unable to nlist %s\n", UNIX);
  1500. X    return (-1);
  1501. X      }
  1502. X
  1503. X    /* make sure they were all found */
  1504. X    if (check_nlist (nlst) > 0)
  1505. X      return (-1);
  1506. X
  1507. X    /* open kernel memory */
  1508. X    if ((kmem = open (KMEM, O_RDONLY)) == -1)
  1509. X      {
  1510. X    perror (KMEM);
  1511. X    return (-1);
  1512. X      }
  1513. X
  1514. X    /* get the symbol values out of kmem */
  1515. X    /* NPROC Tuning parameter for max number of processes */
  1516. X    (void) getkval (nlst[X_V].n_value, &v, sizeof (struct var), nlst[X_V].n_name);
  1517. X    nproc = v.v_proc;
  1518. X
  1519. X    /* stash away certain offsets for later use */
  1520. X    mpid_offset = nlst[X_MPID].n_value;
  1521. X    nproc_offset = nlst[X_NPROC].n_value;
  1522. X    avenrun_offset = nlst[X_AVENRUN].n_value;
  1523. X    anoninfo_offset = nlst[X_ANONINFO].n_value;
  1524. X    total_offset = nlst[X_TOTAL].n_value;
  1525. X    sysinfo_offset = nlst[X_SYSINFO].n_value;
  1526. X
  1527. X    /* allocate space for proc structure array and array of pointers */
  1528. X    bytes = nproc * sizeof (struct prpsinfo);
  1529. X    pbase = (struct prpsinfo *) malloc (bytes);
  1530. X    pref = (struct prpsinfo **) malloc (nproc * sizeof (struct prpsinfo *));
  1531. X
  1532. X    /* Just in case ... */
  1533. X    if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL)
  1534. X      {
  1535. X    (void) fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
  1536. X    return (-1);
  1537. X      }
  1538. X
  1539. X    if (!(procdir = opendir (PROCFS)))
  1540. X      {
  1541. X    (void) fprintf (stderr, "Unable to open %s\n", PROCFS);
  1542. X    return (-1);
  1543. X      }
  1544. X
  1545. X    if (chdir (PROCFS))
  1546. X      {                /* handy for later on when we're reading it */
  1547. X    (void) fprintf (stderr, "Unable to chdir to %s\n", PROCFS);
  1548. X    return (-1);
  1549. X      }
  1550. X
  1551. X    /* all done! */
  1552. X    return (0);
  1553. X  }
  1554. X
  1555. Xchar *
  1556. Xformat_header (char *uname_field)
  1557. X{
  1558. X  register char *ptr;
  1559. X
  1560. X  ptr = header + UNAME_START;
  1561. X  while (*uname_field != '\0')
  1562. X    *ptr++ = *uname_field++;
  1563. X
  1564. X  return (header);
  1565. X}
  1566. X
  1567. Xvoid
  1568. Xget_system_info (struct system_info *si)
  1569. X{
  1570. X  long avenrun[3];
  1571. X  struct sysinfo sysinfo;
  1572. X  struct vmtotal total;
  1573. X  struct anoninfo anoninfo;
  1574. X  static time_t cp_old[CPUSTATES];
  1575. X  static time_t cp_diff[CPUSTATES];    /* for cpu state percentages */
  1576. X  register int i;
  1577. X
  1578. X  (void) getkval (sysinfo_offset, &sysinfo, sizeof (struct sysinfo), "sysinfo");
  1579. X
  1580. X  /* convert cp_time counts to percentages */
  1581. X  (void) percentages (CPUSTATES, cpu_states, sysinfo.cpu, cp_old, cp_diff);
  1582. X
  1583. X  /* get mpid -- process id of last process */
  1584. X  (void) getkval (mpid_offset, &(si->last_pid), sizeof (si->last_pid),
  1585. X          "mpid");
  1586. X
  1587. X  /* get load average array */
  1588. X  (void) getkval (avenrun_offset, (int *) avenrun, sizeof (avenrun), "avenrun");
  1589. X
  1590. X  /* convert load averages to doubles */
  1591. X  for (i = 0; i < 3; i++)
  1592. X    si->load_avg[i] = loaddouble (avenrun[i]);
  1593. X
  1594. X  /* get total -- systemwide main memory usage structure */
  1595. X  (void) getkval (total_offset, (int *) (&total), sizeof (total), "total");
  1596. X  /* convert memory stats to Kbytes */
  1597. X  memory_stats[0] = pagetok (total.t_rm);
  1598. X  memory_stats[1] = pagetok (total.t_arm);
  1599. X  memory_stats[2] = pagetok (total.t_free);
  1600. X  (void) getkval (anoninfo_offset, (int *) (&anoninfo), sizeof (anoninfo),
  1601. X          "anoninfo");
  1602. X  memory_stats[3] = pagetok (anoninfo.ani_max - anoninfo.ani_free);
  1603. X  memory_stats[4] = pagetok (anoninfo.ani_max - anoninfo.ani_resv);
  1604. X
  1605. X  /* set arrays and strings */
  1606. X  si->cpustates = cpu_states;
  1607. X  si->memory = memory_stats;
  1608. X}
  1609. X
  1610. Xstatic struct handle handle;
  1611. X
  1612. Xcaddr_t
  1613. Xget_process_info (
  1614. X           struct system_info *si,
  1615. X           struct process_select *sel,
  1616. X           int (*compare) ())
  1617. X{
  1618. X  register int i;
  1619. X  register int total_procs;
  1620. X  register int active_procs;
  1621. X  register struct prpsinfo **prefp;
  1622. X  register struct prpsinfo *pp;
  1623. X
  1624. X  /* these are copied out of sel for speed */
  1625. X  int show_idle;
  1626. X  int show_system;
  1627. X  int show_uid;
  1628. X
  1629. X  /* Get current number of processes */
  1630. X  (void) getkval (nproc_offset, (int *) (&nproc), sizeof (nproc), "nproc");
  1631. X
  1632. X  /* read all the proc structures */
  1633. X  getptable (pbase);
  1634. X
  1635. X  /* get a pointer to the states summary array */
  1636. X  si->procstates = process_states;
  1637. X
  1638. X  /* set up flags which define what we are going to select */
  1639. X  show_idle = sel->idle;
  1640. X  show_system = sel->system;
  1641. X  show_uid = sel->uid != -1;
  1642. X
  1643. X  /* count up process states and get pointers to interesting procs */
  1644. X  total_procs = 0;
  1645. X  active_procs = 0;
  1646. X  (void) memset (process_states, 0, sizeof (process_states));
  1647. X  prefp = pref;
  1648. X
  1649. X  for (pp = pbase, i = 0; i < nproc; pp++, i++)
  1650. X    {
  1651. X      /*
  1652. X     *  Place pointers to each valid proc structure in pref[].
  1653. X     *  Process slots that are actually in use have a non-zero
  1654. X     *  status field.  Processes with SSYS set are system
  1655. X     *  processes---these get ignored unless show_sysprocs is set.
  1656. X     */
  1657. X      if (pp->pr_state != 0 &&
  1658. X      (show_system || ((pp->pr_flag & SSYS) == 0)))
  1659. X    {
  1660. X      total_procs++;
  1661. X      process_states[pp->pr_state]++;
  1662. X      if ((!pp->pr_zomb) &&
  1663. X          (show_idle || (pp->pr_state == SRUN) || (pp->pr_state == SONPROC)) &&
  1664. X          (!show_uid || pp->pr_uid == (uid_t) sel->uid))
  1665. X        {
  1666. X          *prefp++ = pp;
  1667. X          active_procs++;
  1668. X        }
  1669. X    }
  1670. X    }
  1671. X
  1672. X  /* if requested, sort the "interesting" processes */
  1673. X  if (compare != NULL)
  1674. X      qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *), compare);
  1675. X
  1676. X  /* remember active and total counts */
  1677. X  si->p_total = total_procs;
  1678. X  si->p_active = active_procs;
  1679. X
  1680. X  /* pass back a handle */
  1681. X  handle.next_proc = pref;
  1682. X  handle.remaining = active_procs;
  1683. X  return ((caddr_t) & handle);
  1684. X}
  1685. X
  1686. Xchar fmt[128];            /* static area where result is built */
  1687. X
  1688. Xchar *
  1689. Xformat_next_process (
  1690. X              caddr_t handle,
  1691. X              char *(*get_userid) ())
  1692. X{
  1693. X  register struct prpsinfo *pp;
  1694. X  struct handle *hp;
  1695. X  register long cputime;
  1696. X  register double pctcpu;
  1697. X
  1698. X  /* find and remember the next proc structure */
  1699. X  hp = (struct handle *) handle;
  1700. X  pp = *(hp->next_proc++);
  1701. X  hp->remaining--;
  1702. X
  1703. X  /* get the cpu usage and calculate the cpu percentages */
  1704. X  cputime = pp->pr_time.tv_sec;
  1705. X  pctcpu = percent_cpu (pp);
  1706. X
  1707. X  /* format this entry */
  1708. X  (void) sprintf (fmt,
  1709. X          Proc_format,
  1710. X          pp->pr_pid,
  1711. X          (*get_userid) (pp->pr_uid),
  1712. X          pp->pr_pri - PZERO,
  1713. X          pp->pr_nice - NZERO,
  1714. X          pagetok (pp->pr_size),
  1715. X          pagetok (pp->pr_rssize),
  1716. X          state_abbrev[pp->pr_state],
  1717. X          cputime / 60l,
  1718. X          cputime % 60l,
  1719. X          (pp->pr_cpu & 0377),
  1720. X          100.0 * pctcpu,
  1721. X          pp->pr_fname);
  1722. X
  1723. X  /* return the result */
  1724. X  return (fmt);
  1725. X}
  1726. X
  1727. X/*
  1728. X * check_nlist(nlst) - checks the nlist to see if any symbols were not
  1729. X *        found.  For every symbol that was not found, a one-line
  1730. X *        message is printed to stderr.  The routine returns the
  1731. X *        number of symbols NOT found.
  1732. X */
  1733. Xint
  1734. Xcheck_nlist (register struct nlist *nlst)
  1735. X{
  1736. X  register int i;
  1737. X
  1738. X  /* check to see if we got ALL the symbols we requested */
  1739. X  /* this will write one line to stderr for every symbol not found */
  1740. X
  1741. X  i = 0;
  1742. X  while (nlst->n_name != NULL)
  1743. X    {
  1744. X      if (nlst->n_type == 0)
  1745. X    {
  1746. X      /* this one wasn't found */
  1747. X      (void) fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
  1748. X      i = 1;
  1749. X    }
  1750. X      nlst++;
  1751. X    }
  1752. X  return (i);
  1753. X}
  1754. X
  1755. X
  1756. X/*
  1757. X *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
  1758. X *    "offset" is the byte offset into the kernel for the desired value,
  1759. X *      "ptr" points to a buffer into which the value is retrieved,
  1760. X *      "size" is the size of the buffer (and the object to retrieve),
  1761. X *      "refstr" is a reference string used when printing error meessages,
  1762. X *        if "refstr" starts with a '!', then a failure on read will not
  1763. X *          be fatal (this may seem like a silly way to do things, but I
  1764. X *          really didn't want the overhead of another argument).
  1765. X *
  1766. X */
  1767. Xint
  1768. Xgetkval (
  1769. X      unsigned long offset,
  1770. X      int *ptr,
  1771. X      int size,
  1772. X      char *refstr)
  1773. X{
  1774. X  if (lseek (kmem, (long) offset, 0) == -1)
  1775. X    {
  1776. X      if (*refstr == '!')
  1777. X    refstr++;
  1778. X      (void) fprintf (stderr, "%s: lseek to %s: %s\n",
  1779. X              myname, refstr, sys_errlist[errno]);
  1780. X      quit (22);
  1781. X    }
  1782. X  if (read (kmem, (char *) ptr, size) == -1)
  1783. X    if (*refstr == '!')
  1784. X      /* we lost the race with the kernel, process isn't in memory */
  1785. X      return (0);
  1786. X    else
  1787. X      {
  1788. X    (void) fprintf (stderr, "%s: reading %s: %s\n",
  1789. X            myname, refstr, sys_errlist[errno]);
  1790. X    quit (23);
  1791. X      }
  1792. X  return (1);
  1793. X}
  1794. X
  1795. X/* comparison routine for qsort */
  1796. X
  1797. X/*
  1798. X *  proc_compare - comparison function for "qsort"
  1799. X *    Compares the resource consumption of two processes using five
  1800. X *      distinct keys.  The keys (in descending order of importance) are:
  1801. X *      percent cpu, cpu ticks, state, resident set size, total virtual
  1802. X *      memory usage.  The process states are ordered as follows (from least
  1803. X *      to most important):  WAIT, zombie, sleep, stop, start, run.  The
  1804. X *      array declaration below maps a process state index into a number
  1805. X *      that reflects this ordering.
  1806. X */
  1807. X
  1808. X
  1809. Xunsigned char sorted_state[] =
  1810. X{
  1811. X  0,                /* not used        */
  1812. X  3,                /* sleep        */
  1813. X  6,                /* run            */
  1814. X  2,                /* zombie        */
  1815. X  4,                /* stop            */
  1816. X  5,                /* start        */
  1817. X  7,                /* run on a processor   */
  1818. X  1                /* being swapped (WAIT)    */
  1819. X};
  1820. X
  1821. Xint
  1822. Xproc_compare (
  1823. X           struct prpsinfo **pp1,
  1824. X           struct prpsinfo **pp2)
  1825. X  {
  1826. X    register struct prpsinfo *p1;
  1827. X    register struct prpsinfo *p2;
  1828. X    register long result;
  1829. X
  1830. X    /* remove one level of indirection */
  1831. X    p1 = *pp1;
  1832. X    p2 = *pp2;
  1833. X
  1834. X    /* compare percent cpu (pctcpu) */
  1835. X    if ((result = (long) (p2->pr_cpu - p1->pr_cpu)) == 0)
  1836. X      {
  1837. X    /* use cpticks to break the tie */
  1838. X    if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
  1839. X      {
  1840. X        /* use process state to break the tie */
  1841. X        if ((result = (long) (sorted_state[p2->pr_state] -
  1842. X                  sorted_state[p1->pr_state])) == 0)
  1843. X          {
  1844. X        /* use priority to break the tie */
  1845. X        if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0)
  1846. X          {
  1847. X            /* use resident set size (rssize) to break the tie */
  1848. X            if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
  1849. X              {
  1850. X            /* use total memory to break the tie */
  1851. X            result = (p2->pr_size - p1->pr_size);
  1852. X              }
  1853. X          }
  1854. X          }
  1855. X      }
  1856. X      }
  1857. X    return (result);
  1858. X  }
  1859. X
  1860. X/*
  1861. Xget process table
  1862. X*/
  1863. Xvoid
  1864. Xgetptable (struct prpsinfo *baseptr)
  1865. X{
  1866. X  struct prpsinfo *currproc;    /* pointer to current proc structure    */
  1867. X  int numprocs = 0;
  1868. X  struct dirent *direntp;
  1869. X
  1870. X  for (rewinddir (procdir); direntp = readdir (procdir);)
  1871. X    {
  1872. X      int fd;
  1873. X
  1874. X      if ((fd = open (direntp->d_name, O_RDONLY)) < 0)
  1875. X    continue;
  1876. X
  1877. X      currproc = &baseptr[numprocs];
  1878. X      if (ioctl (fd, PIOCPSINFO, currproc) < 0)
  1879. X    {
  1880. X      (void) close (fd);
  1881. X      continue;
  1882. X    }
  1883. X
  1884. X      numprocs++;
  1885. X      (void) close (fd);
  1886. X    }
  1887. X
  1888. X  if (nproc != numprocs)
  1889. X    nproc = numprocs;
  1890. X}
  1891. X
  1892. X/* return the owner of the specified process, for use in commands.c as we're
  1893. X   running setuid root */
  1894. Xuid_t
  1895. Xproc_owner (pid_t pid)
  1896. X{
  1897. X  register struct prpsinfo *p;
  1898. X  int i;
  1899. X  for (i = 0, p = pbase; i < nproc; i++, p++)
  1900. X    if (p->pr_pid == pid)
  1901. X      return (p->pr_uid);
  1902. X
  1903. X  return (-1);
  1904. X}
  1905. X
  1906. Xint
  1907. Xsetpriority (int dummy, int who, int niceval)
  1908. X{
  1909. X  int scale;
  1910. X  int prio;
  1911. X  pcinfo_t pcinfo;
  1912. X  pcparms_t pcparms;
  1913. X  tsparms_t *tsparms;
  1914. X
  1915. X  strcpy (pcinfo.pc_clname, "TS");
  1916. X  if (priocntl (0, 0, PC_GETCID, (caddr_t) & pcinfo) == -1)
  1917. X    return (-1);
  1918. X
  1919. X  prio = niceval;
  1920. X  if (prio > PRIO_MAX)
  1921. X    prio = PRIO_MAX;
  1922. X  else if (prio < PRIO_MIN)
  1923. X    prio = PRIO_MIN;
  1924. X
  1925. X  tsparms = (tsparms_t *) pcparms.pc_clparms;
  1926. X  scale = ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri;
  1927. X  tsparms->ts_uprilim = tsparms->ts_upri = -(scale * prio) / 20;
  1928. X  pcparms.pc_cid = pcinfo.pc_cid;
  1929. X
  1930. X  if (priocntl (P_PID, who, PC_SETPARMS, (caddr_t) & pcparms) == -1)
  1931. X    return (-1);
  1932. X
  1933. X  return (0);
  1934. X}
  1935. END_OF_FILE
  1936. if test 15173 -ne `wc -c <'machine/m_svr42.c'`; then
  1937.     echo shar: \"'machine/m_svr42.c'\" unpacked with wrong size!
  1938. fi
  1939. # end of 'machine/m_svr42.c'
  1940. fi
  1941. echo shar: End of archive 4 \(of 13\).
  1942. cp /dev/null ark4isdone
  1943. MISSING=""
  1944. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  1945.     if test ! -f ark${I}isdone ; then
  1946.     MISSING="${MISSING} ${I}"
  1947.     fi
  1948. done
  1949. if test "${MISSING}" = "" ; then
  1950.     echo You have unpacked all 13 archives.
  1951.     echo "Now read README and INSTALL, then run Configure"
  1952.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1953. else
  1954.     echo You still need to unpack the following archives:
  1955.     echo "        " ${MISSING}
  1956. fi
  1957. ##  End of shell archive.
  1958. exit 0
  1959.