home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / skill / part03 < prev    next >
Text File  |  1994-07-15  |  70KB  |  2,517 lines

  1. Newsgroups: comp.sources.unix
  2. From: jeff@forys.cranbury.nj.us (Jeff Forys)
  3. Subject: v28i089: skill - signal or reprioritize specified processes, V3.6, Part03/03
  4. References: <1.774325799.5452@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: jeff@forys.cranbury.nj.us (Jeff Forys)
  9. Posting-Number: Volume 28, Issue 89
  10. Archive-Name: skill/part03
  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 3 (of 3)."
  19. # Contents:  machdep/aos-43.c machdep/bsd-43.c machdep/irix-3.c
  20. #   machdep/irix-4.c machdep/ultrix-4.c
  21. # Wrapped by vixie@gw.home.vix.com on Fri Jul 15 19:29:13 1994
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'machdep/aos-43.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'machdep/aos-43.c'\"
  25. else
  26. echo shar: Extracting \"'machdep/aos-43.c'\" \(11465 characters\)
  27. sed "s/^X//" >'machdep/aos-43.c' <<'END_OF_FILE'
  28. X#ifndef lint
  29. Xstatic char rcsid[] = "$Header: aos-43.c,v 1.8 1994/06/26 04:15:19 forys Exp $";
  30. X#endif
  31. X
  32. X/*
  33. X**  This program may be freely redistributed for noncommercial purposes.
  34. X**  This entire comment MUST remain intact.
  35. X**
  36. X**  AOS 4.3 support by Christos Zoulas (christos@deshaw.com)
  37. X**
  38. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  39. X*/
  40. X
  41. X#define    NO_MEXTERN
  42. X#include "conf.h"
  43. X#undef    NO_MEXTERN
  44. X
  45. X#include <sys/user.h>
  46. X#include <sys/proc.h>
  47. X
  48. X#include <stdio.h>
  49. X
  50. X/*
  51. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  52. X * routines and must be global.  Everyone seems to have their own
  53. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  54. X * signals available, not counting zero.
  55. X */
  56. Xchar *SigMap[] = { "0",
  57. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  58. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  59. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  60. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  61. X    "XFSZ", "VTALRM", "PROF", "WINCH", "LOST", "USR1",    /* 25 - 30 */
  62. X    "USR2", "32",                        /* 31 - 32 */
  63. X};
  64. Xint NSig = NSIG;
  65. X
  66. X#define    SETCMD(dst,src,maxlen) {            \
  67. X    extern char *rindex();                \
  68. X    if (maxlen > 0) src[maxlen] = '\0';        \
  69. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  70. X}
  71. X
  72. Xstatic char *TtyDevDir = "/dev";
  73. X
  74. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  75. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  76. Xint    SigPri;            /* signal to send or priority to set */
  77. Xpid_T    MyPid;            /* pid of this process */
  78. Xuid_T    MyUid;            /* uid of this process */
  79. Xchar    *ProgName;        /* program name */
  80. X
  81. X/*
  82. X * This is the machine-dependent initialization routine.
  83. X *
  84. X *   - The following global variables must be initialized:
  85. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  86. X *   - The working directory will be changed to that which contains the
  87. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  88. X *   - If possible, this routine should raise the priority of this process.
  89. X */
  90. Xvoid
  91. XMdepInit(pname)
  92. X    char *pname;
  93. X{
  94. X    extern char *rindex(), *SysErr();
  95. X
  96. X    MyPid = (pid_T) getpid();
  97. X    MyUid = (uid_T) getuid();
  98. X    SETCMD(ProgName, pname, 0)
  99. X
  100. X    /*
  101. X     * If we are running as root, raise our priority to better
  102. X     * catch runaway processes.
  103. X     */
  104. X    if (MyUid == ROOTUID)
  105. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  106. X
  107. X    /*
  108. X     * Determine what we are doing to processes we find.  We will
  109. X     * either send them a signal (skill), or renice them (snice).
  110. X     */
  111. X    Skill = (strcmp(ProgName, "snice") != 0);
  112. X
  113. X    /*
  114. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  115. X     */
  116. X    if (chdir(TtyDevDir) < 0) {
  117. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  118. X                SysErr());
  119. X        exit(EX_SERR);
  120. X    }
  121. X
  122. X    /*
  123. X     * Set up minimum and maximum process priorities.
  124. X     * Initialize SigPri to either default signal (`skill') or
  125. X     * default priority (`snice').
  126. X     */
  127. X    PrioMin = PRIO_MIN;
  128. X    PrioMax = PRIO_MAX;
  129. X    SigPri = Skill? SIGTERM: 4;
  130. X}
  131. X
  132. X/*
  133. X * Carry out an action on a particular process.  If this is `skill',
  134. X * then send the process a signal, otherwise this is `snice' so change
  135. X * it's priority.
  136. X *
  137. X * If 0 is returned, the operation was successful, otherwise -1 is
  138. X * returned and `errno' set.
  139. X */
  140. Xint
  141. XMdepAction(pid)
  142. X    pid_T pid;
  143. X{
  144. X    if (Skill)
  145. X        return(kill((int)pid, SigPri));
  146. X    else
  147. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  148. X}
  149. X
  150. X/*
  151. X * Now, set up everything we need to write a GetProc() routine.
  152. X */
  153. X
  154. X#include <sys/file.h>
  155. X#include <sys/vm.h>
  156. X
  157. X#include <machine/pte.h>
  158. X
  159. X#include <nlist.h>
  160. X
  161. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  162. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  163. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  164. Xstatic char *kernf =    "/vmunix";    /* kernel image */
  165. Xstatic int kmem = 0, mem = 0, swap = 0;
  166. X
  167. Xstatic struct nlist nl[] = {
  168. X    { "_nproc" },
  169. X#define    X_NPROC        0
  170. X    { "_proc" },
  171. X#define    X_PROC        1
  172. X    { "_Usrptmap" },
  173. X#define    X_USRPTMAP    2
  174. X    { "_usrpt" },
  175. X#define    X_USRPT        3
  176. X    { "" },
  177. X#define    X_LAST        4
  178. X};
  179. X
  180. Xstatic    int    nproc = -1;
  181. Xstatic    struct    proc *procp;
  182. Xstatic    struct    pte *usrptmap, *usrpt;
  183. X
  184. X#define    NPROCS    32            /* number of procs to read at once */
  185. X
  186. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  187. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  188. X
  189. Xextern    off_t lseek();
  190. X
  191. X/*
  192. X * GetProc()
  193. X *
  194. X * Fill in and return a `struct ProcInfo' with information about the
  195. X * next process.  If no processes are left, return NULL.
  196. X *
  197. X * Fflag support:
  198. X *    If Fflag is set we will try to avoid reading in the user struct.
  199. X *    We can do this only if Iflag, TtyIndx, and CmdIndx are zero.
  200. X */
  201. Xstruct ProcInfo *
  202. XGetProc()
  203. X{
  204. X    extern char *SysErr();
  205. X    static struct user *GetUser();
  206. X    static struct proc procs[NPROCS], *procsp;
  207. X    static struct ProcInfo procinfo;
  208. X    register struct user *auser;
  209. X    register struct proc *aproc;
  210. X    static int thisproc = 0;
  211. X    static int needuser = 1;        /* Fflag support */
  212. X
  213. X    /*
  214. X     * If this is our first time here, open various files,
  215. X     * and set up the nlist.
  216. X     */
  217. X    if (nproc == -1) {
  218. X        char *errstr = "%s: %s: %s\n";
  219. X        int nfound;
  220. X
  221. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  222. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  223. X            exit(EX_SERR);
  224. X        }
  225. X
  226. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  227. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  228. X            exit(EX_SERR);
  229. X        }
  230. X
  231. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  232. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  233. X            exit(EX_SERR);
  234. X        }
  235. X
  236. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  237. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  238. X            exit(EX_SERR);
  239. X        }
  240. X        if (nfound != 0) {
  241. X            register int i;
  242. X
  243. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  244. X                    ProgName);
  245. X            for (i = 0; i < X_LAST; i++)
  246. X                if (nl[i].n_type == 0)
  247. X                    fprintf(stderr, " %s", nl[i].n_name);
  248. X            (void) putc('\n', stderr);
  249. X            exit(EX_SERR);
  250. X        }
  251. X
  252. X        usrpt = (struct pte *) nl[X_USRPT].n_value;
  253. X        usrptmap = (struct pte *) nl[X_USRPTMAP].n_value;
  254. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  255. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  256. X        /*
  257. X         * We run much faster without reading in the user struct;
  258. X         * the price is incomplete information for errors (no cmd).
  259. X         */
  260. X        if (Fflag && Iflag == 0 && TtyIndx == 0 && CmdIndx == 0)
  261. X            needuser = 0;
  262. X    }
  263. X
  264. X    /*
  265. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  266. X     * by the number of proc structures we have read; when it reaches
  267. X     * zero, we are finished (return NULL).
  268. X     */
  269. X    do {
  270. X        while (thisproc == 0) {
  271. X            int nread;
  272. X            int psize;
  273. X
  274. X            if (nproc == 0)
  275. X                return((struct ProcInfo *)NULL);
  276. X
  277. X            thisproc = MIN(NPROCS, nproc);
  278. X            psize = thisproc * sizeof(struct proc);
  279. X            nproc -= thisproc;
  280. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  281. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  282. X                fprintf(stderr, "%s: read proc: %s\n",
  283. X                        ProgName, SysErr());
  284. X                return((struct ProcInfo *)NULL);
  285. X            } else if (nread != psize) {
  286. X                thisproc = nread / sizeof(struct proc);
  287. X                nproc = 0;
  288. X                fprintf(stderr, "%s: read proc: short read\n",
  289. X                        ProgName);
  290. X            }
  291. X            procsp = procs;
  292. X            procp += thisproc;
  293. X        }
  294. X
  295. X        aproc = procsp++;
  296. X        thisproc--;
  297. X
  298. X        if (aproc->p_stat != 0) {
  299. X            /*
  300. X             * Before we go through the trouble of reading
  301. X             * in the user struct, let's make sure this isn't
  302. X             * a "zombie" or "exiting" process.  If it is,
  303. X             * we have all the information we need; fill in
  304. X             * procinfo and return.
  305. X             */
  306. X            procinfo.pi_flags = 0;
  307. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  308. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  309. X
  310. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  311. X                static char *zombie = "<defunct>";
  312. X                procinfo.pi_flags |= PI_ZOMBIE;
  313. X                procinfo.pi_cmd = zombie;
  314. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  315. X                static char *exiting = "<exiting>";
  316. X                procinfo.pi_flags |= PI_SWEXIT;
  317. X                procinfo.pi_cmd = exiting;
  318. X            } else if (!needuser) {            /* Fflag */
  319. X                static char *fflagcmd = "<-f>";
  320. X                procinfo.pi_cmd = fflagcmd;
  321. X            }
  322. X
  323. X            if (procinfo.pi_flags || !needuser)
  324. X                return(&procinfo);
  325. X            else
  326. X                auser = GetUser(aproc);
  327. X        }
  328. X
  329. X    } while (aproc->p_stat == 0 || auser == NULL);
  330. X
  331. X    /*
  332. X     * We now have a process (`aproc') and a user (`auser').
  333. X     * Fill in the rest of `procinfo'.
  334. X     */
  335. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  336. X        procinfo.pi_flags |= PI_CTLTTY;
  337. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  338. X    }
  339. X
  340. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  341. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  342. X        procinfo.pi_flags |= PI_ASKUSR;
  343. X    } else                 /* set path-stripped command name */
  344. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  345. X
  346. X    return(&procinfo);
  347. X}
  348. X
  349. X#define    SKRD(file, src, dst, size)            \
  350. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  351. X    (read(file, (char *)(dst), (size)) != (size))
  352. X
  353. X/*
  354. X * GetWord(loc)
  355. X *
  356. X * Read in word at `loc' from kernel virtual memory.
  357. X * If an error occurs, call exit(2) with EX_SERR.
  358. X */
  359. Xstatic int
  360. XGetWord(loc)
  361. X    off_t loc;
  362. X{
  363. X    int val;
  364. X
  365. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  366. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  367. X                ProgName, (u_long)loc, kmemf);
  368. X        exit(EX_SERR);
  369. X    }
  370. X    return (val);
  371. X}
  372. X
  373. X#ifndef    CLBYTES
  374. X#define    CLBYTES    (CLSIZE*NBPG)
  375. X#endif
  376. X
  377. X/*
  378. X * GetUser(aproc)
  379. X *
  380. X * Read in the user struct for `aproc' and return a pointer to it.
  381. X * If an error occurs, return NULL.
  382. X */
  383. X#define    SW_UADDR    dtob(aproc->p_swaddr)
  384. X#define    SW_UBYTES    sizeof(struct userx)
  385. X
  386. Xstruct userx {
  387. X    char userfill[UPAGES * NBPG - sizeof(struct user)];
  388. X    struct user user;
  389. X};
  390. X#define REDSIZE (CLSIZE * 2)
  391. X
  392. Xstatic struct user *
  393. XGetUser(aproc)
  394. X    struct proc *aproc;
  395. X{
  396. X    static char *WarnMsg = "Warning: can't read ";
  397. X    union u {
  398. X        struct userx user;
  399. X        char    upgs[UPAGES][NBPG * CLSIZE];
  400. X    } u;
  401. X    static struct pte apte, uptes[HIGHPAGES + CLSIZE + REDSIZE];
  402. X    register int ncl, i;
  403. X
  404. X    /*
  405. X     * If process is not in core, we simply snarf it's user struct
  406. X     * from the swap device.
  407. X     */
  408. X    if ((aproc->p_flag & SLOAD) == 0) {
  409. X        if (SKRD(swap, SW_UADDR, &u, SW_UBYTES)) {
  410. X            if (Wflag)
  411. X                printf("%su for pid %d from %s\n",
  412. X                       WarnMsg, aproc->p_pid, swapf);
  413. X            return ((struct user *)NULL);
  414. X        }
  415. X        return (&u.user.user);
  416. X    }
  417. X
  418. X    /*
  419. X     * Process is in core.  First read from the user page-table
  420. X     * map for this process to get the u-area page table entry.
  421. X     * Next, read in the page table entries that map the u-area.
  422. X     * Finally, read in the physical pages that comprise the u-area.
  423. X     *
  424. X     * If at any time, an lseek() or read() fails, print a warning
  425. X     * message (if `Wflag' is set) and return NULL.
  426. X     */
  427. X    if (SKRD(kmem, &usrptmap[btokmx(aproc->p_p0br) + aproc->p_szpt - 1],
  428. X             &apte, sizeof(apte))) {
  429. X        if (Wflag)
  430. X            printf("%sindir pte of user pt for pid %d from %s\n",
  431. X                   WarnMsg, aproc->p_pid, kmemf);
  432. X        return ((struct user *)NULL);
  433. X    }
  434. X
  435. X    if (SKRD(mem, ctob(apte.pg_pfnum+1) - sizeof(uptes),
  436. X             uptes, sizeof(uptes))) {
  437. X        if (Wflag)
  438. X            printf("%suser pt for pid %d from %s\n",
  439. X                   WarnMsg, aproc->p_pid, memf);
  440. X        return ((struct user *)NULL);
  441. X    }
  442. X
  443. X    /*
  444. X     * Set `ncl' to the (rounded up) number of u-area page clusters
  445. X     * to read, and then read in this user struct (in reverse).
  446. X     */
  447. X    ncl = (SW_UBYTES + NBPG * CLSIZE - 1) / (NBPG * CLSIZE);
  448. X    while (--ncl >= 0) {
  449. X        i = ncl * CLSIZE;
  450. X        if (SKRD(mem,ctob(uptes[CLSIZE+REDSIZE+i].pg_pfnum),
  451. X             u.upgs[i],CLBYTES)){
  452. X            if (Wflag)
  453. X                printf("%suser page %u for pid %d from %s\n",
  454. X                       WarnMsg, 
  455. X                       uptes[CLSIZE+REDSIZE+i].pg_pfnum,
  456. X                       aproc->p_pid, memf);
  457. X            return((struct user *)NULL);
  458. X        }
  459. X    }
  460. X    return (&u.user.user);
  461. X}
  462. END_OF_FILE
  463. if test 11465 -ne `wc -c <'machdep/aos-43.c'`; then
  464.     echo shar: \"'machdep/aos-43.c'\" unpacked with wrong size!
  465. fi
  466. # end of 'machdep/aos-43.c'
  467. fi
  468. if test -f 'machdep/bsd-43.c' -a "${1}" != "-c" ; then 
  469.   echo shar: Will not clobber existing file \"'machdep/bsd-43.c'\"
  470. else
  471. echo shar: Extracting \"'machdep/bsd-43.c'\" \(12470 characters\)
  472. sed "s/^X//" >'machdep/bsd-43.c' <<'END_OF_FILE'
  473. X#ifndef lint
  474. Xstatic char rcsid[] = "$Header: bsd-43.c,v 1.9 1994/06/26 04:15:06 forys Exp $";
  475. X#endif
  476. X
  477. X/*
  478. X**  This program may be freely redistributed for noncommercial purposes.
  479. X**  This entire comment MUST remain intact.
  480. X**
  481. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  482. X*/
  483. X
  484. X#define    NO_MEXTERN
  485. X#include "conf.h"
  486. X#undef    NO_MEXTERN
  487. X
  488. X#include <sys/user.h>
  489. X#include <sys/proc.h>
  490. X
  491. X#include <stdio.h>
  492. X
  493. X/*
  494. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  495. X * routines and must be global.  Everyone seems to have their own
  496. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  497. X * signals available, not counting zero.
  498. X */
  499. Xchar *SigMap[] = { "0",
  500. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  501. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  502. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  503. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  504. X    "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",    /* 25 - 30 */
  505. X    "USR2", "32",                        /* 31 - 32 */
  506. X};
  507. Xint NSig = NSIG;
  508. X
  509. X#define    SETCMD(dst,src,maxlen) {            \
  510. X    extern char *rindex();                \
  511. X    if (maxlen > 0) src[maxlen] = '\0';        \
  512. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  513. X}
  514. X
  515. Xstatic char *TtyDevDir = "/dev";
  516. X
  517. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  518. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  519. Xint    SigPri;            /* signal to send or priority to set */
  520. Xpid_T    MyPid;            /* pid of this process */
  521. Xuid_T    MyUid;            /* uid of this process */
  522. Xchar    *ProgName;        /* program name */
  523. X
  524. X/*
  525. X * This is the machine-dependent initialization routine.
  526. X *
  527. X *   - The following global variables must be initialized:
  528. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  529. X *   - The working directory will be changed to that which contains the
  530. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  531. X *   - If possible, this routine should raise the priority of this process.
  532. X */
  533. Xvoid
  534. XMdepInit(pname)
  535. X    char *pname;
  536. X{
  537. X    extern char *rindex(), *SysErr();
  538. X
  539. X    MyPid = (pid_T) getpid();
  540. X    MyUid = (uid_T) getuid();
  541. X    SETCMD(ProgName, pname, 0)
  542. X
  543. X    /*
  544. X     * If we are running as root, raise our priority to better
  545. X     * catch runaway processes.
  546. X     */
  547. X    if (MyUid == ROOTUID)
  548. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  549. X
  550. X    /*
  551. X     * Determine what we are doing to processes we find.  We will
  552. X     * either send them a signal (skill), or renice them (snice).
  553. X     */
  554. X    Skill = (strcmp(ProgName, "snice") != 0);
  555. X
  556. X    /*
  557. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  558. X     */
  559. X    if (chdir(TtyDevDir) < 0) {
  560. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  561. X                SysErr());
  562. X        exit(EX_SERR);
  563. X    }
  564. X
  565. X    /*
  566. X     * Set up minimum and maximum process priorities.
  567. X     * Initialize SigPri to either default signal (`skill') or
  568. X     * default priority (`snice').
  569. X     */
  570. X    PrioMin = PRIO_MIN;
  571. X    PrioMax = PRIO_MAX;
  572. X    SigPri = Skill? SIGTERM: 4;
  573. X}
  574. X
  575. X/*
  576. X * Carry out an action on a particular process.  If this is `skill',
  577. X * then send the process a signal, otherwise this is `snice' so change
  578. X * it's priority.
  579. X *
  580. X * If 0 is returned, the operation was successful, otherwise -1 is
  581. X * returned and `errno' set.
  582. X */
  583. Xint
  584. XMdepAction(pid)
  585. X    pid_T pid;
  586. X{
  587. X    if (Skill)
  588. X        return(kill((int)pid, SigPri));
  589. X    else
  590. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  591. X}
  592. X
  593. X/*
  594. X * Now, set up everything we need to write a GetProc() routine.
  595. X */
  596. X
  597. X#include <sys/file.h>
  598. X#include <sys/vm.h>
  599. X
  600. X#include <machine/pte.h>
  601. X
  602. X#include <nlist.h>
  603. X
  604. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  605. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  606. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  607. Xstatic char *kernf =    "/vmunix";    /* kernel image */
  608. Xstatic int kmem = 0, mem = 0, swap = 0;
  609. X
  610. Xstatic struct nlist nl[] = {
  611. X    { "_nproc" },
  612. X#define    X_NPROC        0
  613. X    { "_proc" },
  614. X#define    X_PROC        1
  615. X    { "_Usrptmap" },
  616. X#define    X_USRPTMAP    2
  617. X    { "_usrpt" },
  618. X#define    X_USRPT        3
  619. X#ifndef hp800
  620. X    { "" },
  621. X#define    X_LAST        4
  622. X#else
  623. X    { "_ubase" },
  624. X#define    X_UBASE        4
  625. X    { "" },
  626. X#define    X_LAST        5
  627. X#endif
  628. X};
  629. X
  630. Xstatic    int    nproc = -1;
  631. Xstatic    struct    proc *procp;
  632. Xstatic    struct    pte *usrptmap, *usrpt;
  633. X#ifdef hp800
  634. Xstatic    int    ubase;
  635. X#endif
  636. X
  637. X#define    NPROCS    32            /* number of procs to read at once */
  638. X
  639. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  640. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  641. X
  642. Xextern    off_t lseek();
  643. X
  644. X/*
  645. X * GetProc()
  646. X *
  647. X * Fill in and return a `struct ProcInfo' with information about the
  648. X * next process.  If no processes are left, return NULL.
  649. X *
  650. X * Fflag support:
  651. X *    If Fflag is set we will try to avoid reading in the user struct.
  652. X *    We can do this only if Iflag, TtyIndx, and CmdIndx are zero.
  653. X */
  654. Xstruct ProcInfo *
  655. XGetProc()
  656. X{
  657. X    extern char *SysErr();
  658. X    static struct user *GetUser();
  659. X    static struct proc procs[NPROCS], *procsp;
  660. X    static struct ProcInfo procinfo;
  661. X    register struct user *auser;
  662. X    register struct proc *aproc;
  663. X    static int thisproc = 0;
  664. X    static int needuser = 1;        /* Fflag support */
  665. X
  666. X    /*
  667. X     * If this is our first time here, open various files,
  668. X     * and set up the nlist.
  669. X     */
  670. X    if (nproc == -1) {
  671. X        char *errstr = "%s: %s: %s\n";
  672. X        int nfound;
  673. X
  674. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  675. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  676. X            exit(EX_SERR);
  677. X        }
  678. X
  679. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  680. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  681. X            exit(EX_SERR);
  682. X        }
  683. X
  684. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  685. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  686. X            exit(EX_SERR);
  687. X        }
  688. X
  689. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  690. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  691. X            exit(EX_SERR);
  692. X        }
  693. X        if (nfound != 0) {
  694. X            register int i;
  695. X
  696. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  697. X                    ProgName);
  698. X            for (i = 0; i < X_LAST; i++)
  699. X                if (nl[i].n_type == 0)
  700. X                    fprintf(stderr, " %s", nl[i].n_name);
  701. X            (void) putc('\n', stderr);
  702. X            exit(EX_SERR);
  703. X        }
  704. X
  705. X        usrpt = (struct pte *) nl[X_USRPT].n_value;
  706. X        usrptmap = (struct pte *) nl[X_USRPTMAP].n_value;
  707. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  708. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  709. X#ifdef hp800
  710. X        ubase = nl[X_UBASE].n_value;
  711. X#endif
  712. X        /*
  713. X         * We run much faster without reading in the user struct;
  714. X         * the price is incomplete information for errors (no cmd).
  715. X         */
  716. X        if (Fflag && Iflag == 0 && TtyIndx == 0 && CmdIndx == 0)
  717. X            needuser = 0;
  718. X    }
  719. X
  720. X    /*
  721. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  722. X     * by the number of proc structures we have read; when it reaches
  723. X     * zero, we are finished (return NULL).
  724. X     */
  725. X    do {
  726. X        while (thisproc == 0) {
  727. X            int nread;
  728. X            int psize;
  729. X
  730. X            if (nproc == 0)
  731. X                return((struct ProcInfo *)NULL);
  732. X
  733. X            thisproc = MIN(NPROCS, nproc);
  734. X            psize = thisproc * sizeof(struct proc);
  735. X            nproc -= thisproc;
  736. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  737. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  738. X                fprintf(stderr, "%s: read proc: %s\n",
  739. X                        ProgName, SysErr());
  740. X                return((struct ProcInfo *)NULL);
  741. X            } else if (nread != psize) {
  742. X                thisproc = nread / sizeof(struct proc);
  743. X                nproc = 0;
  744. X                fprintf(stderr, "%s: read proc: short read\n",
  745. X                        ProgName);
  746. X            }
  747. X            procsp = procs;
  748. X            procp += thisproc;
  749. X        }
  750. X
  751. X        aproc = procsp++;
  752. X        thisproc--;
  753. X
  754. X        if (aproc->p_stat != 0) {
  755. X            /*
  756. X             * Before we go through the trouble of reading
  757. X             * in the user struct, let's make sure this isn't
  758. X             * a "zombie" or "exiting" process.  If it is,
  759. X             * we have all the information we need; fill in
  760. X             * procinfo and return.
  761. X             */
  762. X            procinfo.pi_flags = 0;
  763. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  764. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  765. X
  766. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  767. X                static char *zombie = "<defunct>";
  768. X                procinfo.pi_flags |= PI_ZOMBIE;
  769. X                procinfo.pi_cmd = zombie;
  770. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  771. X                static char *exiting = "<exiting>";
  772. X                procinfo.pi_flags |= PI_SWEXIT;
  773. X                procinfo.pi_cmd = exiting;
  774. X            } else if (!needuser) {            /* Fflag */
  775. X                static char *fflagcmd = "<-f>";
  776. X                procinfo.pi_cmd = fflagcmd;
  777. X            }
  778. X
  779. X            if (procinfo.pi_flags || !needuser)
  780. X                return(&procinfo);
  781. X            else
  782. X                auser = GetUser(aproc);
  783. X        }
  784. X
  785. X    } while (aproc->p_stat == 0 || auser == NULL);
  786. X
  787. X    /*
  788. X     * We now have a process (`aproc') and a user (`auser').
  789. X     * Fill in the rest of `procinfo'.
  790. X     */
  791. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  792. X        procinfo.pi_flags |= PI_CTLTTY;
  793. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  794. X    }
  795. X
  796. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  797. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  798. X        procinfo.pi_flags |= PI_ASKUSR;
  799. X    } else                 /* set path-stripped command name */
  800. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  801. X
  802. X    return(&procinfo);
  803. X}
  804. X
  805. X#define    SKRD(file, src, dst, size)            \
  806. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  807. X    (read(file, (char *)(dst), (size)) != (size))
  808. X
  809. X/*
  810. X * GetWord(loc)
  811. X *
  812. X * Read in word at `loc' from kernel virtual memory.
  813. X * If an error occurs, call exit(2) with EX_SERR.
  814. X */
  815. Xstatic int
  816. XGetWord(loc)
  817. X    off_t loc;
  818. X{
  819. X    int val;
  820. X
  821. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  822. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  823. X                ProgName, (u_long)loc, kmemf);
  824. X        exit(EX_SERR);
  825. X    }
  826. X    return (val);
  827. X}
  828. X
  829. X#ifndef    CLBYTES
  830. X#define    CLBYTES    (CLSIZE*NBPG)
  831. X#endif
  832. X
  833. X/*
  834. X * GetUser(aproc)
  835. X *
  836. X * Read in the user struct for `aproc' and return a pointer to it.
  837. X * If an error occurs, return NULL.
  838. X */
  839. X#ifndef hp800
  840. X
  841. X#define    SW_UADDR    dtob(aproc->p_swaddr)
  842. X#define    SW_UBYTES    sizeof(struct user)
  843. X
  844. Xstatic struct user *
  845. XGetUser(aproc)
  846. X    struct proc *aproc;
  847. X{
  848. X    static char *WarnMsg = "Warning: can't read ";
  849. X    static union {
  850. X        struct user user;
  851. X        char upgs[UPAGES][NBPG];
  852. X    } u;
  853. X    static struct pte apte, uptes[HIGHPAGES+CLSIZE];
  854. X    register int ncl, i;
  855. X
  856. X    /*
  857. X     * If process is not in core, we simply snarf it's user struct
  858. X     * from the swap device.
  859. X     */
  860. X    if ((aproc->p_flag & SLOAD) == 0) {
  861. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  862. X            if (Wflag)
  863. X                printf("%su for pid %d from %s\n",
  864. X                       WarnMsg, aproc->p_pid, swapf);
  865. X            return ((struct user *)NULL);
  866. X        }
  867. X        return (&u.user);
  868. X    }
  869. X
  870. X    /*
  871. X     * Process is in core.  First read from the user page-table
  872. X     * map for this process to get the u-area page table entry.
  873. X     * Next, read in the page table entries that map the u-area.
  874. X     * Finally, read in the physical pages that comprise the u-area.
  875. X     *
  876. X     * If at any time, an lseek() or read() fails, print a warning
  877. X     * message (if `Wflag' is set) and return NULL.
  878. X     */
  879. X    if (SKRD(kmem, &usrptmap[btokmx(aproc->p_p0br) + aproc->p_szpt - 1],
  880. X             &apte, sizeof(apte))) {
  881. X        if (Wflag)
  882. X            printf("%sindir pte of user pt for pid %d from %s\n",
  883. X                   WarnMsg, aproc->p_pid, kmemf);
  884. X        return ((struct user *)NULL);
  885. X    }
  886. X
  887. X    if (SKRD(mem, ctob(apte.pg_pfnum+1) - sizeof(uptes),
  888. X             uptes, sizeof(uptes))) {
  889. X        if (Wflag)
  890. X            printf("%suser pt for pid %d from %s\n",
  891. X                   WarnMsg, aproc->p_pid, memf);
  892. X        return ((struct user *)NULL);
  893. X    }
  894. X
  895. X    /*
  896. X     * Set `ncl' to the (rounded up) number of u-area page clusters
  897. X     * to read, and then read in this user struct (in reverse).
  898. X     */
  899. X    ncl = (sizeof(struct user) + CLBYTES - 1) / CLBYTES;
  900. X    while (--ncl >= 0) {
  901. X        i = ncl * CLSIZE;
  902. X        if (SKRD(mem,ctob(uptes[CLSIZE+i].pg_pfnum),u.upgs[i],CLBYTES)){
  903. X            if (Wflag)
  904. X                printf("%suser page %u for pid %d from %s\n",
  905. X                       WarnMsg, uptes[CLSIZE+i].pg_pfnum,
  906. X                       aproc->p_pid, memf);
  907. X            return((struct user *)NULL);
  908. X        }
  909. X    }
  910. X    return (&u.user);
  911. X}
  912. X#else    /* hp800 and Inverted Page Tables */
  913. X
  914. X#undef    pindx
  915. X#define    pindx(p)    ((p)->p_ndx)
  916. X
  917. X#define    SW_UADDR    dtob(aproc->p_swaddr + ctod(btoc(KSTAKSIZE*CLBYTES)))
  918. X#define    SW_UBYTES    sizeof(struct user)
  919. X
  920. Xstatic struct user *
  921. XGetUser(aproc)
  922. X    struct proc *aproc;
  923. X{
  924. X    static char *WarnMsg = "Warning: can't read ";
  925. X    static union {
  926. X        struct user user;
  927. X        char upgs[UPAGES][NBPG];
  928. X    } u;
  929. X
  930. X    /*
  931. X     * If process is not in core, we simply snarf it's user struct
  932. X     * from the swap device.
  933. X     */
  934. X    if ((aproc->p_flag & SLOAD) == 0) {
  935. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  936. X            if (Wflag)
  937. X                printf("%su for pid %d from %s\n",
  938. X                       WarnMsg, aproc->p_pid, swapf);
  939. X            return ((struct user *)NULL);
  940. X        }
  941. X        return (&u.user);
  942. X    }
  943. X
  944. X    /*
  945. X     * Process is in core.
  946. X     *
  947. X     * User struct is not mapped into user space,
  948. X     * must be read from kernel VA space.
  949. X     */
  950. X    if (SKRD(kmem, uvadd(aproc), &u.user, sizeof(struct user))) {
  951. X        if (Wflag)
  952. X            printf("%su for pid %d from %s\n",
  953. X                   WarnMsg, aproc->p_pid, kmemf);
  954. X        return ((struct user *)NULL);
  955. X    }
  956. X
  957. X    return (&u.user);
  958. X}
  959. X#endif
  960. END_OF_FILE
  961. if test 12470 -ne `wc -c <'machdep/bsd-43.c'`; then
  962.     echo shar: \"'machdep/bsd-43.c'\" unpacked with wrong size!
  963. fi
  964. # end of 'machdep/bsd-43.c'
  965. fi
  966. if test -f 'machdep/irix-3.c' -a "${1}" != "-c" ; then 
  967.   echo shar: Will not clobber existing file \"'machdep/irix-3.c'\"
  968. else
  969. echo shar: Extracting \"'machdep/irix-3.c'\" \(12967 characters\)
  970. sed "s/^X//" >'machdep/irix-3.c' <<'END_OF_FILE'
  971. X#ifndef lint
  972. Xstatic char rcsid[] = "$Header: irix-3.c,v 1.8 1994/06/26 04:16:15 forys Exp $";
  973. X#endif
  974. X
  975. X/*
  976. X**  This program may be freely redistributed for noncommercial purposes.
  977. X**  This entire comment MUST remain intact.
  978. X**
  979. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  980. X*/
  981. X
  982. X#define    NO_MEXTERN
  983. X#include "conf.h"
  984. X#undef    NO_MEXTERN
  985. X
  986. X#include <sys/dir.h>
  987. X#include <sys/user.h>
  988. X#include <sys/proc.h>
  989. X
  990. X#include <stdio.h>
  991. X
  992. X/*
  993. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  994. X * routines and must be global.  Everyone seems to have their own
  995. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  996. X * signals available, not counting zero.
  997. X */
  998. Xchar *SigMap[] = { "0",
  999. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  1000. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  1001. X    "PIPE", "ALRM", "TERM", "USR1", "USR2", "CHLD",        /* 13 - 18 */
  1002. X    "PWR", "STOP", "TSTP", "POLL", "IO", "URG",        /* 19 - 24 */
  1003. X    "WINCH", "VTALRM", "PROF", "CONT", "TTIN", "TTOU",    /* 25 - 30 */
  1004. X    "XCPU", "XFSZ",                        /* 31 - 32 */
  1005. X};
  1006. Xint NSig = NUMSIGS;
  1007. X
  1008. X#define    SETCMD(dst,src,maxlen) {            \
  1009. X    extern char *rindex();                \
  1010. X    if (maxlen > 0) src[maxlen] = '\0';        \
  1011. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  1012. X}
  1013. X
  1014. Xstatic char *TtyDevDir = "/dev";
  1015. X
  1016. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  1017. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  1018. Xint    SigPri;            /* signal to send or priority to set */
  1019. Xpid_T    MyPid;            /* pid of this process */
  1020. Xuid_T    MyUid;            /* uid of this process */
  1021. Xchar    *ProgName;        /* program name */
  1022. X
  1023. X/*
  1024. X * This is the machine-dependent initialization routine.
  1025. X *
  1026. X *   - The following global variables must be initialized:
  1027. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  1028. X *   - The working directory will be changed to that which contains the
  1029. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  1030. X *   - If possible, this routine should raise the priority of this process.
  1031. X */
  1032. Xvoid
  1033. XMdepInit(pname)
  1034. X    char *pname;
  1035. X{
  1036. X    extern char *rindex(), *SysErr();
  1037. X
  1038. X    MyPid = (pid_T) getpid();
  1039. X    MyUid = (uid_T) getuid();
  1040. X    SETCMD(ProgName, pname, 0)
  1041. X
  1042. X    /*
  1043. X     * If we are running as root, raise our priority to better
  1044. X     * catch runaway processes.
  1045. X     */
  1046. X    if (MyUid == ROOTUID)
  1047. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  1048. X
  1049. X    /*
  1050. X     * Determine what we are doing to processes we find.  We will
  1051. X     * either send them a signal (skill), or renice them (snice).
  1052. X     */
  1053. X    Skill = (strcmp(ProgName, "snice") != 0);
  1054. X
  1055. X    /*
  1056. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  1057. X     */
  1058. X    if (chdir(TtyDevDir) < 0) {
  1059. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  1060. X                SysErr());
  1061. X        exit(EX_SERR);
  1062. X    }
  1063. X
  1064. X    /*
  1065. X     * Set up minimum and maximum process priorities.
  1066. X     * Initialize SigPri to either default signal (`skill') or
  1067. X     * default priority (`snice').
  1068. X     */
  1069. X    PrioMin = PRIO_MIN;
  1070. X    PrioMax = PRIO_MAX;
  1071. X    SigPri = Skill? SIGTERM: 4;
  1072. X}
  1073. X
  1074. X/*
  1075. X * Carry out an action on a particular process.  If this is `skill',
  1076. X * then send the process a signal, otherwise this is `snice' so change
  1077. X * it's priority.
  1078. X *
  1079. X * If 0 is returned, the operation was successful, otherwise -1 is
  1080. X * returned and `errno' set.
  1081. X */
  1082. Xint
  1083. XMdepAction(pid)
  1084. X    pid_T pid;
  1085. X{
  1086. X    if (Skill)
  1087. X        return(kill((int)pid, SigPri));
  1088. X    else
  1089. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  1090. X}
  1091. X
  1092. X/*
  1093. X * Now, set up everything we need to write a GetProc() routine.
  1094. X */
  1095. X
  1096. X#include <sys/immu.h>
  1097. X#include <sys/swap.h>
  1098. X#include <sys/file.h>
  1099. X#include <sys/stat.h>
  1100. X#include <sys/sysmacros.h>
  1101. X
  1102. X#include <nlist.h>
  1103. X
  1104. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  1105. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  1106. Xstatic char *kernf =    "/unix";    /* kernel image */
  1107. Xstatic char *devdskf =    "/dev/dsk";    /* where swap devices can be found */
  1108. Xstatic int kmem = 0, mem = 0;
  1109. X
  1110. Xstatic struct nlist nl[] = {
  1111. X    { "v" },
  1112. X#define    X_VAR        0
  1113. X    { "proc" },
  1114. X#define    X_PROC        1
  1115. X    { "swaptab" },
  1116. X#define    X_SWAPTAB    2
  1117. X    { "" },
  1118. X#define    X_LAST        3
  1119. X};
  1120. X
  1121. Xstatic    int    nproc = -1;
  1122. Xstatic    struct    proc *procp;
  1123. Xstatic    swpt_t    swtab[MSFILES];        /* available swap devices */
  1124. Xstatic    dev_t    swdev[MSFILES];        /* opened swap devices */
  1125. X
  1126. X#define    NPROCS    32            /* number of procs to read at once */
  1127. X
  1128. Xstatic    char    *pidmap[] = { "sched", "init", "vhand", "bdflush" };
  1129. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  1130. X
  1131. Xextern    off_t lseek();
  1132. X
  1133. X/*
  1134. X * GetProc()
  1135. X *
  1136. X * Fill in and return a `struct ProcInfo' with information about the
  1137. X * next process.  If no processes are left, return NULL.
  1138. X *
  1139. X * Fflag support:
  1140. X *      If Fflag is set we will try to avoid reading in the user struct
  1141. X *    and locating/opening the swap device(s).
  1142. X *      We can do this only if Iflag, TtyIndx, and CmdIndx are zero.
  1143. X */
  1144. Xstruct ProcInfo *
  1145. XGetProc()
  1146. X{
  1147. X    extern char *SysErr();
  1148. X    static struct user *GetUser();
  1149. X    static struct proc procs[NPROCS], *procsp;
  1150. X    static struct ProcInfo procinfo;
  1151. X    static struct var var;
  1152. X    register struct user *auser;
  1153. X    register struct proc *aproc;
  1154. X    static int thisproc = 0;
  1155. X    static int needuser = 1;        /* Fflag support */
  1156. X
  1157. X    /*
  1158. X     * If this is our first time here, open various files,
  1159. X     * and set up the nlist.
  1160. X     */
  1161. X    if (nproc == -1) {
  1162. X        char *errstr = "%s: %s: %s\n";
  1163. X        int nfound;
  1164. X
  1165. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  1166. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  1167. X            exit(EX_SERR);
  1168. X        }
  1169. X
  1170. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  1171. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  1172. X            exit(EX_SERR);
  1173. X        }
  1174. X
  1175. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  1176. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  1177. X            exit(EX_SERR);
  1178. X        }
  1179. X
  1180. X        if (nfound != 0) {
  1181. X            register int i;
  1182. X
  1183. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  1184. X                    ProgName);
  1185. X            for (i = 0; i < X_LAST; i++)
  1186. X                if (nl[i].n_type == 0)
  1187. X                    fprintf(stderr, " %s", nl[i].n_name);
  1188. X            (void) putc('\n', stderr);
  1189. X            exit(EX_SERR);
  1190. X        }
  1191. X
  1192. X        GetStruct((off_t)svirtophys(nl[X_VAR].n_value), "var",
  1193. X                  (off_t)&var, sizeof(var));
  1194. X        GetStruct((off_t)svirtophys(nl[X_SWAPTAB].n_value), "swaptab",
  1195. X                  (off_t)swtab, sizeof(swtab));
  1196. X        procp = (struct proc *)svirtophys(nl[X_PROC].n_value);
  1197. X        nproc = var.v_proc;
  1198. X
  1199. X        /*
  1200. X         * We run faster without finding/opening the swap devices
  1201. X         * and reading in the user struct; the price is incomplete
  1202. X         * information for errors (no cmd).
  1203. X         */
  1204. X        if (Fflag && Iflag == 0 && TtyIndx == 0 && CmdIndx == 0)
  1205. X            needuser = 0;
  1206. X        else
  1207. X            OpenSwapDevs();
  1208. X    }
  1209. X
  1210. X    /*
  1211. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  1212. X     * by the number of proc structures we have read; when it reaches
  1213. X     * zero, we are finished (return NULL).
  1214. X     */
  1215. X    do {
  1216. X        while (thisproc == 0) {
  1217. X            int nread;
  1218. X            int psize;
  1219. X
  1220. X            if (nproc == 0)
  1221. X                return((struct ProcInfo *)NULL);
  1222. X
  1223. X            thisproc = MIN(NPROCS, nproc);
  1224. X            psize = thisproc * sizeof(struct proc);
  1225. X            nproc -= thisproc;
  1226. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  1227. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  1228. X                fprintf(stderr, "%s: read proc: %s\n",
  1229. X                        ProgName, SysErr());
  1230. X                return((struct ProcInfo *)NULL);
  1231. X            } else if (nread != psize) {
  1232. X                thisproc = nread / sizeof(struct proc);
  1233. X                nproc = 0;
  1234. X                fprintf(stderr, "%s: read proc: short read\n",
  1235. X                        ProgName);
  1236. X            }
  1237. X            procsp = procs;
  1238. X            procp += thisproc;
  1239. X        }
  1240. X
  1241. X        aproc = procsp++;
  1242. X        thisproc--;
  1243. X
  1244. X        if (aproc->p_stat != 0) {
  1245. X            /*
  1246. X             * Before we go through the trouble of reading
  1247. X             * in the user struct, let's make sure this isn't
  1248. X             * a "zombie" or "exiting" process.  If it is,
  1249. X             * we have all the information we need; fill in
  1250. X             * procinfo and return.
  1251. X             */
  1252. X            procinfo.pi_flags = 0;
  1253. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  1254. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  1255. X
  1256. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  1257. X                static char *zombie = "<defunct>";
  1258. X                procinfo.pi_flags |= PI_ZOMBIE;
  1259. X                procinfo.pi_cmd = zombie;
  1260. X            } else if (aproc->p_flag & SEXIT) {    /* exiting */
  1261. X                static char *exiting = "<exiting>";
  1262. X                procinfo.pi_flags |= PI_SWEXIT;
  1263. X                procinfo.pi_cmd = exiting;
  1264. X            } else if (!needuser) {            /* Fflag */
  1265. X                static char *fflagcmd = "<-f>";
  1266. X                procinfo.pi_cmd = fflagcmd;
  1267. X            }
  1268. X
  1269. X            if (procinfo.pi_flags || !needuser)
  1270. X                return(&procinfo);
  1271. X            else
  1272. X                auser = GetUser(aproc);
  1273. X        }
  1274. X
  1275. X    } while (aproc->p_stat == 0 || auser == NULL);
  1276. X
  1277. X    /*
  1278. X     * We now have a process (`aproc') and a user (`auser').
  1279. X     * Fill in the rest of `procinfo'.
  1280. X     */
  1281. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  1282. X        procinfo.pi_flags |= PI_CTLTTY;
  1283. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  1284. X    }
  1285. X
  1286. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  1287. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  1288. X        procinfo.pi_flags |= PI_ASKUSR;
  1289. X    } else                 /* set path-stripped command name */
  1290. X        SETCMD(procinfo.pi_cmd, auser->u_comm, PSCOMSIZ)
  1291. X
  1292. X    return(&procinfo);
  1293. X}
  1294. X
  1295. X#define    SKRD(file, src, dst, size)            \
  1296. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  1297. X    (read(file, (char *)(dst), (size)) != (size))
  1298. X
  1299. XGetStruct(loc, name, dest, size)
  1300. X    off_t loc;
  1301. X    char *name;
  1302. X    off_t dest;
  1303. X    int size;
  1304. X{
  1305. X    if (SKRD(kmem, loc, dest, size)) {
  1306. X        fprintf(stderr, "%s: can't read %s struct at %lx in %s\n",
  1307. X                ProgName, name, (u_long)loc, kmemf);
  1308. X        exit(EX_SERR);
  1309. X    }
  1310. X}
  1311. X
  1312. X/*
  1313. X * OpenSwapDevs()
  1314. X *
  1315. X * Locate and open all the swap devices currently configured.
  1316. X * The opened file descriptors are saved in `swdev[i]'.
  1317. X *
  1318. X * Side Effect: this routine does a chdir(devdskf).
  1319. X */
  1320. XOpenSwapDevs()
  1321. X{
  1322. X    extern char *SysErr();
  1323. X    struct stat statb;
  1324. X    register DIR *devdsk;
  1325. X    register struct direct *dp;
  1326. X    register char *flnm;
  1327. X    register int i, keeplooking = 1;
  1328. X
  1329. X    /*
  1330. X     * Initialize all file descriptors to "unopened".
  1331. X     */
  1332. X    for (i = 0; i < MSFILES; i++)
  1333. X        swdev[i] = -1;
  1334. X
  1335. X    /*
  1336. X     * Relocate our current working directory to `devdskf' and open
  1337. X     * the directory for reading it's contents.
  1338. X     */
  1339. X    if (chdir(devdskf) < 0) {
  1340. X        fprintf(stderr, "%s: can't change dir to %s: %s\n",
  1341. X                ProgName, devdskf, SysErr());
  1342. X        return;
  1343. X    }
  1344. X    if ((devdsk = opendir(".")) == NULL) {
  1345. X        fprintf(stderr, "%s: can't open %s: %s\n",
  1346. X                    ProgName, devdskf, SysErr());
  1347. X        return;
  1348. X    }
  1349. X
  1350. X    /*
  1351. X     * For each directory entry, if it is one of our swap devices,
  1352. X     * try to open it.
  1353. X     */
  1354. X    while ((dp = readdir(devdsk)) != NULL && keeplooking) {
  1355. X        flnm = dp->d_name;
  1356. X        if (stat(flnm, &statb) < 0)    /* who knows, who cares... */
  1357. X            continue;
  1358. X        keeplooking = 0;
  1359. X        for (i = 0; i < MSFILES; i++) {
  1360. X            if (swdev[i] < 0 && S_ISBLK(statb.st_mode) &&
  1361. X                swtab[i].st_dev == statb.st_rdev)
  1362. X                if ((swdev[i] = open(flnm, 0)) < 0)
  1363. X                    fprintf(stderr,
  1364. X                            "%s: can't open %s/%s: %s\n",
  1365. X                            ProgName,devdskf,flnm,SysErr());
  1366. X
  1367. X            if (swtab[i].st_dev && swdev[i] < 0)
  1368. X                keeplooking = 1;
  1369. X        }
  1370. X    }
  1371. X
  1372. X    /*
  1373. X     * Lastly, see if there were any swap devices we could not locate.
  1374. X     */
  1375. X    if (keeplooking) {
  1376. X        for (i = 0; i < MSFILES; i++)
  1377. X            if (swtab[i].st_dev && swdev[i] < 0)
  1378. X                fprintf(stderr,
  1379. X                "%s: can't open swap device %d,%d\n", ProgName,
  1380. X                major(swtab[i].st_dev), minor(swtab[i].st_dev));
  1381. X    }
  1382. X    closedir(devdsk);
  1383. X}
  1384. X
  1385. X/*
  1386. X * GetUser(aproc)
  1387. X *
  1388. X * Read in the user struct for `aproc' and return a pointer to it.
  1389. X * If an error occurs, return NULL.
  1390. X */
  1391. Xstatic struct user *
  1392. XGetUser(aproc)
  1393. X    struct proc *aproc;
  1394. X{
  1395. X    static char *WarnMsg = "Warning: can't read ";
  1396. X    static union {
  1397. X        struct user user;
  1398. X        char upgs[USIZE][NBPP];
  1399. X    } u;
  1400. X    register int i, pgtype, file, swapi;
  1401. X    register u_int addr;
  1402. X    register char *flnm;
  1403. X
  1404. X    /*
  1405. X     * aproc->p_upgs has the pdes for the u-area.  Also, encoded into
  1406. X     * the pde is the key to the location of these pages.  If the disk
  1407. X     * block descriptor is of type DBD_NONE, then the pages are in
  1408. X     * core.  If they are of type DBD_SWAP they are out on swap device
  1409. X     * number `dbd_swpi' at logical block number `dbd_pgno'.  This is
  1410. X     * actually pretty cool, except that each swap partition must be
  1411. X     * treated separately (so we had to open all of them).
  1412. X     *
  1413. X     * If at any time, an lseek() or read() fails, print a warning
  1414. X     * message (if `Wflag' is set) and return NULL.
  1415. X     */
  1416. X    for (i = 0; i < USIZE; i++) {
  1417. X        pgtype = pdetodbd(&aproc->p_upgs[i])->dbd_type;
  1418. X        switch (pgtype) {
  1419. X            case DBD_NONE:    /* in core */
  1420. X            addr = aproc->p_upgs[i].pgm.pg_pfn*NBPP;
  1421. X            file = mem;
  1422. X            flnm = memf;
  1423. X            break;
  1424. X            case DBD_SWAP:    /* swapped out */
  1425. X            /*
  1426. X             * I assume that it's necessary to add in `st_swplo'
  1427. X             * in case our logical swap partition starts at a
  1428. X             * block offset other than zero.  The include files
  1429. X             * werent clear on this, so I guessed.  ..jef
  1430. X             */
  1431. X            swapi = aproc->p_upgs[i].pgm.dbd.dbd_swpi;
  1432. X            addr = BBTOB(aproc->p_upgs[i].pgm.dbd.dbd_pgno +
  1433. X                         swtab[swapi].st_swplo);
  1434. X            file = swdev[swapi];
  1435. X            flnm = "swap";
  1436. X            break;
  1437. X            default:        /* other (impossible?) things */
  1438. X            if (Wflag)
  1439. X                printf("%suser page of type %d for pid %d\n",
  1440. X                       WarnMsg, pgtype, aproc->p_pid);
  1441. X            return((struct user *)NULL);
  1442. X        }
  1443. X        if (SKRD(file, addr, u.upgs[i], NBPP)) {
  1444. X            if (Wflag)
  1445. X                printf("%suser page %u for pid %d from %s\n",
  1446. X                       WarnMsg, addr/NBPP, aproc->p_pid, flnm);
  1447. X            return((struct user *)NULL);
  1448. X        }
  1449. X    }
  1450. X    return (&u.user);
  1451. X}
  1452. END_OF_FILE
  1453. if test 12967 -ne `wc -c <'machdep/irix-3.c'`; then
  1454.     echo shar: \"'machdep/irix-3.c'\" unpacked with wrong size!
  1455. fi
  1456. # end of 'machdep/irix-3.c'
  1457. fi
  1458. if test -f 'machdep/irix-4.c' -a "${1}" != "-c" ; then 
  1459.   echo shar: Will not clobber existing file \"'machdep/irix-4.c'\"
  1460. else
  1461. echo shar: Extracting \"'machdep/irix-4.c'\" \(12975 characters\)
  1462. sed "s/^X//" >'machdep/irix-4.c' <<'END_OF_FILE'
  1463. X#ifndef lint
  1464. Xstatic char rcsid[] = "$Header: irix-4.c,v 1.6 1994/06/26 04:18:31 forys Exp $";
  1465. X#endif
  1466. X
  1467. X/*
  1468. X**  This program may be freely redistributed for noncommercial purposes.
  1469. X**  This entire comment MUST remain intact.
  1470. X**
  1471. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  1472. X*/
  1473. X
  1474. X#define    NO_MEXTERN
  1475. X#include "conf.h"
  1476. X#undef    NO_MEXTERN
  1477. X
  1478. X#include <sys/dir.h>
  1479. X#include <sys/user.h>
  1480. X#include <sys/proc.h>
  1481. X
  1482. X#include <stdio.h>
  1483. X
  1484. X/*
  1485. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  1486. X * routines and must be global.  Everyone seems to have their own
  1487. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  1488. X * signals available, not counting zero.
  1489. X */
  1490. Xchar *SigMap[] = { "0",
  1491. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  1492. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  1493. X    "PIPE", "ALRM", "TERM", "USR1", "USR2", "CHLD",        /* 13 - 18 */
  1494. X    "PWR", "STOP", "TSTP", "POLL", "IO", "URG",        /* 19 - 24 */
  1495. X    "WINCH", "VTALRM", "PROF", "CONT", "TTIN", "TTOU",    /* 25 - 30 */
  1496. X    "XCPU", "XFSZ",                        /* 31 - 32 */
  1497. X};
  1498. Xint NSig = NUMSIGS;
  1499. X
  1500. X#define    SETCMD(dst,src,maxlen) {            \
  1501. X    extern char *rindex();                \
  1502. X    if (maxlen > 0) src[maxlen] = '\0';        \
  1503. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  1504. X}
  1505. X
  1506. Xstatic char *TtyDevDir = "/dev";
  1507. X
  1508. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  1509. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  1510. Xint    SigPri;            /* signal to send or priority to set */
  1511. Xpid_T    MyPid;            /* pid of this process */
  1512. Xuid_T    MyUid;            /* uid of this process */
  1513. Xchar    *ProgName;        /* program name */
  1514. X
  1515. X/*
  1516. X * This is the machine-dependent initialization routine.
  1517. X *
  1518. X *   - The following global variables must be initialized:
  1519. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  1520. X *   - The working directory will be changed to that which contains the
  1521. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  1522. X *   - If possible, this routine should raise the priority of this process.
  1523. X */
  1524. Xvoid
  1525. XMdepInit(pname)
  1526. X    char *pname;
  1527. X{
  1528. X    extern char *rindex(), *SysErr();
  1529. X
  1530. X    MyPid = (pid_T) getpid();
  1531. X    MyUid = (uid_T) getuid();
  1532. X    SETCMD(ProgName, pname, 0)
  1533. X
  1534. X    /*
  1535. X     * If we are running as root, raise our priority to better
  1536. X     * catch runaway processes.
  1537. X     */
  1538. X    if (MyUid == ROOTUID)
  1539. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  1540. X
  1541. X    /*
  1542. X     * Determine what we are doing to processes we find.  We will
  1543. X     * either send them a signal (skill), or renice them (snice).
  1544. X     */
  1545. X    Skill = (strcmp(ProgName, "snice") != 0);
  1546. X
  1547. X    /*
  1548. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  1549. X     */
  1550. X    if (chdir(TtyDevDir) < 0) {
  1551. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  1552. X                SysErr());
  1553. X        exit(EX_SERR);
  1554. X    }
  1555. X
  1556. X    /*
  1557. X     * Set up minimum and maximum process priorities.
  1558. X     * Initialize SigPri to either default signal (`skill') or
  1559. X     * default priority (`snice').
  1560. X     */
  1561. X    PrioMin = PRIO_MIN;
  1562. X    PrioMax = PRIO_MAX;
  1563. X    SigPri = Skill? SIGTERM: 4;
  1564. X}
  1565. X
  1566. X/*
  1567. X * Carry out an action on a particular process.  If this is `skill',
  1568. X * then send the process a signal, otherwise this is `snice' so change
  1569. X * it's priority.
  1570. X *
  1571. X * If 0 is returned, the operation was successful, otherwise -1 is
  1572. X * returned and `errno' set.
  1573. X */
  1574. Xint
  1575. XMdepAction(pid)
  1576. X    pid_T pid;
  1577. X{
  1578. X    if (Skill)
  1579. X        return(kill((int)pid, SigPri));
  1580. X    else
  1581. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  1582. X}
  1583. X
  1584. X/*
  1585. X * Now, set up everything we need to write a GetProc() routine.
  1586. X */
  1587. X
  1588. X#include <sys/immu.h>
  1589. X#include <sys/swap.h>
  1590. X#include <sys/file.h>
  1591. X#include <sys/stat.h>
  1592. X#include <sys/sysmacros.h>
  1593. X
  1594. X#include <nlist.h>
  1595. X
  1596. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  1597. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  1598. Xstatic char *kernf =    "/unix";    /* kernel image */
  1599. Xstatic char *devdskf =    "/dev/dsk";    /* where swap devices can be found */
  1600. Xstatic int kmem = 0, mem = 0;
  1601. X
  1602. Xstatic struct nlist nl[] = {
  1603. X    { "v" },
  1604. X#define    X_VAR        0
  1605. X    { "proc" },
  1606. X#define    X_PROC        1
  1607. X    { "swaptab" },
  1608. X#define    X_SWAPTAB    2
  1609. X    { "" },
  1610. X#define    X_LAST        3
  1611. X};
  1612. X
  1613. Xstatic    int    nproc = -1;
  1614. Xstatic    struct    proc *procp;
  1615. Xstatic    swpt_t    swtab[MSFILES];        /* available swap devices */
  1616. Xstatic    dev_t    swdev[MSFILES];        /* opened swap devices */
  1617. X
  1618. X#define    NPROCS    32            /* number of procs to read at once */
  1619. X
  1620. Xstatic    char    *pidmap[] = { "sched", "init", "vhand", "bdflush" };
  1621. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  1622. X
  1623. Xextern    off_t lseek();
  1624. X
  1625. X/*
  1626. X * GetProc()
  1627. X *
  1628. X * Fill in and return a `struct ProcInfo' with information about the
  1629. X * next process.  If no processes are left, return NULL.
  1630. X *
  1631. X * Fflag support:
  1632. X *      If Fflag is set we will try to avoid reading in the user struct
  1633. X *    and locating/opening the swap device(s).
  1634. X *      We can do this only if Iflag, TtyIndx, and CmdIndx are zero.
  1635. X */
  1636. Xstruct ProcInfo *
  1637. XGetProc()
  1638. X{
  1639. X    extern char *SysErr();
  1640. X    static struct user *GetUser();
  1641. X    static struct proc procs[NPROCS], *procsp;
  1642. X    static struct ProcInfo procinfo;
  1643. X    static struct var var;
  1644. X    register struct user *auser;
  1645. X    register struct proc *aproc;
  1646. X    static int thisproc = 0;
  1647. X    static int needuser = 1;        /* Fflag support */
  1648. X
  1649. X    /*
  1650. X     * If this is our first time here, open various files,
  1651. X     * and set up the nlist.
  1652. X     */
  1653. X    if (nproc == -1) {
  1654. X        char *errstr = "%s: %s: %s\n";
  1655. X        int nfound;
  1656. X
  1657. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  1658. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  1659. X            exit(EX_SERR);
  1660. X        }
  1661. X
  1662. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  1663. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  1664. X            exit(EX_SERR);
  1665. X        }
  1666. X
  1667. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  1668. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  1669. X            exit(EX_SERR);
  1670. X        }
  1671. X
  1672. X        if (nfound != 0) {
  1673. X            register int i;
  1674. X
  1675. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  1676. X                    ProgName);
  1677. X            for (i = 0; i < X_LAST; i++)
  1678. X                if (nl[i].n_type == 0)
  1679. X                    fprintf(stderr, " %s", nl[i].n_name);
  1680. X            (void) putc('\n', stderr);
  1681. X            exit(EX_SERR);
  1682. X        }
  1683. X
  1684. X        GetStruct((off_t)svirtophys(nl[X_VAR].n_value), "var",
  1685. X                  (off_t)&var, sizeof(var));
  1686. X        GetStruct((off_t)svirtophys(nl[X_SWAPTAB].n_value), "swaptab",
  1687. X                  (off_t)swtab, sizeof(swtab));
  1688. X        procp = (struct proc *)svirtophys(nl[X_PROC].n_value);
  1689. X        nproc = var.v_proc;
  1690. X
  1691. X        /*
  1692. X         * We run faster without finding/opening the swap devices
  1693. X         * and reading in the user struct; the price is incomplete
  1694. X         * information for errors (no cmd).
  1695. X         */
  1696. X        if (Fflag && Iflag == 0 && TtyIndx == 0 && CmdIndx == 0)
  1697. X            needuser = 0;
  1698. X        else
  1699. X            OpenSwapDevs();
  1700. X    }
  1701. X
  1702. X    /*
  1703. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  1704. X     * by the number of proc structures we have read; when it reaches
  1705. X     * zero, we are finished (return NULL).
  1706. X     */
  1707. X    do {
  1708. X        while (thisproc == 0) {
  1709. X            int nread;
  1710. X            int psize;
  1711. X
  1712. X            if (nproc == 0)
  1713. X                return((struct ProcInfo *)NULL);
  1714. X
  1715. X            thisproc = MIN(NPROCS, nproc);
  1716. X            psize = thisproc * sizeof(struct proc);
  1717. X            nproc -= thisproc;
  1718. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  1719. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  1720. X                fprintf(stderr, "%s: read proc: %s\n",
  1721. X                        ProgName, SysErr());
  1722. X                return((struct ProcInfo *)NULL);
  1723. X            } else if (nread != psize) {
  1724. X                thisproc = nread / sizeof(struct proc);
  1725. X                nproc = 0;
  1726. X                fprintf(stderr, "%s: read proc: short read\n",
  1727. X                        ProgName);
  1728. X            }
  1729. X            procsp = procs;
  1730. X            procp += thisproc;
  1731. X        }
  1732. X
  1733. X        aproc = procsp++;
  1734. X        thisproc--;
  1735. X
  1736. X        if (aproc->p_stat != 0) {
  1737. X            /*
  1738. X             * Before we go through the trouble of reading
  1739. X             * in the user struct, let's make sure this isn't
  1740. X             * a "zombie" or "exiting" process.  If it is,
  1741. X             * we have all the information we need; fill in
  1742. X             * procinfo and return.
  1743. X             */
  1744. X            procinfo.pi_flags = 0;
  1745. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  1746. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  1747. X
  1748. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  1749. X                static char *zombie = "<defunct>";
  1750. X                procinfo.pi_flags |= PI_ZOMBIE;
  1751. X                procinfo.pi_cmd = zombie;
  1752. X            } else if (aproc->p_flag & SEXIT) {    /* exiting */
  1753. X                static char *exiting = "<exiting>";
  1754. X                procinfo.pi_flags |= PI_SWEXIT;
  1755. X                procinfo.pi_cmd = exiting;
  1756. X            } else if (!needuser) {            /* Fflag */
  1757. X                static char *fflagcmd = "<-f>";
  1758. X                procinfo.pi_cmd = fflagcmd;
  1759. X            }
  1760. X
  1761. X            if (procinfo.pi_flags || !needuser)
  1762. X                return(&procinfo);
  1763. X            else
  1764. X                auser = GetUser(aproc);
  1765. X        }
  1766. X
  1767. X    } while (aproc->p_stat == 0 || auser == NULL);
  1768. X
  1769. X    /*
  1770. X     * We now have a process (`aproc') and a user (`auser').
  1771. X     * Fill in the rest of `procinfo'.
  1772. X     */
  1773. X    if (auser->u_ttyd != (dev_t)-1) {    /* has a controlling tty */
  1774. X        procinfo.pi_flags |= PI_CTLTTY;
  1775. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  1776. X    }
  1777. X
  1778. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  1779. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  1780. X        procinfo.pi_flags |= PI_ASKUSR;
  1781. X    } else                 /* set path-stripped command name */
  1782. X        SETCMD(procinfo.pi_cmd, auser->u_comm, PSCOMSIZ)
  1783. X
  1784. X    return(&procinfo);
  1785. X}
  1786. X
  1787. X#define    SKRD(file, src, dst, size)            \
  1788. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  1789. X    (read(file, (char *)(dst), (size)) != (size))
  1790. X
  1791. XGetStruct(loc, name, dest, size)
  1792. X    off_t loc;
  1793. X    char *name;
  1794. X    off_t dest;
  1795. X    int size;
  1796. X{
  1797. X    if (SKRD(kmem, loc, dest, size)) {
  1798. X        fprintf(stderr, "%s: can't read %s struct at %lx in %s\n",
  1799. X                ProgName, name, (u_long)loc, kmemf);
  1800. X        exit(EX_SERR);
  1801. X    }
  1802. X}
  1803. X
  1804. X/*
  1805. X * OpenSwapDevs()
  1806. X *
  1807. X * Locate and open all the swap devices currently configured.
  1808. X * The opened file descriptors are saved in `swdev[i]'.
  1809. X *
  1810. X * Side Effect: this routine does a chdir(devdskf).
  1811. X */
  1812. XOpenSwapDevs()
  1813. X{
  1814. X    extern char *SysErr();
  1815. X    struct stat statb;
  1816. X    register DIR *devdsk;
  1817. X    register struct direct *dp;
  1818. X    register char *flnm;
  1819. X    register int i, keeplooking = 1;
  1820. X
  1821. X    /*
  1822. X     * Initialize all file descriptors to "unopened".
  1823. X     */
  1824. X    for (i = 0; i < MSFILES; i++)
  1825. X        swdev[i] = -1;
  1826. X
  1827. X    /*
  1828. X     * Relocate our current working directory to `devdskf' and open
  1829. X     * the directory for reading it's contents.
  1830. X     */
  1831. X    if (chdir(devdskf) < 0) {
  1832. X        fprintf(stderr, "%s: can't change dir to %s: %s\n",
  1833. X                ProgName, devdskf, SysErr());
  1834. X        return;
  1835. X    }
  1836. X    if ((devdsk = opendir(".")) == NULL) {
  1837. X        fprintf(stderr, "%s: can't open %s: %s\n",
  1838. X                    ProgName, devdskf, SysErr());
  1839. X        return;
  1840. X    }
  1841. X
  1842. X    /*
  1843. X     * For each directory entry, if it is one of our swap devices,
  1844. X     * try to open it.
  1845. X     */
  1846. X    while ((dp = readdir(devdsk)) != NULL && keeplooking) {
  1847. X        flnm = dp->d_name;
  1848. X        if (stat(flnm, &statb) < 0)    /* who knows, who cares... */
  1849. X            continue;
  1850. X        keeplooking = 0;
  1851. X        for (i = 0; i < MSFILES; i++) {
  1852. X            if (swdev[i] < 0 && S_ISBLK(statb.st_mode) &&
  1853. X                swtab[i].st_dev == statb.st_rdev)
  1854. X                if ((swdev[i] = open(flnm, 0)) < 0)
  1855. X                    fprintf(stderr,
  1856. X                            "%s: can't open %s/%s: %s\n",
  1857. X                            ProgName,devdskf,flnm,SysErr());
  1858. X
  1859. X            if (swtab[i].st_dev && swdev[i] < 0)
  1860. X                keeplooking = 1;
  1861. X        }
  1862. X    }
  1863. X
  1864. X    /*
  1865. X     * Lastly, see if there were any swap devices we could not locate.
  1866. X     */
  1867. X    if (keeplooking) {
  1868. X        for (i = 0; i < MSFILES; i++)
  1869. X            if (swtab[i].st_dev && swdev[i] < 0)
  1870. X                fprintf(stderr,
  1871. X                "%s: can't open swap device %d,%d\n", ProgName,
  1872. X                major(swtab[i].st_dev), minor(swtab[i].st_dev));
  1873. X    }
  1874. X    closedir(devdsk);
  1875. X}
  1876. X
  1877. X/*
  1878. X * GetUser(aproc)
  1879. X *
  1880. X * Read in the user struct for `aproc' and return a pointer to it.
  1881. X * If an error occurs, return NULL.
  1882. X */
  1883. Xstatic struct user *
  1884. XGetUser(aproc)
  1885. X    struct proc *aproc;
  1886. X{
  1887. X    static char *WarnMsg = "Warning: can't read ";
  1888. X    static union {
  1889. X        struct user user;
  1890. X        char upgs[USIZE][NBPP];
  1891. X    } u;
  1892. X    register int i, pgtype, file, swapi;
  1893. X    register u_int addr;
  1894. X    register char *flnm;
  1895. X
  1896. X    /*
  1897. X     * aproc->p_upgs has the pdes for the u-area.  Also, encoded into
  1898. X     * the pde is the key to the location of these pages.  If the disk
  1899. X     * block descriptor is of type DBD_NONE, then the pages are in
  1900. X     * core.  If they are of type DBD_SWAP they are out on swap device
  1901. X     * number `dbd_swpi' at logical block number `dbd_pgno'.  This is
  1902. X     * actually pretty cool, except that each swap partition must be
  1903. X     * treated separately (so we had to open all of them).
  1904. X     *
  1905. X     * If at any time, an lseek() or read() fails, print a warning
  1906. X     * message (if `Wflag' is set) and return NULL.
  1907. X     */
  1908. X    for (i = 0; i < USIZE; i++) {
  1909. X        pgtype = pdetodbd(&aproc->p_upgs[i])->dbd_type;
  1910. X        switch (pgtype) {
  1911. X            case DBD_NONE:    /* in core */
  1912. X            addr = aproc->p_upgs[i].pgm.pg_pfn*NBPP;
  1913. X            file = mem;
  1914. X            flnm = memf;
  1915. X            break;
  1916. X            case DBD_SWAP:    /* swapped out */
  1917. X            /*
  1918. X             * I assume that it's necessary to add in `st_swplo'
  1919. X             * in case our logical swap partition starts at a
  1920. X             * block offset other than zero.  The include files
  1921. X             * werent clear on this, so I guessed.  ..jef
  1922. X             */
  1923. X            swapi = aproc->p_upgs[i].pgm.dbd.dbd_swpi;
  1924. X            addr = BBTOB(aproc->p_upgs[i].pgm.dbd.dbd_pgno +
  1925. X                         swtab[swapi].st_swplo);
  1926. X            file = swdev[swapi];
  1927. X            flnm = "swap";
  1928. X            break;
  1929. X            default:        /* other (impossible?) things */
  1930. X            if (Wflag)
  1931. X                printf("%suser page of type %d for pid %d\n",
  1932. X                       WarnMsg, pgtype, aproc->p_pid);
  1933. X            return((struct user *)NULL);
  1934. X        }
  1935. X        if (SKRD(file, addr, u.upgs[i], NBPP)) {
  1936. X            if (Wflag)
  1937. X                printf("%suser page %u for pid %d from %s\n",
  1938. X                       WarnMsg, addr/NBPP, aproc->p_pid, flnm);
  1939. X            return((struct user *)NULL);
  1940. X        }
  1941. X    }
  1942. X    return (&u.user);
  1943. X}
  1944. END_OF_FILE
  1945. if test 12975 -ne `wc -c <'machdep/irix-4.c'`; then
  1946.     echo shar: \"'machdep/irix-4.c'\" unpacked with wrong size!
  1947. fi
  1948. # end of 'machdep/irix-4.c'
  1949. fi
  1950. if test -f 'machdep/ultrix-4.c' -a "${1}" != "-c" ; then 
  1951.   echo shar: Will not clobber existing file \"'machdep/ultrix-4.c'\"
  1952. else
  1953. echo shar: Extracting \"'machdep/ultrix-4.c'\" \(13985 characters\)
  1954. sed "s/^X//" >'machdep/ultrix-4.c' <<'END_OF_FILE'
  1955. X#ifndef lint
  1956. Xstatic char rcsid[] = "$Header: ultrix-4.c,v 1.6 1994/06/26 04:16:59 forys Exp $";
  1957. X#endif
  1958. X
  1959. X/*
  1960. X**  This program may be freely redistributed for noncommercial purposes.
  1961. X**  This entire comment MUST remain intact.
  1962. X**
  1963. X**  Ultrix 4 support by Ric Anderson (ric@cs.arizona.edu)
  1964. X**
  1965. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  1966. X*/
  1967. X
  1968. X#define    NO_MEXTERN
  1969. X#include "conf.h"
  1970. X#undef    NO_MEXTERN
  1971. X
  1972. X#include <sys/user.h>
  1973. X#include <sys/proc.h>
  1974. X
  1975. X#include <stdio.h>
  1976. X
  1977. X#define CRIT_PID    4  /* Query kills for pids .LE. this number */
  1978. X
  1979. X/*
  1980. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  1981. X * routines and must be global.  Everyone seems to have their own
  1982. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  1983. X * signals available, not counting zero.
  1984. X */
  1985. Xchar *SigMap[] = { "0",
  1986. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  1987. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  1988. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  1989. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  1990. X    "XFSZ", "VTALRM", "PROF", "WINCH", "LOST", "USR1",    /* 25 - 30 */
  1991. X    "USR2", "32",                        /* 31 - 32 */
  1992. X};
  1993. Xint NSig = NSIG;
  1994. X
  1995. X#define    SETCMD(dst,src,maxlen) {            \
  1996. X    extern char *rindex();                \
  1997. X    if (maxlen > 0) src[maxlen] = '\0';        \
  1998. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  1999. X}
  2000. X
  2001. Xstatic char *TtyDevDir = "/dev";
  2002. X
  2003. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  2004. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  2005. Xint    SigPri;            /* signal to send or priority to set */
  2006. Xpid_T    MyPid;            /* pid of this process */
  2007. Xuid_T    MyUid;            /* uid of this process */
  2008. Xchar    *ProgName;        /* program name */
  2009. X
  2010. X/*
  2011. X * This is the machine-dependent initialization routine.
  2012. X *
  2013. X *   - The following global variables must be initialized:
  2014. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  2015. X *   - The working directory will be changed to that which contains the
  2016. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  2017. X *   - If possible, this routine should raise the priority of this process.
  2018. X */
  2019. Xvoid
  2020. XMdepInit(pname)
  2021. X    char *pname;
  2022. X{
  2023. X    extern char *rindex(), *SysErr();
  2024. X
  2025. X    MyPid = (pid_T) getpid();
  2026. X    MyUid = (uid_T) getuid();
  2027. X    SETCMD(ProgName, pname, 0)
  2028. X
  2029. X    /*
  2030. X     * If we are running as root, raise our priority to better
  2031. X     * catch runaway processes.
  2032. X     */
  2033. X    if (MyUid == ROOTUID)
  2034. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  2035. X
  2036. X    /*
  2037. X     * Determine what we are doing to processes we find.  We will
  2038. X     * either send them a signal (skill), or renice them (snice).
  2039. X     */
  2040. X    Skill = (strcmp(ProgName, "snice") != 0);
  2041. X
  2042. X    /*
  2043. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  2044. X     */
  2045. X    if (chdir(TtyDevDir) < 0) {
  2046. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  2047. X                SysErr());
  2048. X        exit(EX_SERR);
  2049. X    }
  2050. X
  2051. X    /*
  2052. X     * Set up minimum and maximum process priorities.
  2053. X     * Initialize SigPri to either default signal (`skill') or
  2054. X     * default priority (`snice').
  2055. X     */
  2056. X    PrioMin = PRIO_MIN;
  2057. X    PrioMax = PRIO_MAX;
  2058. X    SigPri = Skill? SIGTERM: 4;
  2059. X}
  2060. X
  2061. X/*
  2062. X * Carry out an action on a particular process.  If this is `skill',
  2063. X * then send the process a signal, otherwise this is `snice' so change
  2064. X * it's priority.
  2065. X *
  2066. X * If 0 is returned, the operation was successful, otherwise -1 is
  2067. X * returned and `errno' set.
  2068. X */
  2069. Xint
  2070. XMdepAction(pid)
  2071. X    pid_T pid;
  2072. X{
  2073. X    if (Skill)
  2074. X        return(kill((int)pid, SigPri));
  2075. X    else
  2076. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  2077. X}
  2078. X
  2079. X/*
  2080. X * Now, set up everything we need to write a GetProc() routine.
  2081. X */
  2082. X
  2083. X#include <sys/tty.h>
  2084. X#include <sys/file.h>
  2085. X#include <sys/vm.h>
  2086. X
  2087. X#include <machine/pte.h>
  2088. X
  2089. X#include <nlist.h>
  2090. X
  2091. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  2092. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  2093. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  2094. Xstatic char *kernf =    "/vmunix";    /* kernel image */
  2095. Xstatic int kmem = 0, mem = 0, swap = 0;
  2096. X
  2097. Xstatic struct nlist nl[] = {
  2098. X    { "_nproc" },
  2099. X#define    X_NPROC        0
  2100. X    { "_proc" },
  2101. X#define    X_PROC        1
  2102. X    { "_proc_bitmap" },
  2103. X#define    X_PROC_BITMAP    2
  2104. X#ifdef vax
  2105. X    { "_Usrptmap" },
  2106. X#define    X_USRPTMAP    3
  2107. X    { "_usrpt" },
  2108. X#define    X_USRPT        4
  2109. X    { "" },
  2110. X#define    X_LAST        5
  2111. X#else
  2112. X    { "" },
  2113. X#define    X_LAST        3
  2114. X#endif
  2115. X};
  2116. X
  2117. Xstatic    int    nproc = -1;
  2118. Xstatic    int    absolute_proc_number = -1;
  2119. Xstatic    struct    proc *procp;
  2120. X#ifdef vax
  2121. Xstatic    struct    pte *usrptmap, *usrpt;
  2122. X#endif
  2123. X
  2124. X#define    NPROCS    32            /* number of procs to read at once */
  2125. X
  2126. Xextern    off_t lseek();
  2127. X
  2128. X/*
  2129. X * GetProc()
  2130. X *
  2131. X * Fill in and return a `struct ProcInfo' with information about the
  2132. X * next process.  If no processes are left, return NULL.
  2133. X */
  2134. Xstruct ProcInfo *
  2135. XGetProc()
  2136. X{
  2137. X    int proc_active;
  2138. X    extern char *SysErr();
  2139. X    static struct user *GetUser();
  2140. X    static unsigned bitmap;
  2141. X    static struct proc procs[NPROCS], *procsp;
  2142. X    static struct ProcInfo procinfo;
  2143. X    static struct tty tty;
  2144. X    register struct user *auser;
  2145. X    register struct proc *aproc;
  2146. X    static int thisproc = 0;
  2147. X
  2148. X    /*
  2149. X     * If this is our first time here, open various files,
  2150. X     * and set up the nlist.
  2151. X     */
  2152. X    if (nproc == -1) {
  2153. X        char *errstr = "%s: %s: %s\n";
  2154. X        int nfound;
  2155. X
  2156. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  2157. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  2158. X            exit(EX_SERR);
  2159. X        }
  2160. X
  2161. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  2162. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  2163. X            exit(EX_SERR);
  2164. X        }
  2165. X
  2166. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  2167. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  2168. X            exit(EX_SERR);
  2169. X        }
  2170. X
  2171. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  2172. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  2173. X            exit(EX_SERR);
  2174. X        }
  2175. X        if (nfound != 0) {
  2176. X            register int i;
  2177. X
  2178. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  2179. X                    ProgName);
  2180. X            for (i = 0; i < X_LAST; i++)
  2181. X                if (nl[i].n_type == 0)
  2182. X                    fprintf(stderr, " %s", nl[i].n_name);
  2183. X            (void) putc('\n', stderr);
  2184. X            exit(EX_SERR);
  2185. X        }
  2186. X
  2187. X#ifdef vax
  2188. X        usrpt = (struct pte *) nl[X_USRPT].n_value;
  2189. X        usrptmap = (struct pte *) nl[X_USRPTMAP].n_value;
  2190. X#endif
  2191. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  2192. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  2193. X    }
  2194. X
  2195. X    /*
  2196. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  2197. X     * by the number of proc structures we have read; when it reaches
  2198. X     * zero, we are finished (return NULL).
  2199. X     */
  2200. X    do {
  2201. X        while (thisproc == 0) {
  2202. X            int nread;
  2203. X            int psize;
  2204. X
  2205. X            if (nproc == 0)
  2206. X                return((struct ProcInfo *)NULL);
  2207. X
  2208. X            thisproc = MIN(NPROCS, nproc);
  2209. X            psize = thisproc * sizeof(struct proc);
  2210. X            nproc -= thisproc;
  2211. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  2212. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  2213. X                fprintf(stderr, "%s: read proc: %s\n",
  2214. X                        ProgName, SysErr());
  2215. X                return((struct ProcInfo *)NULL);
  2216. X            } else if (nread != psize) {
  2217. X                thisproc = nread / sizeof(struct proc);
  2218. X                nproc = 0;
  2219. X                fprintf(stderr, "%s: read proc: short read\n",
  2220. X                        ProgName);
  2221. X            }
  2222. X            procsp = procs;
  2223. X            procp += thisproc;
  2224. X        }
  2225. X
  2226. X        aproc = procsp++;
  2227. X        thisproc--;
  2228. X
  2229. X/*  Ultrix 4.x uses a bitmap to tell if a proc structure is    */
  2230. X/*  valid.  We read and check the bitmap.  The code here is    */
  2231. X/*  structured around 32 bits/entry, and 4 bytes/entry.        */
  2232. X
  2233. X        absolute_proc_number++;
  2234. X        if((absolute_proc_number % 32) == 0)
  2235. X            bitmap = GetWord((unsigned int)nl[X_PROC_BITMAP].n_value
  2236. X              + ((absolute_proc_number / 32) * 4));
  2237. X        proc_active = (bitmap & (1 << (absolute_proc_number % 32))) != 0;
  2238. X        if (proc_active) {
  2239. X            /*
  2240. X             * Before we go through the trouble of reading
  2241. X             * in the user struct, let's make sure this isn't
  2242. X             * a "zombie" or "exiting" process.  If it is,
  2243. X             * we have all the information we need; fill in
  2244. X             * procinfo and return.
  2245. X             */
  2246. X            procinfo.pi_flags = 0;
  2247. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  2248. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  2249. X
  2250. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  2251. X                static char *zombie = "<defunct>";
  2252. X                procinfo.pi_flags |= PI_ZOMBIE;
  2253. X                procinfo.pi_cmd = zombie;
  2254. X            } else if (aproc->p_type & SWEXIT) {    /* exiting */
  2255. X                static char *exiting = "<exiting>";
  2256. X                procinfo.pi_flags |= PI_SWEXIT;
  2257. X                procinfo.pi_cmd = exiting;
  2258. X            }
  2259. X
  2260. X            if (procinfo.pi_flags)
  2261. X                return(&procinfo);
  2262. X            else
  2263. X                auser = GetUser(aproc);
  2264. X        }
  2265. X
  2266. X    } while (!proc_active || auser == NULL);
  2267. X
  2268. X    /*
  2269. X     * We now have a process (`aproc') and a user (`auser').
  2270. X     * Fill in the rest of `procinfo'.
  2271. X     */
  2272. X    if (aproc->p_ttyp != 0 &&    /* has a controlling terminal? */
  2273. X        lseek(kmem, (off_t)aproc->p_ttyp, L_SET) != -1 &&
  2274. X        read(kmem, (char *)&tty, sizeof(tty)) == sizeof(tty)) {
  2275. X        procinfo.pi_flags |= PI_CTLTTY;
  2276. X        procinfo.pi_tty = (tty_T) tty.t_dev;
  2277. X    }
  2278. X
  2279. X    if (aproc->p_pid <= CRIT_PID)    /* special */
  2280. X        procinfo.pi_flags |= PI_ASKUSR;
  2281. X    SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  2282. X
  2283. X    return(&procinfo);
  2284. X}
  2285. X
  2286. X#define    SKRD(file, src, dst, size)            \
  2287. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  2288. X    (read(file, (char *)(dst), (size)) != (size))
  2289. X
  2290. X/*
  2291. X * GetStruct(loc,name,dest,size)
  2292. X *
  2293. X * Read in structure at `loc' from kernel virtual memory.
  2294. X * If an error occurs, return non-zero.
  2295. X */
  2296. X
  2297. Xstatic int
  2298. XGetStruct(loc,name,dest,size)
  2299. Xchar *name;
  2300. Xint size;
  2301. Xoff_t dest, loc;
  2302. X{
  2303. X    if(SKRD(kmem,loc,dest,size))
  2304. X        return(0);
  2305. X    return(1);
  2306. X}
  2307. X
  2308. X/*
  2309. X * GetWord(loc)
  2310. X *
  2311. X * Read in word at `loc' from kernel virtual memory.
  2312. X * If an error occurs, call exit(2) with EX_SERR.
  2313. X */
  2314. Xstatic int
  2315. XGetWord(loc)
  2316. X    off_t loc;
  2317. X{
  2318. X    int val;
  2319. X
  2320. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  2321. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  2322. X                ProgName, (u_long)loc, kmemf);
  2323. X        exit(EX_SERR);
  2324. X    }
  2325. X    return (val);
  2326. X}
  2327. X
  2328. X#ifdef mips
  2329. X#define    SW_UADDR    dtob(GetWord(dmap.dm_ptdaddr))
  2330. X#define    SW_UBYTES    sizeof(struct user)
  2331. X
  2332. X/*
  2333. X * GetUser(aproc)
  2334. X *
  2335. X * Read in the user struct for `aproc' and return a pointer to it.
  2336. X * If an error occurs, return NULL.
  2337. X */
  2338. Xstatic struct user *
  2339. XGetUser(aproc)
  2340. X    struct proc *aproc;
  2341. X{
  2342. X    static char *WarnMsg = "Warning: can't read ";
  2343. X    static union {
  2344. X        struct user user;
  2345. X        char upgs[UPAGES][NBPG];
  2346. X    } u;
  2347. X    static struct pte uptes[UPAGES];
  2348. X    static struct dmap dmap;
  2349. X    register int i, nbytes;
  2350. X
  2351. X    /*
  2352. X     * If process is not in core, we simply snarf it's user struct
  2353. X     * from the swap device.
  2354. X     */
  2355. X    if ((aproc->p_sched & SLOAD) == 0) {
  2356. X        if(!GetStruct((off_t)aproc->p_smap,"aproc->p_smap",
  2357. X          &dmap,sizeof(dmap))) {
  2358. X            if (Wflag)
  2359. X                printf("%s dmap for pid %d from %s\n",
  2360. X                       WarnMsg, aproc->p_pid, swapf);
  2361. X            return ((struct user *)NULL);
  2362. X        }
  2363. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  2364. X            if (Wflag)
  2365. X                printf("%su for pid %d from %s\n",
  2366. X                       WarnMsg, aproc->p_pid, swapf);
  2367. X            return ((struct user *)NULL);
  2368. X        }
  2369. X        return (&u.user);
  2370. X    }
  2371. X
  2372. X    /*
  2373. X     * Process is in core.  Follow p_addr to read in the page
  2374. X     * table entries that map the u-area and then read in the
  2375. X     * physical pages that comprise the u-area.
  2376. X     *
  2377. X     * If at any time, an lseek() or read() fails, print a warning
  2378. X     * message (if `Wflag' is set) and return NULL.
  2379. X     */
  2380. X    if (SKRD(kmem, aproc->p_addr, uptes, sizeof(uptes))) {
  2381. X        if (Wflag)
  2382. X            printf("%suser pt for pid %d from %s\n",
  2383. X                   WarnMsg, aproc->p_pid, kmemf);
  2384. X        return ((struct user *)NULL);
  2385. X    }
  2386. X
  2387. X    nbytes = sizeof(struct user);
  2388. X    for (i = 0; i < UPAGES && nbytes > 0; i++) {
  2389. X        if (SKRD(mem, ptob(uptes[i].pg_pfnum), u.upgs[i], NBPG)) {
  2390. X            if (Wflag)
  2391. X                printf("%suser page %u for pid %d from %s\n",
  2392. X                       WarnMsg, uptes[i].pg_pfnum,
  2393. X                       aproc->p_pid, memf);
  2394. X            return((struct user *)NULL);
  2395. X        }
  2396. X        nbytes -= NBPG;
  2397. X    }
  2398. X    return (&u.user);
  2399. X}
  2400. X#endif /* mips */
  2401. X
  2402. X#ifdef vax
  2403. X/****    The following code is uncompiled, and untested.  if you have
  2404. X *    an Ultrix 4.x vax to compile it on, please do so and send
  2405. X *    mods to jeff forys.
  2406. X */
  2407. X
  2408. X#define    SW_UADDR    dtob(GetWord(dmap.dm_ptdaddr))
  2409. X#define    SW_UBYTES    sizeof(struct user)
  2410. X
  2411. X/*
  2412. X * GetUser(aproc)
  2413. X *
  2414. X * Read in the user struct for `aproc' and return a pointer to it.
  2415. X * If an error occurs, return NULL.
  2416. X */
  2417. Xstatic struct user *
  2418. XGetUser(aproc)
  2419. X    struct proc *aproc;
  2420. X{
  2421. X    static char *WarnMsg = "Warning: can't read ";
  2422. X    static union {
  2423. X        struct user user;
  2424. X        char upgs[UPAGES][NBPG];
  2425. X    } u;
  2426. X    static struct pte apte, uptes[CLSIZE+HIGHPAGES];
  2427. X    static struct dmap dmap;
  2428. X    register int ncl, i, nbytes;
  2429. X
  2430. X    /*
  2431. X     * If process is not in core, we simply snarf it's user struct
  2432. X     * from the swap device.
  2433. X     */
  2434. X    if ((aproc->p_sched & SLOAD) == 0) {
  2435. X        if(!GetStruct((off_t)aproc->p_smap,"aproc->p_smap",
  2436. X          &dmap,sizeof(dmap))) {
  2437. X            if (Wflag)
  2438. X                printf("%s dmap for pid %d from %s\n",
  2439. X                       WarnMsg, aproc->p_pid, swapf);
  2440. X            return ((struct user *)NULL);
  2441. X        }
  2442. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  2443. X            if (Wflag)
  2444. X                printf("%su for pid %d from %s\n",
  2445. X                       WarnMsg, aproc->p_pid, swapf);
  2446. X            return ((struct user *)NULL);
  2447. X        }
  2448. X        return (&u.user);
  2449. X    }
  2450. X
  2451. X/* Process is in core.  First read from the user page-table    */
  2452. X/* map for this process to get the u-area page table entry.    */
  2453. X/* Next, read in the page table entries that map the u-area.    */
  2454. X/* Finally, read in the physical pages that comprise the    */
  2455. X/* u-area.                            */
  2456. X/*                                */
  2457. X/* If at any time, an lseek() or read() fails, print a warning    */
  2458. X/* message (if `Wflag' is set) and return NULL.            */
  2459. X
  2460. X    if (SKRD(kmem, &usrptmap[btokmx(aproc->p_p0br) + aproc->p_szpt - 1],
  2461. X             &apte, sizeof(apte))) {
  2462. X        if (Wflag)
  2463. X            printf("%sindir pte of user pt for pid %d from %s\n",
  2464. X              WarnMsg, aproc->p_pid, kmemf);
  2465. X        return ((struct user *)NULL);
  2466. X    }
  2467. X
  2468. X    if (SKRD(mem, ctob(apte.pg_pfnum+1) - sizeof(uptes),
  2469. X             uptes, sizeof(uptes))) {
  2470. X        if (Wflag)
  2471. X            printf("%suser pt for pid %d from %s\n",
  2472. X                   WarnMsg, aproc->p_pid, memf);
  2473. X        return ((struct user *)NULL);
  2474. X    }
  2475. X
  2476. X    /*
  2477. X     * Set `ncl' to the (rounded up) number of u-area page clusters
  2478. X     * to read, and then read in this user struct (in reverse).
  2479. X     */
  2480. X    ncl = (sizeof(struct user) + CLBYTES - 1) / CLBYTES;
  2481. X    while (--ncl >= 0) {
  2482. X        i = ncl * CLSIZE;
  2483. X        if (SKRD(mem,ctob(uptes[CLSIZE+i].pg_pfnum),u.upgs[i],CLBYTES)){
  2484. X            if (Wflag)
  2485. X                printf("%suser page %u for pid %d from %s\n",
  2486. X                       WarnMsg, uptes[CLSIZE+i].pg_pfnum,
  2487. X                       aproc->p_pid, memf);
  2488. X            return((struct user *)NULL);
  2489. X        }
  2490. X    }
  2491. X    return (&u.user);
  2492. X}
  2493. X#endif /* vax */
  2494. END_OF_FILE
  2495. if test 13985 -ne `wc -c <'machdep/ultrix-4.c'`; then
  2496.     echo shar: \"'machdep/ultrix-4.c'\" unpacked with wrong size!
  2497. fi
  2498. # end of 'machdep/ultrix-4.c'
  2499. fi
  2500. echo shar: End of archive 3 \(of 3\).
  2501. cp /dev/null ark3isdone
  2502. MISSING=""
  2503. for I in 1 2 3 ; do
  2504.     if test ! -f ark${I}isdone ; then
  2505.     MISSING="${MISSING} ${I}"
  2506.     fi
  2507. done
  2508. if test "${MISSING}" = "" ; then
  2509.     echo You have unpacked all 3 archives.
  2510.     rm -f ark[1-9]isdone
  2511. else
  2512.     echo You still need to unpack the following archives:
  2513.     echo "        " ${MISSING}
  2514. fi
  2515. ##  End of shell archive.
  2516. exit 0
  2517.