home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / skill / part02 < prev    next >
Text File  |  1994-07-15  |  97KB  |  3,536 lines

  1. Newsgroups: comp.sources.unix
  2. From: jeff@forys.cranbury.nj.us (Jeff Forys)
  3. Subject: v28i088: skill - signal or reprioritize specified processes, V3.6, Part02/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 88
  10. Archive-Name: skill/part02
  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 2 (of 3)."
  19. # Contents:  machdep/aix-3.c machdep/dynix-3.c machdep/hpux-70.c
  20. #   machdep/hpux-91.c machdep/osx-4.c machdep/sunos-3.c
  21. #   machdep/sys-5r4.c machdep/ultrix-22.c machdep/umips-21.c
  22. # Wrapped by vixie@gw.home.vix.com on Fri Jul 15 19:29:13 1994
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'machdep/aix-3.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'machdep/aix-3.c'\"
  26. else
  27. echo shar: Extracting \"'machdep/aix-3.c'\" \(8956 characters\)
  28. sed "s/^X//" >'machdep/aix-3.c' <<'END_OF_FILE'
  29. X#ifndef lint
  30. Xstatic char rcsid[] = "$Header: aix-3.c,v 1.4 1994/06/26 04:17:59 forys Exp $";
  31. X#endif
  32. X
  33. X/*
  34. X**  This program may be freely redistributed for noncommercial purposes.
  35. X**  This entire comment MUST remain intact.
  36. X**
  37. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  38. X*/
  39. X
  40. X#define    NO_MEXTERN
  41. X#include "conf.h"
  42. X#undef    NO_MEXTERN
  43. X
  44. X#include <sys/user.h>
  45. X#include <sys/proc.h>
  46. X
  47. X#include <stdio.h>
  48. X
  49. X/*
  50. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  51. X * routines and must be global.  Everyone seems to have their own
  52. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  53. X * signals available, not counting zero.
  54. X */
  55. Xchar *SigMap[] = { "0",
  56. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT",        /*  1 -  6 */
  57. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  58. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  59. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  60. X    "XFSZ", "26", "MSG", "WINCH", "PWR", "USR1",        /* 25 - 30 */
  61. X    "USR2", "PROF", "DANGER", "VTALRM", "MIGRATE", "PRE",    /* 31 - 36 */
  62. X    "37", "38", "39", "40", "41", "42",            /* 37 - 42 */
  63. X    "43", "44", "45", "46", "47", "48",            /* 43 - 48 */
  64. X    "49", "50", "51", "52", "53", "54",            /* 49 - 54 */
  65. X    "55", "56", "57", "58", "59", "GRANT",            /* 55 - 60 */
  66. X    "RETRACT", "SOUND", "SAK", "64",            /* 61 - 64 */
  67. X};
  68. Xint NSig = NSIG;
  69. X
  70. X#define    SETCMD(dst,src,maxlen) {            \
  71. X    extern char *rindex();                \
  72. X    if (maxlen > 0) src[maxlen] = '\0';        \
  73. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  74. X}
  75. X
  76. Xstatic char *TtyDevDir = "/dev";
  77. X
  78. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  79. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  80. Xint    SigPri;            /* signal to send or priority to set */
  81. Xpid_T    MyPid;            /* pid of this process */
  82. Xuid_T    MyUid;            /* uid of this process */
  83. Xchar    *ProgName;        /* program name */
  84. X
  85. X/*
  86. X * This is the machine-dependent initialization routine.
  87. X *
  88. X *   - The following global variables must be initialized:
  89. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  90. X *   - The working directory will be changed to that which contains the
  91. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  92. X *   - If possible, this routine should raise the priority of this process.
  93. X */
  94. Xvoid
  95. XMdepInit(pname)
  96. X    char *pname;
  97. X{
  98. X    extern char *rindex(), *SysErr();
  99. X
  100. X    MyPid = (pid_T) getpid();
  101. X    MyUid = (uid_T) getuid();
  102. X    SETCMD(ProgName, pname, 0)
  103. X
  104. X    /*
  105. X     * If we are running as root, raise our priority to better
  106. X     * catch runaway processes.
  107. X     */
  108. X    if (MyUid == ROOTUID)
  109. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  110. X
  111. X    /*
  112. X     * Determine what we are doing to processes we find.  We will
  113. X     * either send them a signal (skill), or renice them (snice).
  114. X     */
  115. X    Skill = (strcmp(ProgName, "snice") != 0);
  116. X
  117. X    /*
  118. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  119. X     */
  120. X    if (chdir(TtyDevDir) < 0) {
  121. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  122. X                SysErr());
  123. X        exit(EX_SERR);
  124. X    }
  125. X
  126. X    /*
  127. X     * Set up minimum and maximum process priorities.
  128. X     * Initialize SigPri to either default signal (`skill') or
  129. X     * default priority (`snice').
  130. X     */
  131. X    PrioMin = PRIO_MIN;
  132. X    PrioMax = PRIO_MAX;
  133. X    SigPri = Skill? SIGTERM: 4;
  134. X}
  135. X
  136. X/*
  137. X * Carry out an action on a particular process.  If this is `skill',
  138. X * then send the process a signal, otherwise this is `snice' so change
  139. X * it's priority.
  140. X *
  141. X * If 0 is returned, the operation was successful, otherwise -1 is
  142. X * returned and `errno' set.
  143. X */
  144. Xint
  145. XMdepAction(pid)
  146. X    pid_T pid;
  147. X{
  148. X    if (Skill)
  149. X        return(kill((int)pid, SigPri));
  150. X    else
  151. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  152. X}
  153. X
  154. X/*
  155. X * Now, set up everything we need to write a GetProc() routine.
  156. X *
  157. X * IMPORTANT NOTE TO PEOPLE SNARFING THIS CODE:
  158. X *
  159. X *    The AIX getproc() and getuser() routines are unsupported (not to
  160. X *    mention, undocumented).  They are liable to be changed, or replaced
  161. X *    in future versions of AIX.  Please include this comment in any
  162. X *    code that uses these routines.  Thanks.
  163. X *
  164. X *    With that said, here's a brief (incomplete) description of each:
  165. X *
  166. X *        #include <procinfo.h>
  167. X *
  168. X *        struct procinfo pinfo[N];
  169. X *        getproc(pinfo, N, sizeof(struct procinfo))
  170. X *        RETURN: number of procs read (must be all), or -1 on error.
  171. X *        [If N is too small, -1 is returned with errno == ENOSPC]
  172. X *
  173. X *        struct userinfo uinfo;
  174. X *        struct procinfo *aproc;
  175. X *        getuser(aproc, sizeof(struct procinfo), &uinfo, sizeof(uinfo))
  176. X *        RETURN: 0 on success, -1 on error.
  177. X */
  178. X
  179. X#include <sys/var.h>
  180. X#include <sys/sysconfig.h>
  181. X#include <sys/errno.h>
  182. X
  183. X#include <procinfo.h>
  184. X
  185. Xextern    off_t lseek();
  186. X
  187. X#define    NPROCS    256    /* size of `procs' struct (if too small, use calloc) */
  188. X
  189. X/*
  190. X * GetProc()
  191. X *
  192. X * Fill in and return a `struct ProcInfo' with information about the
  193. X * next process.  If no processes are left, return NULL.
  194. X *
  195. X * Fflag support:
  196. X *    If Fflag is set we will try to avoid reading in the user struct.
  197. X *    We can do this only if Iflag, TtyIndx, and CmdIndx are zero.
  198. X */
  199. Xstruct ProcInfo *
  200. XGetProc()
  201. X{
  202. X    extern int errno;
  203. X    extern char *SysErr();
  204. X    static struct procinfo pinfo[NPROCS], *procsp;
  205. X    static struct ProcInfo procinfo;
  206. X    register struct procinfo *aproc;
  207. X    register struct userinfo *auser;
  208. X    static int thisproc = 0;
  209. X    static int initialized = 0;
  210. X    static int needuser = 1;        /* Fflag support */
  211. X
  212. X    /*
  213. X     * Read in all the processes at once, into a large block of memory;
  214. X     * if `pinfo' is big enough, we'll use that, o/w we will calloc()
  215. X     * what we need.  Either way, `procsp' will point to the next proc.
  216. X     *
  217. X     * The first time thisproc == 0, we do the `procsp' initialization.
  218. X     * The second time thisproc == 0, we are finished and return NULL.
  219. X     * The following `while' is for sanity; it could be an `if'.
  220. X     */
  221. X    while (thisproc == 0) {
  222. X        char *errstr = "%s: %s: %s\n";
  223. X        register u_int nprocs, maxnprocs, pisize;
  224. X
  225. X        if (initialized)
  226. X            return((struct ProcInfo *)NULL);
  227. X
  228. X        pisize = sizeof(struct procinfo);
  229. X        if ((thisproc = getproc(pinfo, (u_int)NPROCS, pisize)) < 0) {
  230. X            /*
  231. X             * We apparently have more then NPROCS processes
  232. X             * running on this machine.  Ideally, one should
  233. X             * raise NPROCS if they run into this problem.
  234. X             * However, we'll quietly deal with it by grabbing
  235. X             * a sufficiently large block of memory.
  236. X             *
  237. X             * N.B. `nprocs' is temporarily used to hold `errno'
  238. X             * across the call to sysconfig(), after which, it
  239. X             * will assume it's real duty.
  240. X             */
  241. X            struct var v;
  242. X
  243. X            nprocs = errno;
  244. X            if (sysconfig(SYS_GETPARMS, &v, sizeof(struct var)) < 0)
  245. X                maxnprocs = 1024 * 1024;    /* very big */
  246. X            else
  247. X                maxnprocs = v.v_proc;
  248. X            errno = nprocs;
  249. X
  250. X            nprocs = NPROCS;
  251. X            while (errno == ENOSPC && nprocs <= maxnprocs) {
  252. X                nprocs <<= 1;
  253. X                if ((procsp = (struct procinfo *)
  254. X                     calloc(nprocs, pisize)) == NULL) {
  255. X                    fprintf(stderr, errstr, ProgName,
  256. X                            "getproc", "out of memory");
  257. X                    exit(EX_SERR);
  258. X                }
  259. X                errno = 0;
  260. X                thisproc = getproc(procsp, nprocs, pisize);
  261. X                if (thisproc < 0 && errno != ENOSPC) {
  262. X                    fprintf(stderr, errstr, ProgName,
  263. X                        "getproc", SysErr());
  264. X                    exit(EX_SERR);
  265. X                } else if (thisproc == nprocs)
  266. X                    break;
  267. X                free((void *)procsp);
  268. X            }
  269. X            if (nprocs > maxnprocs) {
  270. X                fprintf(stderr, errstr, ProgName,
  271. X                        "GetProc", "maxnproc exceeded");
  272. X                exit(EX_SERR);
  273. X            }
  274. X        } else
  275. X            procsp = pinfo;
  276. X
  277. X        /*
  278. X         * We run a little faster without reading in the user struct;
  279. X         * the price is incomplete information for errors (no cmd).
  280. X         */
  281. X        if (Fflag && Iflag == 0 && TtyIndx == 0 && CmdIndx == 0)
  282. X            needuser = 0;
  283. X
  284. X        initialized = 1;
  285. X    }
  286. X
  287. X    /*
  288. X     * Trudge thru `procsp'.  Decrement `thisproc' as we go.
  289. X     */
  290. X    do {
  291. X        aproc = procsp++;
  292. X        thisproc--;
  293. X
  294. X        if (aproc->pi_stat != SNONE) {
  295. X            /*
  296. X             * Make sure this isn't a "zombie" or "exiting"
  297. X             * process.  If it is, we have all the information
  298. X             * we need; fill in procinfo and return.
  299. X             */
  300. X            procinfo.pi_flags = 0;
  301. X            procinfo.pi_pid = (pid_T) aproc->pi_pid;
  302. X            procinfo.pi_uid = (uid_T) aproc->pi_uid;
  303. X
  304. X            if (aproc->pi_stat == SZOMB) {    /* zombie */
  305. X                static char *zombie = "<defunct>";
  306. X                procinfo.pi_flags |= PI_ZOMBIE;
  307. X                procinfo.pi_cmd = zombie;
  308. X            } else if (aproc->pi_flag & SEXIT) {
  309. X                static char *exiting = "<exiting>";
  310. X                procinfo.pi_flags |= PI_SWEXIT;
  311. X                procinfo.pi_cmd = exiting;
  312. X            } else if (!needuser) {
  313. X                static char *fflagcmd = "<-f>";
  314. X                procinfo.pi_cmd = fflagcmd;
  315. X            }
  316. X
  317. X            if (procinfo.pi_flags || !needuser)
  318. X                return(&procinfo);
  319. X            else {
  320. X                static struct userinfo uinfo;
  321. X                if (getuser(aproc, sizeof(struct procinfo),
  322. X                            &uinfo,sizeof(struct userinfo)) < 0)
  323. X                    auser = NULL;
  324. X                else
  325. X                    auser = &uinfo;
  326. X            }
  327. X        }
  328. X
  329. X    } while (aproc->pi_stat == SNONE || auser == NULL);
  330. X
  331. X    /*
  332. X     * We now have a process (`aproc').
  333. X     * Fill in the rest of `procinfo'.
  334. X     */
  335. X    if (auser->ui_ttyp != -1) {    /* has a controlling tty */
  336. X        procinfo.pi_flags |= PI_CTLTTY;
  337. X        procinfo.pi_tty = (tty_T) auser->ui_ttyd;
  338. X    }
  339. X
  340. X    /* set path-stripped command name */
  341. X    SETCMD(procinfo.pi_cmd, auser->ui_comm, MAXCOMLEN)
  342. X
  343. X    return(&procinfo);
  344. X}
  345. END_OF_FILE
  346. if test 8956 -ne `wc -c <'machdep/aix-3.c'`; then
  347.     echo shar: \"'machdep/aix-3.c'\" unpacked with wrong size!
  348. fi
  349. # end of 'machdep/aix-3.c'
  350. fi
  351. if test -f 'machdep/dynix-3.c' -a "${1}" != "-c" ; then 
  352.   echo shar: Will not clobber existing file \"'machdep/dynix-3.c'\"
  353. else
  354. echo shar: Extracting \"'machdep/dynix-3.c'\" \(9697 characters\)
  355. sed "s/^X//" >'machdep/dynix-3.c' <<'END_OF_FILE'
  356. X#ifndef lint
  357. Xstatic char rcsid[] = "$Header: dynix-3.c,v 1.9 1994/06/26 04:15:50 forys Exp $";
  358. X#endif
  359. X
  360. X/*
  361. X**  This program may be freely redistributed for noncommercial purposes.
  362. X**  This entire comment MUST remain intact.
  363. X**
  364. X**  Dynix 3.0 support by Gorodecki Tom (tom@taux01.nsc.com)
  365. X**
  366. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  367. X*/
  368. X
  369. X#define    NO_MEXTERN
  370. X#include "conf.h"
  371. X#undef    NO_MEXTERN
  372. X
  373. X#include <sys/user.h>
  374. X#include <sys/proc.h>
  375. X
  376. X#include <stdio.h>
  377. X
  378. X/*
  379. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  380. X * routines and must be global.  Everyone seems to have their own
  381. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  382. X * signals available, not counting zero.
  383. X */
  384. Xchar *SigMap[] = { "0",
  385. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  386. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  387. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  388. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  389. X    "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",    /* 25 - 30 */
  390. X    "USR2", "32",                        /* 31 - 32 */
  391. X};
  392. Xint NSig = NSIG;
  393. X
  394. X#define    SETCMD(dst,src,maxlen) {            \
  395. X    extern char *rindex();                \
  396. X    if (maxlen > 0) src[maxlen] = '\0';        \
  397. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  398. X}
  399. X
  400. Xstatic char *TtyDevDir = "/dev";
  401. X
  402. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  403. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  404. Xint    SigPri;            /* signal to send or priority to set */
  405. Xpid_T    MyPid;            /* pid of this process */
  406. Xuid_T    MyUid;            /* uid of this process */
  407. Xchar    *ProgName;        /* program name */
  408. X
  409. X/*
  410. X * This is the machine-dependent initialization routine.
  411. X *
  412. X *   - The following global variables must be initialized:
  413. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  414. X *   - The working directory will be changed to that which contains the
  415. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  416. X *   - If possible, this routine should raise the priority of this process.
  417. X */
  418. Xvoid
  419. XMdepInit(pname)
  420. X    char *pname;
  421. X{
  422. X    extern char *rindex(), *SysErr();
  423. X
  424. X    MyPid = (pid_T) getpid();
  425. X    MyUid = (uid_T) getuid();
  426. X    SETCMD(ProgName, pname, 0)
  427. X
  428. X    /*
  429. X     * If we are running as root, raise our priority to better
  430. X     * catch runaway processes.
  431. X     */
  432. X    if (MyUid == ROOTUID)
  433. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  434. X
  435. X    /*
  436. X     * Determine what we are doing to processes we find.  We will
  437. X     * either send them a signal (skill), or renice them (snice).
  438. X     */
  439. X    Skill = (strcmp(ProgName, "snice") != 0);
  440. X
  441. X    /*
  442. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  443. X     */
  444. X    if (chdir(TtyDevDir) < 0) {
  445. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  446. X                SysErr());
  447. X        exit(EX_SERR);
  448. X    }
  449. X
  450. X    /*
  451. X     * Set up minimum and maximum process priorities.
  452. X     * Initialize SigPri to either default signal (`skill') or
  453. X     * default priority (`snice').
  454. X     */
  455. X    PrioMin = PRIO_MIN;
  456. X    PrioMax = PRIO_MAX;
  457. X    SigPri = Skill? SIGTERM: 4;
  458. X}
  459. X
  460. X/*
  461. X * Carry out an action on a particular process.  If this is `skill',
  462. X * then send the process a signal, otherwise this is `snice' so change
  463. X * it's priority.
  464. X *
  465. X * If 0 is returned, the operation was successful, otherwise -1 is
  466. X * returned and `errno' set.
  467. X */
  468. Xint
  469. XMdepAction(pid)
  470. X    pid_T pid;
  471. X{
  472. X    if (Skill)
  473. X        return(kill((int)pid, SigPri));
  474. X    else
  475. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  476. X}
  477. X
  478. X/*
  479. X * Now, set up everything we need to write a GetProc() routine.
  480. X */
  481. X
  482. X#include <sys/file.h>
  483. X#include <sys/vm.h>
  484. X
  485. X#include <machine/pte.h>
  486. X
  487. X#include <nlist.h>
  488. X
  489. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  490. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  491. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  492. Xstatic char *kernf =    "/dynix";    /* kernel image */
  493. Xstatic int kmem = 0, mem = 0, swap = 0;
  494. X
  495. Xstatic struct nlist nl[] = {
  496. X    { "_nproc" },
  497. X#define    X_NPROC        0
  498. X    { "_proc" },
  499. X#define    X_PROC        1
  500. X    { "" },
  501. X#define    X_LAST        2
  502. X};
  503. Xstatic    int    nproc = -1;
  504. Xstatic    struct    proc *procp;
  505. X
  506. X#define    NPROCS    32            /* number of procs to read at once */
  507. X
  508. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  509. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  510. X
  511. Xextern    off_t lseek();
  512. X
  513. X/*
  514. X * GetProc()
  515. X *
  516. X * Fill in and return a `struct ProcInfo' with information about the
  517. X * next process.  If no processes are left, return NULL.
  518. X */
  519. Xstruct ProcInfo *
  520. XGetProc()
  521. X{
  522. X    extern char *SysErr();
  523. X    static struct user *GetUser();
  524. X    static struct proc procs[NPROCS], *procsp;
  525. X    static struct ProcInfo procinfo;
  526. X    register struct user *auser;
  527. X    register struct proc *aproc;
  528. X    static int thisproc = 0;
  529. X
  530. X    /*
  531. X     * If this is our first time here, open various files,
  532. X     * and set up the nlist.
  533. X     */
  534. X    if (nproc == -1) {
  535. X        char *errstr = "%s: %s: %s\n";
  536. X        int nfound;
  537. X
  538. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  539. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  540. X            exit(EX_SERR);
  541. X        }
  542. X
  543. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  544. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  545. X            exit(EX_SERR);
  546. X        }
  547. X
  548. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  549. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  550. X            exit(EX_SERR);
  551. X        }
  552. X
  553. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  554. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  555. X            exit(EX_SERR);
  556. X        }
  557. X        if (nfound != 0) {
  558. X            register int i;
  559. X
  560. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  561. X                    ProgName);
  562. X            for (i = 0; i < X_LAST; i++)
  563. X                if (nl[i].n_type == 0)
  564. X                    fprintf(stderr, " %s", nl[i].n_name);
  565. X            (void) putc('\n', stderr);
  566. X            exit(EX_SERR);
  567. X        }
  568. X
  569. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  570. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  571. X    }
  572. X
  573. X    /*
  574. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  575. X     * by the number of proc structures we have read; when it reaches
  576. X     * zero, we are finished (return NULL).
  577. X     */
  578. X    do {
  579. X        while (thisproc == 0) {
  580. X            int nread;
  581. X            int psize;
  582. X
  583. X            if (nproc == 0)
  584. X                return((struct ProcInfo *)NULL);
  585. X
  586. X            thisproc = MIN(NPROCS, nproc);
  587. X            psize = thisproc * sizeof(struct proc);
  588. X            nproc -= thisproc;
  589. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  590. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  591. X                fprintf(stderr, "%s: read proc: %s\n",
  592. X                        ProgName, SysErr());
  593. X                return((struct ProcInfo *)NULL);
  594. X            } else if (nread != psize) {
  595. X                thisproc = nread / sizeof(struct proc);
  596. X                nproc = 0;
  597. X                fprintf(stderr, "%s: read proc: short read\n",
  598. X                        ProgName);
  599. X            }
  600. X            procsp = procs;
  601. X            procp += thisproc;
  602. X        }
  603. X
  604. X        aproc = procsp++;
  605. X        thisproc--;
  606. X
  607. X        if (aproc->p_stat != 0) {
  608. X            /*
  609. X             * Before we go through the trouble of reading
  610. X             * in the user struct, let's make sure this isn't
  611. X             * a "zombie" or "exiting" process.  If it is,
  612. X             * we have all the information we need; fill in
  613. X             * procinfo and return.
  614. X             */
  615. X            procinfo.pi_flags = 0;
  616. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  617. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  618. X
  619. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  620. X                static char *zombie = "<defunct>";
  621. X                procinfo.pi_flags |= PI_ZOMBIE;
  622. X                procinfo.pi_cmd = zombie;
  623. X#ifdef    SWEXIT    /* not in Dynix 3.0.12; maybe in future releases? */
  624. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  625. X                static char *exiting = "<exiting>";
  626. X                procinfo.pi_flags |= PI_SWEXIT;
  627. X                procinfo.pi_cmd = exiting;
  628. X#endif
  629. X            }
  630. X
  631. X            if (procinfo.pi_flags)
  632. X                return(&procinfo);
  633. X            else
  634. X                auser = GetUser(aproc);
  635. X        }
  636. X
  637. X    } while (aproc->p_stat == 0 || auser == NULL);
  638. X
  639. X    /*
  640. X     * We now have a process (`aproc') and a user (`auser').
  641. X     * Fill in the rest of `procinfo'.
  642. X     */
  643. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  644. X        procinfo.pi_flags |= PI_CTLTTY;
  645. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  646. X    }
  647. X
  648. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  649. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  650. X        procinfo.pi_flags |= PI_ASKUSR;
  651. X    } else                 /* set path-stripped command name */
  652. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  653. X
  654. X    return(&procinfo);
  655. X}
  656. X
  657. X#define    SKRD(file, src, dst, size)            \
  658. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  659. X    (read(file, (char *)(dst), (size)) != (size))
  660. X
  661. X/*
  662. X * GetWord(loc)
  663. X *
  664. X * Read in word at `loc' from kernel virtual memory.
  665. X * If an error occurs, call exit(2) with EX_SERR.
  666. X */
  667. Xstatic int
  668. XGetWord(loc)
  669. X    off_t loc;
  670. X{
  671. X    int val;
  672. X
  673. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  674. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  675. X                ProgName, (u_long)loc, kmemf);
  676. X        exit(EX_SERR);
  677. X    }
  678. X    return (val);
  679. X}
  680. X
  681. X#define    SW_UADDR    dtob(aproc->p_swaddr)
  682. X#define    SW_UBYTES    roundup(sizeof(struct user), DEV_BSIZE)
  683. X
  684. X/*
  685. X * GetUser(aproc)
  686. X *
  687. X * Read in the user struct for `aproc' and return a pointer to it.
  688. X * If an error occurs, return NULL.
  689. X */
  690. Xstatic struct user *
  691. XGetUser(aproc)
  692. X    struct proc *aproc;
  693. X{
  694. X    static char *WarnMsg = "Warning: can't read ";
  695. X    static struct user *u = NULL;
  696. X    extern char *valloc();
  697. X
  698. X    /*
  699. X     * Grab a page-aligned block of memory for user structs.
  700. X     */
  701. X    if (u == NULL) {
  702. X        if ((u = (struct user *)valloc(UPAGES*NBPG)) == NULL) {
  703. X            if (Wflag)
  704. X                printf("%su for pid %d (valloc failed)\n",
  705. X                       WarnMsg, aproc->p_pid);
  706. X            return ((struct user *)NULL);
  707. X        }
  708. X    }
  709. X
  710. X    /*
  711. X     * If process is not in core, we simply snarf it's user struct
  712. X     * from the swap device.
  713. X     */
  714. X    if ((aproc->p_flag & SLOAD) == 0) {
  715. X        if (SKRD(swap, SW_UADDR, u, SW_UBYTES)) {
  716. X            if (Wflag)
  717. X                printf("%su for pid %d from %s\n",
  718. X                       WarnMsg, aproc->p_pid, swapf);
  719. X            return ((struct user *)NULL);
  720. X        }
  721. X        return (u);
  722. X    }
  723. X
  724. X    /*
  725. X     * Process is in core.
  726. X     * p_uarea points to u-area in kernel VA space.
  727. X     */
  728. X    if (SKRD(kmem, aproc->p_uarea, u, sizeof(struct user))) {
  729. X        if (Wflag)
  730. X            printf("%su for pid %d from %s\n",
  731. X                   WarnMsg, aproc->p_pid, kmemf);
  732. X        return ((struct user *)NULL);
  733. X    }
  734. X    return(u);
  735. X}
  736. END_OF_FILE
  737. if test 9697 -ne `wc -c <'machdep/dynix-3.c'`; then
  738.     echo shar: \"'machdep/dynix-3.c'\" unpacked with wrong size!
  739. fi
  740. # end of 'machdep/dynix-3.c'
  741. fi
  742. if test -f 'machdep/hpux-70.c' -a "${1}" != "-c" ; then 
  743.   echo shar: Will not clobber existing file \"'machdep/hpux-70.c'\"
  744. else
  745. echo shar: Extracting \"'machdep/hpux-70.c'\" \(11170 characters\)
  746. sed "s/^X//" >'machdep/hpux-70.c' <<'END_OF_FILE'
  747. X#ifndef lint
  748. Xstatic char rcsid[] = "$Header: hpux-70.c,v 1.9 1994/06/26 04:14:28 forys Exp $";
  749. X#endif
  750. X
  751. X/*
  752. X**  This program may be freely redistributed for noncommercial purposes.
  753. X**  This entire comment MUST remain intact.
  754. X**
  755. X**  HP-UX 6.5 support by Christos Zoulas (christos@deshaw.com)
  756. X**
  757. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  758. X*/
  759. X
  760. X#define    WOPR    /* some headers do magic when this is defined */
  761. X
  762. X#define    NO_MEXTERN
  763. X#include "conf.h"
  764. X#undef    NO_MEXTERN
  765. X
  766. X#include <sys/user.h>
  767. X#include <sys/proc.h>
  768. X#include <sys/rtprio.h>
  769. X#include <stdio.h>
  770. X
  771. X/*
  772. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  773. X * routines and must be global.  Everyone seems to have their own
  774. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  775. X * signals available, not counting zero.
  776. X */
  777. Xchar *SigMap[] = { "0",
  778. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  779. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  780. X    "PIPE", "ALRM", "TERM", "USR1", "USR2", "CLD",        /* 13 - 18 */
  781. X    "PWR", "VTALRM", "PROF", "IO", "WINDOW", "STOP",    /* 19 - 24 */
  782. X    "TSTP", "CONT", "TTIN", "TTOU", "URG", "LOST",        /* 25 - 30 */
  783. X    "31", "DIL",                        /* 31 - 32 */
  784. X};
  785. Xint NSig = NSIG-1;
  786. X
  787. X#define    SETCMD(dst,src,maxlen) {            \
  788. X    extern char *strrchr();                \
  789. X    if (maxlen > 0) src[maxlen] = '\0';        \
  790. X    dst = (dst = strrchr(src, '/')) ? ++dst: src;    \
  791. X}
  792. X
  793. Xstatic char *TtyDevDir = "/dev";
  794. X
  795. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  796. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  797. Xint    SigPri;            /* signal to send or priority to set */
  798. Xpid_T    MyPid;            /* pid of this process */
  799. Xuid_T    MyUid;            /* uid of this process */
  800. Xchar    *ProgName;        /* program name */
  801. X
  802. X/*
  803. X * This is the machine-dependent initialization routine.
  804. X *
  805. X *   - The following global variables must be initialized:
  806. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  807. X *   - The working directory will be changed to that which contains the
  808. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  809. X *   - If possible, this routine should raise the priority of this process.
  810. X */
  811. Xvoid
  812. XMdepInit(pname)
  813. X    char *pname;
  814. X{
  815. X    extern char *rindex(), *SysErr();
  816. X
  817. X    MyPid = (pid_T) getpid();
  818. X    MyUid = (uid_T) getuid();
  819. X    SETCMD(ProgName, pname, 0)
  820. X
  821. X    /*
  822. X     * If we are running as root, raise our priority to better
  823. X     * catch runaway processes.
  824. X     */
  825. X    if (MyUid == ROOTUID)
  826. X        (void) rtprio(MyPid, RTPRIO_MIN);
  827. X
  828. X    /*
  829. X     * Determine what we are doing to processes we find.  We will
  830. X     * either send them a signal (skill), or renice them (snice).
  831. X     */
  832. X    Skill = (strcmp(ProgName, "snice") != 0);
  833. X
  834. X    /*
  835. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  836. X     */
  837. X    if (chdir(TtyDevDir) < 0) {
  838. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  839. X                SysErr());
  840. X        exit(EX_SERR);
  841. X    }
  842. X
  843. X    /*
  844. X     * Set up minimum and maximum process priorities.
  845. X     * Initialize SigPri to either default signal (`skill') or
  846. X     * default priority (`snice').
  847. X     */
  848. X    PrioMin = RTPRIO_MIN;
  849. X    PrioMax = RTPRIO_MAX;
  850. X    SigPri = Skill? SIGTERM: RTPRIO_RTOFF;
  851. X}
  852. X
  853. X/*
  854. X * Carry out an action on a particular process.  If this is `skill',
  855. X * then send the process a signal, otherwise this is `snice' so change
  856. X * it's priority.
  857. X *
  858. X * If 0 is returned, the operation was successful, otherwise -1 is
  859. X * returned and `errno' set.
  860. X */
  861. Xint
  862. XMdepAction(pid)
  863. X    pid_T pid;
  864. X{
  865. X    if (Skill)
  866. X        return(kill((int)pid, SigPri));
  867. X    else
  868. X        return(rtprio((int)pid, SigPri));
  869. X}
  870. X
  871. X/*
  872. X * Now, set up everything we need to write a GetProc() routine.
  873. X */
  874. X
  875. X#include <sys/file.h>
  876. X#include <sys/vm.h>
  877. X
  878. X#include <machine/pte.h>
  879. X
  880. X#ifdef hp9000s800
  881. X#include <nlist.h>
  882. X#endif
  883. X
  884. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  885. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  886. Xstatic char *swapf =    "/dev/swap";    /* paging device */
  887. Xstatic char *kernf =    "/hp-ux";    /* kernel image */
  888. Xstatic int kmem = 0, mem = 0, swap = 0;
  889. X
  890. X#ifdef hp9000s800
  891. Xstatic struct nlist nl[] = {
  892. X    { "nproc" },
  893. X#define    X_NPROC        0
  894. X    { "proc" },
  895. X#define    X_PROC        1
  896. X    { "ubase" },
  897. X#define    X_UBASE        2
  898. X    { "npids" },
  899. X#define    X_NPIDS        3
  900. X    { "" },
  901. X#define    X_LAST        4
  902. X};
  903. X#else
  904. Xstatic struct nlist nl[] = {
  905. X    { "_nproc" },
  906. X#define    X_NPROC        0
  907. X    { "_proc" },
  908. X#define    X_PROC        1
  909. X    { "" },
  910. X#define    X_LAST        2
  911. X};
  912. X#endif
  913. X
  914. Xstatic    int    nproc = -1;
  915. Xstatic    struct    proc *procp;
  916. X#ifdef hp9000s800
  917. Xstatic    int    npids;
  918. Xstatic    struct user *ubase;
  919. X#endif
  920. X
  921. X#define    NPROCS    32            /* number of procs to read at once */
  922. X
  923. X#ifdef hp9000s800
  924. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon",
  925. X                      "statdaemon", "syncdaemon" };
  926. X#else
  927. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  928. X#endif
  929. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  930. X
  931. Xextern    off_t lseek();
  932. X
  933. X/*
  934. X * GetProc()
  935. X *
  936. X * Fill in and return a `struct ProcInfo' with information about the
  937. X * next process.  If no processes are left, return NULL.
  938. X */
  939. Xstruct ProcInfo *
  940. XGetProc()
  941. X{
  942. X    extern char *SysErr();
  943. X    static struct user *GetUser();
  944. X    static struct proc procs[NPROCS], *procsp;
  945. X    static struct ProcInfo procinfo;
  946. X    register struct user *auser;
  947. X    register struct proc *aproc;
  948. X    static int thisproc = 0;
  949. X
  950. X    /*
  951. X     * If this is our first time here, open various files,
  952. X     * and set up the nlist.
  953. X     */
  954. X    if (nproc == -1) {
  955. X        char *errstr = "%s: %s: %s\n";
  956. X        int nfound;
  957. X
  958. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  959. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  960. X            exit(EX_SERR);
  961. X        }
  962. X
  963. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  964. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  965. X            exit(EX_SERR);
  966. X        }
  967. X
  968. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  969. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  970. X            exit(EX_SERR);
  971. X        }
  972. X
  973. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  974. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  975. X            exit(EX_SERR);
  976. X        }
  977. X        if (nfound != 0) {
  978. X            register int i;
  979. X
  980. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  981. X                    ProgName);
  982. X            for (i = 0; i < X_LAST; i++)
  983. X                if (nl[i].n_type == 0)
  984. X                    fprintf(stderr, " %s", nl[i].n_name);
  985. X            (void) putc('\n', stderr);
  986. X            exit(EX_SERR);
  987. X        }
  988. X
  989. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  990. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  991. X#ifdef hp9000s800
  992. X        npids = GetWord((off_t)nl[X_NPIDS].n_value);
  993. X        ubase = (struct user *)nl[X_UBASE].n_value;
  994. X#endif
  995. X    }
  996. X
  997. X    /*
  998. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  999. X     * by the number of proc structures we have read; when it reaches
  1000. X     * zero, we are finished (return NULL).
  1001. X     */
  1002. X    do {
  1003. X        while (thisproc == 0) {
  1004. X            int nread;
  1005. X            int psize;
  1006. X
  1007. X            if (nproc == 0)
  1008. X                return((struct ProcInfo *)NULL);
  1009. X
  1010. X            thisproc = MIN(NPROCS, nproc);
  1011. X            psize = thisproc * sizeof(struct proc);
  1012. X            nproc -= thisproc;
  1013. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  1014. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  1015. X                fprintf(stderr, "%s: read proc: %s\n",
  1016. X                        ProgName, SysErr());
  1017. X                return((struct ProcInfo *)NULL);
  1018. X            } else if (nread != psize) {
  1019. X                thisproc = nread / sizeof(struct proc);
  1020. X                nproc = 0;
  1021. X                fprintf(stderr, "%s: read proc: short read\n",
  1022. X                        ProgName);
  1023. X            }
  1024. X            procsp = procs;
  1025. X            procp += thisproc;
  1026. X        }
  1027. X
  1028. X        aproc = procsp++;
  1029. X        thisproc--;
  1030. X
  1031. X        if (aproc->p_stat != 0) {
  1032. X            /*
  1033. X             * Before we go through the trouble of reading
  1034. X             * in the user struct, let's make sure this isn't
  1035. X             * a "zombie" or "exiting" process.  If it is,
  1036. X             * we have all the information we need; fill in
  1037. X             * procinfo and return.
  1038. X             */
  1039. X            procinfo.pi_flags = 0;
  1040. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  1041. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  1042. X
  1043. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  1044. X                static char *zombie = "<defunct>";
  1045. X                procinfo.pi_flags |= PI_ZOMBIE;
  1046. X                procinfo.pi_cmd = zombie;
  1047. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  1048. X                static char *exiting = "<exiting>";
  1049. X                procinfo.pi_flags |= PI_SWEXIT;
  1050. X                procinfo.pi_cmd = exiting;
  1051. X            }
  1052. X
  1053. X            if (procinfo.pi_flags)
  1054. X                return(&procinfo);
  1055. X            else
  1056. X                auser = GetUser(aproc);
  1057. X        }
  1058. X
  1059. X    } while (aproc->p_stat == 0 || auser == NULL);
  1060. X
  1061. X    /*
  1062. X     * We now have a process (`aproc') and a user (`auser').
  1063. X     * Fill in the rest of `procinfo'.
  1064. X     */
  1065. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  1066. X        procinfo.pi_flags |= PI_CTLTTY;
  1067. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  1068. X    }
  1069. X
  1070. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  1071. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  1072. X        procinfo.pi_flags |= PI_ASKUSR;
  1073. X    } else                 /* set path-stripped command name */
  1074. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  1075. X
  1076. X    return(&procinfo);
  1077. X}
  1078. X
  1079. X#define    SKRD(file, src, dst, size)            \
  1080. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  1081. X    (read(file, (char *)(dst), (size)) != (size))
  1082. X
  1083. X/*
  1084. X * GetWord(loc)
  1085. X *
  1086. X * Read in word at `loc' from kernel virtual memory.
  1087. X * If an error occurs, call exit(2) with EX_SERR.
  1088. X */
  1089. Xstatic int
  1090. XGetWord(loc)
  1091. X    off_t loc;
  1092. X{
  1093. X    int val;
  1094. X
  1095. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  1096. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  1097. X                ProgName, (u_long)loc, kmemf);
  1098. X        exit(EX_SERR);
  1099. X    }
  1100. X    return (val);
  1101. X}
  1102. X
  1103. X#ifdef hp9000s800
  1104. X#define    SW_UADDR    dtob(aproc->p_swaddr+ctod(btoc(STACKSIZE*NBPG)))
  1105. X#define    SW_UBYTES    sizeof(struct user)
  1106. X#else
  1107. X#define    SW_UADDR    dtob(aproc->p_swaddr)
  1108. X#define    SW_UBYTES    ctob(btoc(sizeof(struct user)))
  1109. X#endif
  1110. X
  1111. X/*
  1112. X * GetUser(aproc)
  1113. X *
  1114. X * Read in the user struct for `aproc' and return a pointer to it.
  1115. X * If an error occurs, return NULL.
  1116. X */
  1117. Xstatic struct user *
  1118. XGetUser(aproc)
  1119. X    struct proc *aproc;
  1120. X{
  1121. X    static char *WarnMsg = "Warning: can't read ";
  1122. X    static union {
  1123. X        struct user user;
  1124. X        char upgs[UPAGES][NBPG];
  1125. X    } u;
  1126. X#ifndef hp9000s800
  1127. X    static struct pte uptes[UPAGES];
  1128. X    register int i, nbytes;
  1129. X#endif
  1130. X
  1131. X    /*
  1132. X     * If process is not in core, we simply snarf it's user struct
  1133. X     * from the swap device.
  1134. X     */
  1135. X    if ((aproc->p_flag & SLOAD) == 0) {
  1136. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  1137. X            if (Wflag)
  1138. X                printf("%su for pid %d from %s\n",
  1139. X                       WarnMsg, aproc->p_pid, swapf);
  1140. X            return ((struct user *)NULL);
  1141. X        }
  1142. X        return (&u.user);
  1143. X    }
  1144. X
  1145. X#ifdef hp9000s800
  1146. X    /*
  1147. X     * User areas are all in kernel VM starting at `ubase'.
  1148. X     * uvadd() uses `ubase' and `npids' to determine location.
  1149. X     */
  1150. X#undef    pindx
  1151. X#define    pindx(p)    ((p)->p_ndx)
  1152. X    if (SKRD(kmem, uvadd(aproc), &u.user, sizeof(struct user))) {
  1153. X        if (Wflag)
  1154. X            printf("%suser area for pid %d from %s\n",
  1155. X                   WarnMsg, aproc->p_pid, kmemf);
  1156. X        return((struct user *)NULL);
  1157. X    }
  1158. X#else
  1159. X    /*
  1160. X     * Process is in core.  Follow p_addr to read in the page
  1161. X     * table entries that map the u-area and then read in the
  1162. X     * physical pages that comprise the u-area.
  1163. X     *
  1164. X     * If at any time, an lseek() or read() fails, print a warning
  1165. X     * message (if `Wflag' is set) and return NULL.
  1166. X     */
  1167. X    if (SKRD(kmem, aproc->p_addr, uptes, sizeof(uptes))) {
  1168. X        if (Wflag)
  1169. X            printf("%suser pt for pid %d from %s\n",
  1170. X                   WarnMsg, aproc->p_pid, kmemf);
  1171. X        return ((struct user *)NULL);
  1172. X    }
  1173. X
  1174. X    nbytes = sizeof(struct user);
  1175. X    for (i = 0; i < UPAGES && nbytes > 0; i++) {
  1176. X        if (SKRD(mem, ptob(uptes[i].pg_pfnum), u.upgs[i], NBPG)) {
  1177. X            if (Wflag)
  1178. X                printf("%suser page %u for pid %d from %s\n",
  1179. X                       WarnMsg, uptes[i].pg_pfnum,
  1180. X                       aproc->p_pid, memf);
  1181. X            return((struct user *)NULL);
  1182. X        }
  1183. X        nbytes -= NBPG;
  1184. X    }
  1185. X#endif
  1186. X    return (&u.user);
  1187. X}
  1188. END_OF_FILE
  1189. if test 11170 -ne `wc -c <'machdep/hpux-70.c'`; then
  1190.     echo shar: \"'machdep/hpux-70.c'\" unpacked with wrong size!
  1191. fi
  1192. # end of 'machdep/hpux-70.c'
  1193. fi
  1194. if test -f 'machdep/hpux-91.c' -a "${1}" != "-c" ; then 
  1195.   echo shar: Will not clobber existing file \"'machdep/hpux-91.c'\"
  1196. else
  1197. echo shar: Extracting \"'machdep/hpux-91.c'\" \(9399 characters\)
  1198. sed "s/^X//" >'machdep/hpux-91.c' <<'END_OF_FILE'
  1199. X#ifndef lint
  1200. Xstatic char rcsid[] = "$Header: hpux-91.c,v 1.7 1994/06/26 04:32:33 forys Exp $";
  1201. X#endif
  1202. X
  1203. X/*
  1204. X**  This program may be freely redistributed for noncommercial purposes.
  1205. X**  This entire comment MUST remain intact.
  1206. X**
  1207. X**  HP-UX 8.0 support by Christos Zoulas (christos@deshaw.com)
  1208. X**
  1209. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  1210. X*/
  1211. X
  1212. X#define    WOPR    /* some headers do magic when this is defined */
  1213. X
  1214. X#define    NO_MEXTERN
  1215. X#include "conf.h"
  1216. X#undef    NO_MEXTERN
  1217. X
  1218. X#include <sys/user.h>
  1219. X#include <sys/proc.h>
  1220. X#include <sys/rtprio.h>
  1221. X
  1222. X#include <stdio.h>
  1223. X
  1224. X/*
  1225. X** Note: HP-UX finally supports setpriority(2); snice has been changed to
  1226. X** use this, rather than rtprio(2).  If you need the old behavior, you can
  1227. X** #define OLD_RTPRIO.
  1228. X*/
  1229. X
  1230. X/*
  1231. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  1232. X * routines and must be global.  Everyone seems to have their own
  1233. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  1234. X * signals available, not counting zero.
  1235. X */
  1236. Xchar *SigMap[] = { "0",
  1237. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  1238. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  1239. X    "PIPE", "ALRM", "TERM", "USR1", "USR2", "CLD",        /* 13 - 18 */
  1240. X    "PWR", "VTALRM", "PROF", "IO", "WINDOW", "STOP",    /* 19 - 24 */
  1241. X    "TSTP", "CONT", "TTIN", "TTOU", "URG", "LOST",        /* 25 - 30 */
  1242. X    "31", "DIL",                        /* 31 - 32 */
  1243. X};
  1244. Xint NSig = NSIG-1;
  1245. X
  1246. X#define    SETCMD(dst,src,maxlen) {            \
  1247. X    extern char *strrchr();                \
  1248. X    if (maxlen > 0) src[maxlen] = '\0';        \
  1249. X    dst = (dst = strrchr(src, '/')) ? ++dst: src;    \
  1250. X}
  1251. X
  1252. Xstatic char *TtyDevDir = "/dev";
  1253. X
  1254. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  1255. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  1256. Xint    SigPri;            /* signal to send or priority to set */
  1257. Xpid_T    MyPid;            /* pid of this process */
  1258. Xuid_T    MyUid;            /* uid of this process */
  1259. Xchar    *ProgName;        /* program name */
  1260. X
  1261. X/*
  1262. X * This is the machine-dependent initialization routine.
  1263. X *
  1264. X *   - The following global variables must be initialized:
  1265. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  1266. X *   - The working directory will be changed to that which contains the
  1267. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  1268. X *   - If possible, this routine should raise the priority of this process.
  1269. X */
  1270. Xvoid
  1271. XMdepInit(pname)
  1272. X    char *pname;
  1273. X{
  1274. X    extern char *rindex(), *SysErr();
  1275. X
  1276. X    MyPid = (pid_T) getpid();
  1277. X    MyUid = (uid_T) getuid();
  1278. X    SETCMD(ProgName, pname, 0)
  1279. X
  1280. X    /*
  1281. X     * If we are running as root, raise our priority to better
  1282. X     * catch runaway processes.
  1283. X     */
  1284. X    if (MyUid == ROOTUID)
  1285. X#ifdef OLD_RTPRIO
  1286. X        (void) rtprio(MyPid, RTPRIO_MIN);
  1287. X#else
  1288. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  1289. X#endif
  1290. X
  1291. X    /*
  1292. X     * Determine what we are doing to processes we find.  We will
  1293. X     * either send them a signal (skill), or renice them (snice).
  1294. X     */
  1295. X    Skill = (strstr(ProgName, "snice") == NULL);
  1296. X
  1297. X    /*
  1298. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  1299. X     */
  1300. X    if (chdir(TtyDevDir) < 0) {
  1301. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  1302. X                SysErr());
  1303. X        exit(EX_SERR);
  1304. X    }
  1305. X
  1306. X    /*
  1307. X     * Set up minimum and maximum process priorities.
  1308. X     * Initialize SigPri to either default signal (`skill') or
  1309. X     * default priority (`snice').
  1310. X     */
  1311. X#ifdef OLD_RTPRIO
  1312. X    PrioMin = RTPRIO_MIN;
  1313. X    PrioMax = RTPRIO_MAX;
  1314. X    SigPri = Skill? SIGTERM: RTPRIO_RTOFF;
  1315. X#else
  1316. X    PrioMin = PRIO_MIN;
  1317. X    PrioMax = PRIO_MAX;
  1318. X    SigPri = Skill? SIGTERM: 4;
  1319. X#endif
  1320. X}
  1321. X
  1322. X/*
  1323. X * Carry out an action on a particular process.  If this is `skill',
  1324. X * then send the process a signal, otherwise this is `snice' so change
  1325. X * it's priority.
  1326. X *
  1327. X * If 0 is returned, the operation was successful, otherwise -1 is
  1328. X * returned and `errno' set.
  1329. X */
  1330. Xint
  1331. XMdepAction(pid)
  1332. X    pid_T pid;
  1333. X{
  1334. X    if (Skill)
  1335. X        return(kill((int)pid, SigPri));
  1336. X    else
  1337. X#ifdef OLD_RTPRIO
  1338. X        return(rtprio((int)pid, SigPri));
  1339. X#else
  1340. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  1341. X#endif
  1342. X}
  1343. X
  1344. X/*
  1345. X * Now, set up everything we need to write a GetProc() routine.
  1346. X */
  1347. X
  1348. X#include <sys/file.h>
  1349. X#include <sys/vm.h>
  1350. X#include <sys/pstat.h>
  1351. X
  1352. X#if defined(hp9000s800) || defined(__hp9000s800)
  1353. X#include <nlist.h>
  1354. X#endif
  1355. X
  1356. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  1357. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  1358. Xstatic char *swapf =    "/dev/dmem";    /* paging device */
  1359. Xstatic char *kernf =    "/hp-ux";    /* kernel image */
  1360. Xstatic int kmem = 0, mem = 0, swap = 0;
  1361. X
  1362. X#ifdef hp9000s800
  1363. Xstatic struct nlist nl[] = {
  1364. X    { "nproc" },
  1365. X#define    X_NPROC        0
  1366. X    { "proc" },
  1367. X#define    X_PROC        1
  1368. X    { "" },
  1369. X#define    X_LAST        2
  1370. X};
  1371. X#else
  1372. Xstatic struct nlist nl[] = {
  1373. X    { "_nproc" },
  1374. X#define    X_NPROC        0
  1375. X    { "_proc" },
  1376. X#define    X_PROC        1
  1377. X    { "" },
  1378. X#define    X_LAST        2
  1379. X};
  1380. X#endif
  1381. X
  1382. Xstatic    int    nproc = -1;
  1383. Xstatic    struct    proc *procp;
  1384. X
  1385. X#define    NPROCS    32            /* number of procs to read at once */
  1386. X
  1387. X#ifdef hp9000s800
  1388. Xstatic    char    *pidmap[] = { "swapper", "init", "vhand", "statdaemon" };
  1389. X#else
  1390. Xstatic    char    *pidmap[] = { "swapper", "init", "vhand" };
  1391. X#endif
  1392. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  1393. X
  1394. Xextern    off_t lseek();
  1395. X
  1396. X/*
  1397. X * GetProc()
  1398. X *
  1399. X * Fill in and return a `struct ProcInfo' with information about the
  1400. X * next process.  If no processes are left, return NULL.
  1401. X */
  1402. Xstruct ProcInfo *
  1403. XGetProc()
  1404. X{
  1405. X    extern char *SysErr();
  1406. X    static int GetWord();
  1407. X    static struct proc procs[NPROCS], *procsp;
  1408. X    static struct ProcInfo procinfo;
  1409. X    static  struct  pst_status apst;
  1410. X    register struct proc *aproc;
  1411. X    static int thisproc = 0;
  1412. X
  1413. X    /*
  1414. X     * If this is our first time here, open various files,
  1415. X     * and set up the nlist.
  1416. X     */
  1417. X    if (nproc == -1) {
  1418. X        char *errstr = "%s: %s: %s\n";
  1419. X        int nfound;
  1420. X
  1421. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  1422. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  1423. X            exit(EX_SERR);
  1424. X        }
  1425. X
  1426. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  1427. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  1428. X            exit(EX_SERR);
  1429. X        }
  1430. X
  1431. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  1432. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  1433. X            exit(EX_SERR);
  1434. X        }
  1435. X
  1436. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  1437. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  1438. X            exit(EX_SERR);
  1439. X        }
  1440. X        if (nfound != 0) {
  1441. X            register int i;
  1442. X
  1443. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  1444. X                    ProgName);
  1445. X            for (i = 0; i < X_LAST; i++)
  1446. X                if (nl[i].n_type == 0)
  1447. X                    fprintf(stderr, " %s", nl[i].n_name);
  1448. X            (void) putc('\n', stderr);
  1449. X            exit(EX_SERR);
  1450. X        }
  1451. X
  1452. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  1453. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  1454. X    }
  1455. X
  1456. X    /*
  1457. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  1458. X     * by the number of proc structures we have read; when it reaches
  1459. X     * zero, we are finished (return NULL).
  1460. X     */
  1461. X    do {
  1462. X        while (thisproc == 0) {
  1463. X            int nread;
  1464. X            int psize;
  1465. X
  1466. X            if (nproc == 0)
  1467. X                return((struct ProcInfo *)NULL);
  1468. X
  1469. X            thisproc = MIN(NPROCS, nproc);
  1470. X            psize = thisproc * sizeof(struct proc);
  1471. X            nproc -= thisproc;
  1472. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  1473. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  1474. X                fprintf(stderr, "%s: read proc: %s\n",
  1475. X                        ProgName, SysErr());
  1476. X                return((struct ProcInfo *)NULL);
  1477. X            } else if (nread != psize) {
  1478. X                thisproc = nread / sizeof(struct proc);
  1479. X                nproc = 0;
  1480. X                fprintf(stderr, "%s: read proc: short read\n",
  1481. X                        ProgName);
  1482. X            }
  1483. X            procsp = procs;
  1484. X            procp += thisproc;
  1485. X        }
  1486. X
  1487. X        aproc = procsp++;
  1488. X        thisproc--;
  1489. X        if (aproc->p_stat != 0) {
  1490. X            if (pstat(PSTAT_PROC, &apst, sizeof(apst), 0, 
  1491. X                  aproc->p_pid) != 1)
  1492. X                aproc->p_stat = 0;
  1493. X            /*
  1494. X             * Before we fill in the rest of `procinfo', let's
  1495. X             * make sure this isn't a "zombie" or "exiting"
  1496. X             * process.  If it is, we have all the information
  1497. X             * we need; fill in procinfo and return.
  1498. X             */
  1499. X            procinfo.pi_flags = 0;
  1500. X            procinfo.pi_pid = (pid_T) apst.pst_pid;
  1501. X            procinfo.pi_uid = (uid_T) apst.pst_uid;
  1502. X
  1503. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  1504. X                static char *zombie = "<defunct>";
  1505. X                procinfo.pi_flags |= PI_ZOMBIE;
  1506. X                procinfo.pi_cmd = zombie;
  1507. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  1508. X                static char *exiting = "<exiting>";
  1509. X                procinfo.pi_flags |= PI_SWEXIT;
  1510. X                procinfo.pi_cmd = exiting;
  1511. X            }
  1512. X            if (procinfo.pi_flags)
  1513. X                return(&procinfo);
  1514. X        }
  1515. X
  1516. X    } while (aproc->p_stat == 0);
  1517. X
  1518. X    /*
  1519. X     * We now have a process (`aproc') and process info (`apst').
  1520. X     * Fill in the rest of `procinfo'.
  1521. X     */
  1522. X    if (apst.pst_term.psd_major != -1) {
  1523. X        procinfo.pi_flags |= PI_CTLTTY;
  1524. X        procinfo.pi_tty = (tty_T) makedev(apst.pst_term.psd_major,
  1525. X                          apst.pst_term.psd_minor);
  1526. X    }
  1527. X
  1528. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  1529. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  1530. X        procinfo.pi_flags |= PI_ASKUSR;
  1531. X    } else { /* set path-stripped command name */
  1532. X        char *s, *strtok();
  1533. X        if ((s = strtok(apst.pst_cmd, "\n\t ")) == NULL)
  1534. X            s = apst.pst_cmd;
  1535. X        if (*s == '-')
  1536. X            s++;
  1537. X#ifdef PST_CLEN
  1538. X        SETCMD(procinfo.pi_cmd, s, PST_CLEN)
  1539. X#else
  1540. X        SETCMD(procinfo.pi_cmd, s, MAXCOMLEN)
  1541. X#endif
  1542. X    }
  1543. X
  1544. X    return(&procinfo);
  1545. X}
  1546. X
  1547. X#define    SKRD(file, src, dst, size)            \
  1548. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  1549. X    (read(file, (char *)(dst), (size)) != (size))
  1550. X
  1551. X/*
  1552. X * GetWord(loc)
  1553. X *
  1554. X * Read in word at `loc' from kernel virtual memory.
  1555. X * If an error occurs, call exit(2) with EX_SERR.
  1556. X */
  1557. Xstatic int
  1558. XGetWord(loc)
  1559. X    off_t loc;
  1560. X{
  1561. X    int val;
  1562. X
  1563. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  1564. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  1565. X                ProgName, (u_long)loc, kmemf);
  1566. X        exit(EX_SERR);
  1567. X    }
  1568. X    return (val);
  1569. X}
  1570. END_OF_FILE
  1571. if test 9399 -ne `wc -c <'machdep/hpux-91.c'`; then
  1572.     echo shar: \"'machdep/hpux-91.c'\" unpacked with wrong size!
  1573. fi
  1574. # end of 'machdep/hpux-91.c'
  1575. fi
  1576. if test -f 'machdep/osx-4.c' -a "${1}" != "-c" ; then 
  1577.   echo shar: Will not clobber existing file \"'machdep/osx-4.c'\"
  1578. else
  1579. echo shar: Extracting \"'machdep/osx-4.c'\" \(9940 characters\)
  1580. sed "s/^X//" >'machdep/osx-4.c' <<'END_OF_FILE'
  1581. X#ifndef lint
  1582. Xstatic char rcsid[] = "$Header: osx-4.c,v 1.8 1994/06/26 04:16:26 forys Exp $";
  1583. X#endif
  1584. X
  1585. X/*
  1586. X**  This program may be freely redistributed for noncommercial purposes.
  1587. X**  This entire comment MUST remain intact.
  1588. X**
  1589. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  1590. X*/
  1591. X
  1592. X#define    NO_MEXTERN
  1593. X#include "conf.h"
  1594. X#undef    NO_MEXTERN
  1595. X
  1596. X#include <sys/user.h>
  1597. X#include <sys/proc.h>
  1598. X
  1599. X#include <stdio.h>
  1600. X
  1601. X/*
  1602. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  1603. X * routines and must be global.  Everyone seems to have their own
  1604. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  1605. X * signals available, not counting zero.
  1606. X */
  1607. Xchar *SigMap[] = { "0",
  1608. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  1609. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  1610. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  1611. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  1612. X    "XFSZ", "VTALRM", "PROF", "USR1", "USR2", "PWR",    /* 25 - 30 */
  1613. X    "31", "32",                        /* 31 - 32 */
  1614. X};
  1615. Xint NSig = NSIG;
  1616. X
  1617. X#define    SETCMD(dst,src,maxlen) {            \
  1618. X    extern char *rindex();                \
  1619. X    if (maxlen > 0) src[maxlen] = '\0';        \
  1620. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  1621. X}
  1622. X
  1623. Xstatic char *TtyDevDir = "/dev";
  1624. X
  1625. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  1626. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  1627. Xint    SigPri;            /* signal to send or priority to set */
  1628. Xpid_T    MyPid;            /* pid of this process */
  1629. Xuid_T    MyUid;            /* uid of this process */
  1630. Xchar    *ProgName;        /* program name */
  1631. X
  1632. X/*
  1633. X * This is the machine-dependent initialization routine.
  1634. X *
  1635. X *   - The following global variables must be initialized:
  1636. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  1637. X *   - The working directory will be changed to that which contains the
  1638. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  1639. X *   - If possible, this routine should raise the priority of this process.
  1640. X */
  1641. Xvoid
  1642. XMdepInit(pname)
  1643. X    char *pname;
  1644. X{
  1645. X    extern char *rindex(), *SysErr();
  1646. X
  1647. X    MyPid = (pid_T) getpid();
  1648. X    MyUid = (uid_T) getuid();
  1649. X    SETCMD(ProgName, pname, 0)
  1650. X
  1651. X    /*
  1652. X     * If we are running as root, raise our priority to better
  1653. X     * catch runaway processes.
  1654. X     */
  1655. X    if (MyUid == ROOTUID)
  1656. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  1657. X
  1658. X    /*
  1659. X     * Determine what we are doing to processes we find.  We will
  1660. X     * either send them a signal (skill), or renice them (snice).
  1661. X     */
  1662. X    Skill = (strcmp(ProgName, "snice") != 0);
  1663. X
  1664. X    /*
  1665. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  1666. X     */
  1667. X    if (chdir(TtyDevDir) < 0) {
  1668. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  1669. X                SysErr());
  1670. X        exit(EX_SERR);
  1671. X    }
  1672. X
  1673. X    /*
  1674. X     * Set up minimum and maximum process priorities.
  1675. X     * Initialize SigPri to either default signal (`skill') or
  1676. X     * default priority (`snice').
  1677. X     */
  1678. X    PrioMin = PRIO_MIN;
  1679. X    PrioMax = PRIO_MAX;
  1680. X    SigPri = Skill? SIGTERM: 4;
  1681. X}
  1682. X
  1683. X/*
  1684. X * Carry out an action on a particular process.  If this is `skill',
  1685. X * then send the process a signal, otherwise this is `snice' so change
  1686. X * it's priority.
  1687. X *
  1688. X * If 0 is returned, the operation was successful, otherwise -1 is
  1689. X * returned and `errno' set.
  1690. X */
  1691. Xint
  1692. XMdepAction(pid)
  1693. X    pid_T pid;
  1694. X{
  1695. X    if (Skill)
  1696. X        return(kill((int)pid, SigPri));
  1697. X    else
  1698. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  1699. X}
  1700. X
  1701. X/*
  1702. X * Now, set up everything we need to write a GetProc() routine.
  1703. X */
  1704. X
  1705. X#include <sys/file.h>
  1706. X#include <sys/vm.h>
  1707. X#include <sys/pte.h>
  1708. X
  1709. X#include <nlist.h>
  1710. X
  1711. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  1712. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  1713. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  1714. Xstatic char *kernf =    "/vmunix";    /* kernel image */
  1715. Xstatic int kmem = 0, mem = 0, swap = 0;
  1716. X
  1717. Xstatic struct nlist nl[] = {
  1718. X    { "_nproc" },
  1719. X#define    X_NPROC        0
  1720. X    { "_proc" },
  1721. X#define    X_PROC        1
  1722. X    { "" },
  1723. X#define    X_LAST        2
  1724. X};
  1725. Xstatic    int    nproc = -1;
  1726. Xstatic    struct    proc *procp;
  1727. X
  1728. X#define    NPROCS    32            /* number of procs to read at once */
  1729. X
  1730. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  1731. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  1732. X
  1733. Xextern    off_t lseek();
  1734. X
  1735. X/*
  1736. X * GetProc()
  1737. X *
  1738. X * Fill in and return a `struct ProcInfo' with information about the
  1739. X * next process.  If no processes are left, return NULL.
  1740. X */
  1741. Xstruct ProcInfo *
  1742. XGetProc()
  1743. X{
  1744. X    extern char *SysErr();
  1745. X    static struct user *GetUser();
  1746. X    static struct proc procs[NPROCS], *procsp;
  1747. X    static struct ProcInfo procinfo;
  1748. X    register struct user *auser;
  1749. X    register struct proc *aproc;
  1750. X    static int thisproc = 0;
  1751. X
  1752. X    /*
  1753. X     * If this is our first time here, open various files,
  1754. X     * and set up the nlist.
  1755. X     */
  1756. X    if (nproc == -1) {
  1757. X        char *errstr = "%s: %s: %s\n";
  1758. X        int nfound;
  1759. X
  1760. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  1761. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  1762. X            exit(EX_SERR);
  1763. X        }
  1764. X
  1765. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  1766. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  1767. X            exit(EX_SERR);
  1768. X        }
  1769. X
  1770. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  1771. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  1772. X            exit(EX_SERR);
  1773. X        }
  1774. X
  1775. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  1776. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  1777. X            exit(EX_SERR);
  1778. X        }
  1779. X        if (nfound != 0) {
  1780. X            register int i;
  1781. X
  1782. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  1783. X                    ProgName);
  1784. X            for (i = 0; i < X_LAST; i++)
  1785. X                if (nl[i].n_type == 0)
  1786. X                    fprintf(stderr, " %s", nl[i].n_name);
  1787. X            (void) putc('\n', stderr);
  1788. X            exit(EX_SERR);
  1789. X        }
  1790. X
  1791. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  1792. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  1793. X    }
  1794. X
  1795. X    /*
  1796. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  1797. X     * by the number of proc structures we have read; when it reaches
  1798. X     * zero, we are finished (return NULL).
  1799. X     */
  1800. X    do {
  1801. X        while (thisproc == 0) {
  1802. X            int nread;
  1803. X            int psize;
  1804. X
  1805. X            if (nproc == 0)
  1806. X                return((struct ProcInfo *)NULL);
  1807. X
  1808. X            thisproc = MIN(NPROCS, nproc);
  1809. X            psize = thisproc * sizeof(struct proc);
  1810. X            nproc -= thisproc;
  1811. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  1812. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  1813. X                fprintf(stderr, "%s: read proc: %s\n",
  1814. X                        ProgName, SysErr());
  1815. X                return((struct ProcInfo *)NULL);
  1816. X            } else if (nread != psize) {
  1817. X                thisproc = nread / sizeof(struct proc);
  1818. X                nproc = 0;
  1819. X                fprintf(stderr, "%s: read proc: short read\n",
  1820. X                        ProgName);
  1821. X            }
  1822. X            procsp = procs;
  1823. X            procp += thisproc;
  1824. X        }
  1825. X
  1826. X        aproc = procsp++;
  1827. X        thisproc--;
  1828. X
  1829. X        if (aproc->p_stat != 0) {
  1830. X            /*
  1831. X             * Before we go through the trouble of reading
  1832. X             * in the user struct, let's make sure this isn't
  1833. X             * a "zombie" or "exiting" process.  If it is,
  1834. X             * we have all the information we need; fill in
  1835. X             * procinfo and return.
  1836. X             */
  1837. X            procinfo.pi_flags = 0;
  1838. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  1839. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  1840. X
  1841. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  1842. X                static char *zombie = "<defunct>";
  1843. X                procinfo.pi_flags |= PI_ZOMBIE;
  1844. X                procinfo.pi_cmd = zombie;
  1845. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  1846. X                static char *exiting = "<exiting>";
  1847. X                procinfo.pi_flags |= PI_SWEXIT;
  1848. X                procinfo.pi_cmd = exiting;
  1849. X            }
  1850. X
  1851. X            if (procinfo.pi_flags)
  1852. X                return(&procinfo);
  1853. X            else
  1854. X                auser = GetUser(aproc);
  1855. X        }
  1856. X
  1857. X    } while (aproc->p_stat == 0 || auser == NULL);
  1858. X
  1859. X    /*
  1860. X     * We now have a process (`aproc') and a user (`auser').
  1861. X     * Fill in the rest of `procinfo'.
  1862. X     */
  1863. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  1864. X        procinfo.pi_flags |= PI_CTLTTY;
  1865. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  1866. X    }
  1867. X
  1868. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  1869. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  1870. X        procinfo.pi_flags |= PI_ASKUSR;
  1871. X    } else                 /* set path-stripped command name */
  1872. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  1873. X
  1874. X    return(&procinfo);
  1875. X}
  1876. X
  1877. X#define    SKRD(file, src, dst, size)            \
  1878. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  1879. X    (read(file, (char *)(dst), (size)) != (size))
  1880. X
  1881. X/*
  1882. X * GetWord(loc)
  1883. X *
  1884. X * Read in word at `loc' from kernel virtual memory.
  1885. X * If an error occurs, call exit(2) with EX_SERR.
  1886. X */
  1887. Xstatic int
  1888. XGetWord(loc)
  1889. X    off_t loc;
  1890. X{
  1891. X    int val;
  1892. X
  1893. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  1894. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  1895. X                ProgName, (u_long)loc, kmemf);
  1896. X        exit(EX_SERR);
  1897. X    }
  1898. X    return (val);
  1899. X}
  1900. X
  1901. X#ifndef    NBPG
  1902. X#define    NBPG    PAGSIZ
  1903. X#endif
  1904. X
  1905. X#define    SW_UADDR    dtob(aproc->p_swaddr+aproc->p_szpt)
  1906. X#define    SW_UBYTES    sizeof(struct user)
  1907. X
  1908. X/*
  1909. X * GetUser(aproc)
  1910. X *
  1911. X * Read in the user struct for `aproc' and return a pointer to it.
  1912. X * If an error occurs, return NULL.
  1913. X */
  1914. Xstatic struct user *
  1915. XGetUser(aproc)
  1916. X    struct proc *aproc;
  1917. X{
  1918. X    static char *WarnMsg = "Warning: can't read ";
  1919. X    static union {
  1920. X        struct user user;
  1921. X        char upgs[UPAGES][NBPG];
  1922. X    } u;
  1923. X    static struct pte uptes[UPAGES];
  1924. X    register int i, nbytes;
  1925. X
  1926. X    /*
  1927. X     * If process is not in core, we simply snarf it's user struct
  1928. X     * from the swap device.
  1929. X     */
  1930. X    if ((aproc->p_flag & SLOAD) == 0) {
  1931. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  1932. X            if (Wflag)
  1933. X                printf("%su for pid %d from %s\n",
  1934. X                       WarnMsg, aproc->p_pid, swapf);
  1935. X            return ((struct user *)NULL);
  1936. X        }
  1937. X        return (&u.user);
  1938. X    }
  1939. X
  1940. X    /*
  1941. X     * Process is in core.  Follow p_addr to read in the page
  1942. X     * table entries that map the u-area and then read in the
  1943. X     * physical pages that comprise the u-area.
  1944. X     *
  1945. X     * If at any time, an lseek() or read() fails, print a warning
  1946. X     * message (if `Wflag' is set) and return NULL.
  1947. X     */
  1948. X    if (SKRD(kmem, aproc->p_addr, uptes, sizeof(uptes))) {
  1949. X        if (Wflag)
  1950. X            printf("%suser pt for pid %d from %s\n",
  1951. X                   WarnMsg, aproc->p_pid, kmemf);
  1952. X        return ((struct user *)NULL);
  1953. X    }
  1954. X
  1955. X    nbytes = sizeof(struct user);
  1956. X    for (i = 0; i < UPAGES && nbytes > 0; i++) {
  1957. X        if (SKRD(mem, ptob(uptes[i].pg_pfnum), u.upgs[i], NBPG)) {
  1958. X            if (Wflag)
  1959. X                printf("%suser page %u for pid %d from %s\n",
  1960. X                       WarnMsg, uptes[i].pg_pfnum,
  1961. X                       aproc->p_pid, memf);
  1962. X            return((struct user *)NULL);
  1963. X        }
  1964. X        nbytes -= NBPG;
  1965. X    }
  1966. X    return (&u.user);
  1967. X}
  1968. END_OF_FILE
  1969. if test 9940 -ne `wc -c <'machdep/osx-4.c'`; then
  1970.     echo shar: \"'machdep/osx-4.c'\" unpacked with wrong size!
  1971. fi
  1972. # end of 'machdep/osx-4.c'
  1973. fi
  1974. if test -f 'machdep/sunos-3.c' -a "${1}" != "-c" ; then 
  1975.   echo shar: Will not clobber existing file \"'machdep/sunos-3.c'\"
  1976. else
  1977. echo shar: Extracting \"'machdep/sunos-3.c'\" \(10724 characters\)
  1978. sed "s/^X//" >'machdep/sunos-3.c' <<'END_OF_FILE'
  1979. X#ifndef lint
  1980. Xstatic char rcsid[] = "$Header: sunos-3.c,v 1.8 1994/06/26 04:17:12 forys Exp $";
  1981. X#endif
  1982. X
  1983. X/*
  1984. X**  This program may be freely redistributed for noncommercial purposes.
  1985. X**  This entire comment MUST remain intact.
  1986. X**
  1987. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  1988. X*/
  1989. X
  1990. X#define    NO_MEXTERN
  1991. X#include "conf.h"
  1992. X#undef    NO_MEXTERN
  1993. X
  1994. X#include <sys/user.h>
  1995. X#include <sys/proc.h>
  1996. X
  1997. X#include <stdio.h>
  1998. X
  1999. X/*
  2000. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  2001. X * routines and must be global.  Everyone seems to have their own
  2002. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  2003. X * signals available, not counting zero.
  2004. X */
  2005. Xchar *SigMap[] = { "0",
  2006. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  2007. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  2008. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  2009. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  2010. X    "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",    /* 25 - 30 */
  2011. X    "USR2", "32",                        /* 31 - 32 */
  2012. X};
  2013. Xint NSig = NSIG;
  2014. X
  2015. X#define    SETCMD(dst,src,maxlen) {            \
  2016. X    extern char *rindex();                \
  2017. X    if (maxlen > 0) src[maxlen] = '\0';        \
  2018. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  2019. X}
  2020. X
  2021. Xstatic char *TtyDevDir = "/dev";
  2022. X
  2023. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  2024. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  2025. Xint    SigPri;            /* signal to send or priority to set */
  2026. Xpid_T    MyPid;            /* pid of this process */
  2027. Xuid_T    MyUid;            /* uid of this process */
  2028. Xchar    *ProgName;        /* program name */
  2029. X
  2030. X/*
  2031. X * This is the machine-dependent initialization routine.
  2032. X *
  2033. X *   - The following global variables must be initialized:
  2034. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  2035. X *   - The working directory will be changed to that which contains the
  2036. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  2037. X *   - If possible, this routine should raise the priority of this process.
  2038. X */
  2039. Xvoid
  2040. XMdepInit(pname)
  2041. X    char *pname;
  2042. X{
  2043. X    extern char *rindex(), *SysErr();
  2044. X
  2045. X    MyPid = (pid_T) getpid();
  2046. X    MyUid = (uid_T) getuid();
  2047. X    SETCMD(ProgName, pname, 0)
  2048. X
  2049. X    /*
  2050. X     * If we are running as root, raise our priority to better
  2051. X     * catch runaway processes.
  2052. X     */
  2053. X    if (MyUid == ROOTUID)
  2054. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  2055. X
  2056. X    /*
  2057. X     * Determine what we are doing to processes we find.  We will
  2058. X     * either send them a signal (skill), or renice them (snice).
  2059. X     */
  2060. X    Skill = (strcmp(ProgName, "snice") != 0);
  2061. X
  2062. X    /*
  2063. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  2064. X     */
  2065. X    if (chdir(TtyDevDir) < 0) {
  2066. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  2067. X                SysErr());
  2068. X        exit(EX_SERR);
  2069. X    }
  2070. X
  2071. X    /*
  2072. X     * Set up minimum and maximum process priorities.
  2073. X     * Initialize SigPri to either default signal (`skill') or
  2074. X     * default priority (`snice').
  2075. X     */
  2076. X    PrioMin = PRIO_MIN;
  2077. X    PrioMax = PRIO_MAX;
  2078. X    SigPri = Skill? SIGTERM: 4;
  2079. X}
  2080. X
  2081. X/*
  2082. X * Carry out an action on a particular process.  If this is `skill',
  2083. X * then send the process a signal, otherwise this is `snice' so change
  2084. X * it's priority.
  2085. X *
  2086. X * If 0 is returned, the operation was successful, otherwise -1 is
  2087. X * returned and `errno' set.
  2088. X */
  2089. Xint
  2090. XMdepAction(pid)
  2091. X    pid_T pid;
  2092. X{
  2093. X    if (Skill)
  2094. X        return(kill((int)pid, SigPri));
  2095. X    else
  2096. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  2097. X}
  2098. X
  2099. X/*
  2100. X * Now, set up everything we need to write a GetProc() routine.
  2101. X */
  2102. X
  2103. X#include <sys/file.h>
  2104. X#include <sys/vm.h>
  2105. X
  2106. X#include <machine/pte.h>
  2107. X
  2108. X#include <nlist.h>
  2109. X
  2110. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  2111. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  2112. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  2113. Xstatic char *kernf =    "/vmunix";    /* kernel image */
  2114. Xstatic int kmem = 0, mem = 0, swap = 0;
  2115. X
  2116. Xstatic struct nlist nl[] = {
  2117. X    { "_nproc" },
  2118. X#define    X_NPROC        0
  2119. X    { "_proc" },
  2120. X#define    X_PROC        1
  2121. X    { "_Usrptmap" },
  2122. X#define    X_USRPTMAP    2
  2123. X    { "_usrpt" },
  2124. X#define    X_USRPT        3
  2125. X    { "" },
  2126. X#define    X_LAST        4
  2127. X};
  2128. Xstatic    int    nproc = -1;
  2129. Xstatic    struct    proc *procp;
  2130. Xstatic    struct    pte *usrptmap, *usrpt;
  2131. X
  2132. X#define    NPROCS    32            /* number of procs to read at once */
  2133. X
  2134. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  2135. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  2136. X
  2137. Xextern    off_t lseek();
  2138. X
  2139. X/*
  2140. X * GetProc()
  2141. X *
  2142. X * Fill in and return a `struct ProcInfo' with information about the
  2143. X * next process.  If no processes are left, return NULL.
  2144. X */
  2145. Xstruct ProcInfo *
  2146. XGetProc()
  2147. X{
  2148. X    extern char *SysErr();
  2149. X    static struct user *GetUser();
  2150. X    static struct proc procs[NPROCS], *procsp;
  2151. X    static struct ProcInfo procinfo;
  2152. X    register struct user *auser;
  2153. X    register struct proc *aproc;
  2154. X    static int thisproc = 0;
  2155. X
  2156. X    /*
  2157. X     * If this is our first time here, open various files,
  2158. X     * and set up the nlist.
  2159. X     */
  2160. X    if (nproc == -1) {
  2161. X        char *errstr = "%s: %s: %s\n";
  2162. X        int nfound;
  2163. X
  2164. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  2165. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  2166. X            exit(EX_SERR);
  2167. X        }
  2168. X
  2169. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  2170. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  2171. X            exit(EX_SERR);
  2172. X        }
  2173. X
  2174. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  2175. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  2176. X            exit(EX_SERR);
  2177. X        }
  2178. X
  2179. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  2180. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  2181. X            exit(EX_SERR);
  2182. X        }
  2183. X        if (nfound != 0) {
  2184. X            register int i;
  2185. X
  2186. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  2187. X                    ProgName);
  2188. X            for (i = 0; i < X_LAST; i++)
  2189. X                if (nl[i].n_type == 0)
  2190. X                    fprintf(stderr, " %s", nl[i].n_name);
  2191. X            (void) putc('\n', stderr);
  2192. X            exit(EX_SERR);
  2193. X        }
  2194. X
  2195. X        usrpt = (struct pte *) nl[X_USRPT].n_value;
  2196. X        usrptmap = (struct pte *) nl[X_USRPTMAP].n_value;
  2197. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  2198. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  2199. X    }
  2200. X
  2201. X    /*
  2202. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  2203. X     * by the number of proc structures we have read; when it reaches
  2204. X     * zero, we are finished (return NULL).
  2205. X     */
  2206. X    do {
  2207. X        while (thisproc == 0) {
  2208. X            int nread;
  2209. X            int psize;
  2210. X
  2211. X            if (nproc == 0)
  2212. X                return((struct ProcInfo *)NULL);
  2213. X
  2214. X            thisproc = MIN(NPROCS, nproc);
  2215. X            psize = thisproc * sizeof(struct proc);
  2216. X            nproc -= thisproc;
  2217. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  2218. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  2219. X                fprintf(stderr, "%s: read proc: %s\n",
  2220. X                        ProgName, SysErr());
  2221. X                return((struct ProcInfo *)NULL);
  2222. X            } else if (nread != psize) {
  2223. X                thisproc = nread / sizeof(struct proc);
  2224. X                nproc = 0;
  2225. X                fprintf(stderr, "%s: read proc: short read\n",
  2226. X                        ProgName);
  2227. X            }
  2228. X            procsp = procs;
  2229. X            procp += thisproc;
  2230. X        }
  2231. X
  2232. X        aproc = procsp++;
  2233. X        thisproc--;
  2234. X
  2235. X        if (aproc->p_stat != 0) {
  2236. X            /*
  2237. X             * Before we go through the trouble of reading
  2238. X             * in the user struct, let's make sure this isn't
  2239. X             * a "zombie" or "exiting" process.  If it is,
  2240. X             * we have all the information we need; fill in
  2241. X             * procinfo and return.
  2242. X             */
  2243. X            procinfo.pi_flags = 0;
  2244. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  2245. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  2246. X
  2247. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  2248. X                static char *zombie = "<defunct>";
  2249. X                procinfo.pi_flags |= PI_ZOMBIE;
  2250. X                procinfo.pi_cmd = zombie;
  2251. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  2252. X                static char *exiting = "<exiting>";
  2253. X                procinfo.pi_flags |= PI_SWEXIT;
  2254. X                procinfo.pi_cmd = exiting;
  2255. X            }
  2256. X
  2257. X            if (procinfo.pi_flags)
  2258. X                return(&procinfo);
  2259. X            else
  2260. X                auser = GetUser(aproc);
  2261. X        }
  2262. X
  2263. X    } while (aproc->p_stat == 0 || auser == NULL);
  2264. X
  2265. X    /*
  2266. X     * We now have a process (`aproc') and a user (`auser').
  2267. X     * Fill in the rest of `procinfo'.
  2268. X     */
  2269. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  2270. X        procinfo.pi_flags |= PI_CTLTTY;
  2271. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  2272. X    }
  2273. X
  2274. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  2275. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  2276. X        procinfo.pi_flags |= PI_ASKUSR;
  2277. X    } else                 /* set path-stripped command name */
  2278. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  2279. X
  2280. X    return(&procinfo);
  2281. X}
  2282. X
  2283. X#define    SKRD(file, src, dst, size)            \
  2284. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  2285. X    (read(file, (char *)(dst), (size)) != (size))
  2286. X
  2287. X/*
  2288. X * GetWord(loc)
  2289. X *
  2290. X * Read in word at `loc' from kernel virtual memory.
  2291. X * If an error occurs, call exit(2) with EX_SERR.
  2292. X */
  2293. Xstatic int
  2294. XGetWord(loc)
  2295. X    off_t loc;
  2296. X{
  2297. X    int val;
  2298. X
  2299. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  2300. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  2301. X                ProgName, (u_long)loc, kmemf);
  2302. X        exit(EX_SERR);
  2303. X    }
  2304. X    return (val);
  2305. X}
  2306. X
  2307. X#ifndef    CLBYTES
  2308. X#define    CLBYTES    (CLSIZE*NBPG)
  2309. X#endif
  2310. X
  2311. X#define    SW_UADDR    dtob(aproc->p_swaddr)
  2312. X#define    SW_UBYTES    roundup(sizeof(struct user), DEV_BSIZE)
  2313. X
  2314. X/*
  2315. X * GetUser(aproc)
  2316. X *
  2317. X * Read in the user struct for `aproc' and return a pointer to it.
  2318. X * If an error occurs, return NULL.
  2319. X */
  2320. Xstatic struct user *
  2321. XGetUser(aproc)
  2322. X    struct proc *aproc;
  2323. X{
  2324. X    static char *WarnMsg = "Warning: can't read ";
  2325. X    static union {
  2326. X        struct user user;
  2327. X        char upgs[UPAGES][NBPG];
  2328. X    } u;
  2329. X    static struct pte apte, uptes[UPAGES+CLSIZE];
  2330. X    register int ncl, i;
  2331. X
  2332. X    /*
  2333. X     * If process is not in core, we simply snarf it's user struct
  2334. X     * from the swap device.
  2335. X     */
  2336. X    if ((aproc->p_flag & SLOAD) == 0) {
  2337. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  2338. X            if (Wflag)
  2339. X                printf("%su for pid %d from %s\n",
  2340. X                       WarnMsg, aproc->p_pid, swapf);
  2341. X            return ((struct user *)NULL);
  2342. X        }
  2343. X        return (&u.user);
  2344. X    }
  2345. X
  2346. X    /*
  2347. X     * Process is in core.  First read from the user page-table
  2348. X     * map for this process to get the u-area page table entry.
  2349. X     * Next, read in the page table entries that map the u-area.
  2350. X     * Finally, read in the physical pages that comprise the u-area.
  2351. X     *
  2352. X     * If at any time, an lseek() or read() fails, print a warning
  2353. X     * message (if `Wflag' is set) and return NULL.
  2354. X     */
  2355. X    if (SKRD(kmem, &usrptmap[btokmx(aproc->p_p0br) + aproc->p_szpt - 1],
  2356. X             &apte, sizeof(apte))) {
  2357. X        if (Wflag)
  2358. X            printf("%sindir pte of user pt for pid %d from %s\n",
  2359. X                   WarnMsg, aproc->p_pid, kmemf);
  2360. X        return ((struct user *)NULL);
  2361. X    }
  2362. X
  2363. X    if (SKRD(mem, ctob(apte.pg_pfnum+1)-(UPAGES+CLSIZE)*sizeof(struct pte),
  2364. X             uptes, sizeof(uptes))) {
  2365. X        if (Wflag)
  2366. X            printf("%suser pt for pid %d from %s\n",
  2367. X                   WarnMsg, aproc->p_pid, memf);
  2368. X        return ((struct user *)NULL);
  2369. X    }
  2370. X
  2371. X    /*
  2372. X     * Set `ncl' to the (rounded up) number of u-area page clusters
  2373. X     * to read, and then read in this user struct (in reverse).
  2374. X     */
  2375. X    ncl = (sizeof(struct user) + CLBYTES - 1) / CLBYTES;
  2376. X    while (--ncl >= 0) {
  2377. X        i = ncl * CLSIZE;
  2378. X        if (SKRD(mem,ctob(uptes[CLSIZE+i].pg_pfnum),u.upgs[i],CLBYTES)){
  2379. X            if (Wflag)
  2380. X                printf("%suser page %u for pid %d from %s\n",
  2381. X                       WarnMsg, uptes[CLSIZE+i].pg_pfnum,
  2382. X                       aproc->p_pid, memf);
  2383. X            return((struct user *)NULL);
  2384. X        }
  2385. X    }
  2386. X    return (&u.user);
  2387. X}
  2388. END_OF_FILE
  2389. if test 10724 -ne `wc -c <'machdep/sunos-3.c'`; then
  2390.     echo shar: \"'machdep/sunos-3.c'\" unpacked with wrong size!
  2391. fi
  2392. # end of 'machdep/sunos-3.c'
  2393. fi
  2394. if test -f 'machdep/sys-5r4.c' -a "${1}" != "-c" ; then 
  2395.   echo shar: Will not clobber existing file \"'machdep/sys-5r4.c'\"
  2396. else
  2397. echo shar: Extracting \"'machdep/sys-5r4.c'\" \(8314 characters\)
  2398. sed "s/^X//" >'machdep/sys-5r4.c' <<'END_OF_FILE'
  2399. X#ifndef lint
  2400. Xstatic char rcsid[] = "$Header: sys-5r4.c,v 1.10 1994/06/26 04:19:28 forys Exp $";
  2401. X#endif
  2402. X
  2403. X/*
  2404. X**  This program may be freely redistributed for noncommercial purposes.
  2405. X**  This entire comment MUST remain intact.
  2406. X**
  2407. X**  System V support by Ric Anderson (ric@cs.arizona.edu)
  2408. X**
  2409. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  2410. X*/
  2411. X
  2412. X
  2413. X#define    NO_MEXTERN
  2414. X#include "conf.h"
  2415. X#undef    NO_MEXTERN
  2416. X
  2417. X#include <sys/user.h>
  2418. X#include <sys/proc.h>
  2419. X#include <sys/priocntl.h>
  2420. X#include <sys/tspriocntl.h>
  2421. X
  2422. X#if !defined(P_PID)
  2423. X#include <sys/procset.h>
  2424. X#endif
  2425. X
  2426. X#include <dirent.h>
  2427. X#include <stdio.h>
  2428. X
  2429. Xextern int MissedProcCnt;
  2430. X
  2431. X/*
  2432. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  2433. X * routines and must be global.  Everyone seems to have their own
  2434. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  2435. X * signals available, not counting zero.
  2436. X */
  2437. Xchar *SigMap[] = { "0",
  2438. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  2439. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  2440. X    "PIPE", "ALRM", "TERM", "USR1", "USR2", "CHLD",        /* 13 - 18 */
  2441. X    "PWR", "WINCH", "URG", "POLL", "STOP", "TSTP",        /* 19 - 24 */
  2442. X    "CONT", "TTIN", "TTOU", "VTALRM", "PROF", "XCPU",    /* 25 - 30 */
  2443. X    "XFS2", "WAITING", "LWP"                /* 31 - 33 */
  2444. X};
  2445. Xint NSig = NSIG-1;
  2446. X
  2447. X#define    SETCMD(dst,src,maxlen) {            \
  2448. X    extern char *strrchr();                \
  2449. X    if (maxlen > 0) src[maxlen] = '\0';        \
  2450. X    dst = (dst = strrchr(src, '/')) ? ++dst: src;    \
  2451. X}
  2452. X
  2453. Xstatic char *TtyDevDir = "/dev";
  2454. X
  2455. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  2456. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  2457. Xint    SigPri;            /* signal to send or priority to set */
  2458. Xpid_T    MyPid;            /* pid of this process */
  2459. Xuid_T    MyUid;            /* uid of this process */
  2460. Xchar    *ProgName;        /* program name */
  2461. X
  2462. X/*
  2463. X * This is the machine-dependent initialization routine.
  2464. X *
  2465. X *   - The following global variables must be initialized:
  2466. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  2467. X *   - The working directory will be changed to that which contains the
  2468. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  2469. X *   - If possible, this routine should raise the priority of this process.
  2470. X */
  2471. X
  2472. Xvoid skill_getpri(int *low, int *high);
  2473. Xint skill_setpri(pid_t pid, int niceval);
  2474. X
  2475. Xvoid
  2476. XMdepInit(pname)
  2477. X    char *pname;
  2478. X{
  2479. X    extern char *rindex(), *SysErr();
  2480. X
  2481. X    MyPid = (pid_T) getpid();
  2482. X    MyUid = (uid_T) getuid();
  2483. X    SETCMD(ProgName, pname, 0)
  2484. X
  2485. X    /*
  2486. X     * Set up minimum and maximum process priorities.
  2487. X     * Initialize SigPri to either default signal (`skill') or
  2488. X     * default priority (`snice').
  2489. X     */
  2490. X    skill_getpri(&PrioMin,&PrioMax);
  2491. X
  2492. X    /*
  2493. X     * If we are running as root, raise our priority to better
  2494. X     * catch runaway processes.
  2495. X     */
  2496. X    if (MyUid == ROOTUID)
  2497. X        (void) skill_setpri(MyPid, PrioMax);
  2498. X
  2499. X    /*
  2500. X     * Determine what we are doing to processes we find.  We will
  2501. X     * either send them a signal (skill), or renice them (snice).
  2502. X     */
  2503. X    Skill = (strstr(ProgName, "snice") == NULL);
  2504. X
  2505. X    /*
  2506. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  2507. X     */
  2508. X    if (chdir(TtyDevDir) < 0) {
  2509. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  2510. X                SysErr());
  2511. X        exit(EX_SERR);
  2512. X    }
  2513. X    SigPri = Skill? SIGTERM: 4;
  2514. X}
  2515. X
  2516. X/*
  2517. X * Carry out an action on a particular process.  If this is `skill',
  2518. X * then send the process a signal, otherwise this is `snice' so change
  2519. X * it's priority.
  2520. X *
  2521. X * If 0 is returned, the operation was successful, otherwise -1 is
  2522. X * returned and `errno' set.
  2523. X */
  2524. Xint
  2525. XMdepAction(pid)
  2526. X    pid_T pid;
  2527. X{
  2528. X    if (Skill)
  2529. X        return(kill((int)pid, SigPri));
  2530. X    else
  2531. X        return(skill_setpri((int)pid, SigPri));
  2532. X}
  2533. X
  2534. X/*
  2535. X * Now, set up everything we need to write a GetProc() routine.
  2536. X */
  2537. X
  2538. X#include <sys/procfs.h>
  2539. X
  2540. X#include <fcntl.h>
  2541. X
  2542. Xstatic char *ProcDir =    "/proc";    /* proc direcotry */
  2543. Xstatic char *ProcFil =    "/proc/%s";    /* proc images */
  2544. X
  2545. X/*
  2546. X * GetProc()
  2547. X *
  2548. X * Fill in and return a `struct ProcInfo' with information about the
  2549. X * next process.  If no processes are left, return NULL.
  2550. X */
  2551. Xstruct ProcInfo *
  2552. XGetProc()
  2553. X{
  2554. X    extern char *SysErr();
  2555. X    static char *zombie = "<defunct>";
  2556. X    static struct ProcInfo procinfo;
  2557. X    static DIR *dirfp = NULL;
  2558. X    static struct prpsinfo pinfo;
  2559. X    struct dirent *dp;
  2560. X    char flnm[FILENAME_MAX];
  2561. X    int fd;
  2562. X
  2563. X    /*
  2564. X     * If this is our first time here, open the proc directory,...
  2565. X     */
  2566. X    if (dirfp == NULL && (dirfp=opendir(ProcDir)) == NULL) {
  2567. X        fprintf(stderr, "%s: %s: %s\n", ProgName, ProcDir, SysErr());
  2568. X        exit(EX_SERR);
  2569. X    }
  2570. X
  2571. X    while ((dp = readdir(dirfp)) != NULL) {
  2572. X        if (strcmp(dp->d_name,".") == 0 || strcmp(dp->d_name,"..") == 0)
  2573. X            continue;
  2574. X        (void) sprintf(flnm, ProcFil, dp->d_name);
  2575. X        if ((fd = open(flnm, O_RDONLY)) < 0) {
  2576. X            MissedProcCnt++;
  2577. X            continue;    /* ignore procs we don't own */
  2578. X        }
  2579. X        if (ioctl(fd, PIOCPSINFO, &pinfo) == -1) {
  2580. X            (void) close(fd);
  2581. X            continue;    /* ignore these too */
  2582. X        }
  2583. X        (void) close(fd);
  2584. X
  2585. X        /*
  2586. X         * Information about a process now resides in 'pinfo'.
  2587. X         */
  2588. X        procinfo.pi_flags = 0;
  2589. X        procinfo.pi_pid = pinfo.pr_pid;
  2590. X        procinfo.pi_uid = pinfo.pr_uid;
  2591. X        if (pinfo.pr_zomb != 0) {
  2592. X            procinfo.pi_flags |= PI_ZOMBIE;
  2593. X            procinfo.pi_cmd = zombie;
  2594. X        } else {
  2595. X            if (pinfo.pr_pid < 5)    /* low pids are special */
  2596. X                procinfo.pi_flags |= PI_ASKUSR;
  2597. X            if (pinfo.pr_lttydev != PRNODEV) {
  2598. X                procinfo.pi_flags |= PI_CTLTTY;
  2599. X                procinfo.pi_tty = pinfo.pr_lttydev;
  2600. X            }
  2601. X            procinfo.pi_cmd = pinfo.pr_fname;
  2602. X        }
  2603. X        return(&procinfo);
  2604. X    }
  2605. X
  2606. X    (void) closedir(dirfp);
  2607. X    dirfp = NULL;
  2608. X    return((struct ProcInfo *)NULL);
  2609. X}
  2610. X
  2611. X
  2612. X
  2613. X/**    skill_getpri - set min/max priority of our process.
  2614. X *
  2615. X *    void skill_getpri(int *low, int *high);
  2616. X *
  2617. X *    Entry    low = pointer to cell to receive Minimum value.
  2618. X *        high = pointer to cell to receive Maximum value.
  2619. X *
  2620. X *    Exit    values set.
  2621. X */
  2622. X
  2623. X
  2624. X#define min(a,b)    ((a) < (b) ? (a) : (b))
  2625. X
  2626. Xvoid skill_getpri(int *low, int *high)
  2627. X{ pcparms_t getparms;
  2628. X  pcinfo_t getinfo;
  2629. X  tsparms_t *tparms_p;
  2630. X  tsinfo_t *tinfo_p;
  2631. X
  2632. X/* first, read the current parameters for the process.        */
  2633. X
  2634. X  (void) memset(&getparms,0,sizeof(getparms));
  2635. X  getparms.pc_cid = PC_CLNULL;
  2636. X  if(priocntl(P_PID,P_MYID,PC_GETPARMS,(caddr_t) &getparms) == -1)
  2637. X    return;
  2638. X  tparms_p = (tsparms_t *) getparms.pc_clparms;
  2639. X
  2640. X/* get class info (assumes skill will be in the TS class, but    */
  2641. X/* will probably work OK for RT.                */
  2642. X
  2643. X  (void) memset(&getinfo,0,sizeof(getinfo));
  2644. X  getinfo.pc_cid = getparms.pc_cid;
  2645. X  if(priocntl(P_PID,P_MYID,PC_GETCLINFO,(caddr_t) &getinfo) == -1)
  2646. X    return;
  2647. X  tinfo_p = (tsinfo_t *) getinfo.pc_clinfo;
  2648. X
  2649. X  if(tparms_p->ts_uprilim == 0) {
  2650. X    *low = -abs(tinfo_p->ts_maxupri);
  2651. X    *high = abs(tinfo_p->ts_maxupri);
  2652. X  }
  2653. X  else {
  2654. X    *low = -min(abs(tparms_p->ts_uprilim),abs(tinfo_p->ts_maxupri));
  2655. X    *high = min(abs(tparms_p->ts_uprilim),abs(tinfo_p->ts_maxupri));
  2656. X  }
  2657. X  return;
  2658. X} /* skill_getpri */
  2659. X
  2660. X
  2661. X
  2662. X
  2663. X/**    skill_setpri - set priority of a process.
  2664. X *
  2665. X *    int skill_setpri(pid_t pid,int niceval);
  2666. X *
  2667. X *    Entry    pid = process id of target.
  2668. X *        niceval = priority adjustment.
  2669. X *
  2670. X *    Exit    returns -1 on error, 0 for ok.
  2671. X *
  2672. X *    Notes    Used in place of setpriority, which doesn't
  2673. X *        exist under SunOS5 (Solaris 2) except in BSD
  2674. X *        compatability mode.
  2675. X */
  2676. X
  2677. X
  2678. Xint skill_setpri(pid_t pid,int niceval)
  2679. X{ pcparms_t getparms, setprio;
  2680. X  pcinfo_t getinfo;
  2681. X  tsparms_t *tset_p;
  2682. X
  2683. X/* first, read the current parameters for the process.        */
  2684. X
  2685. X  (void) memset(&getparms,0,sizeof(getparms));
  2686. X  getparms.pc_cid = PC_CLNULL;
  2687. X  if(priocntl(P_PID,pid,PC_GETPARMS,(caddr_t) &getparms) == -1)
  2688. X    return(-1);
  2689. X
  2690. X/* get class info and check for TS class - we don't understand    */
  2691. X/* other classes.                        */
  2692. X
  2693. X  (void) memset(&getinfo,0,sizeof(getinfo));
  2694. X  getinfo.pc_cid = getparms.pc_cid;
  2695. X  if(priocntl(P_PID,pid,PC_GETCLINFO,(caddr_t) &getinfo) == -1)
  2696. X    return(-1);
  2697. X  if(strncmp(getinfo.pc_clname,"TS",2) != 0) {
  2698. X    fprintf(stderr,"%s: can't change priorities for class \"%s\"\n",
  2699. X     ProgName,getinfo.pc_clname);
  2700. X    return(-1);
  2701. X  }
  2702. X
  2703. X/* next, use that information plus the niceval to set priority.    */
  2704. X/* we use -niceval because skill thinks negative values are     */
  2705. X/* higher priority, but priocntl thinks positive is higher as I    */
  2706. X/* read the SunOS 5.1 priocntl(2) man page.            */
  2707. X
  2708. X  setprio.pc_cid = getparms.pc_cid;
  2709. X  tset_p = (tsparms_t *) setprio.pc_clparms;
  2710. X  tset_p->ts_uprilim = TS_NOCHANGE;
  2711. X  tset_p->ts_upri = -niceval;
  2712. X  if(priocntl(P_PID,pid,PC_SETPARMS,(caddr_t) &setprio) == -1)
  2713. X    return(-1);
  2714. X  return(0);
  2715. X} /* skill_setpri */
  2716. END_OF_FILE
  2717. if test 8314 -ne `wc -c <'machdep/sys-5r4.c'`; then
  2718.     echo shar: \"'machdep/sys-5r4.c'\" unpacked with wrong size!
  2719. fi
  2720. # end of 'machdep/sys-5r4.c'
  2721. fi
  2722. if test -f 'machdep/ultrix-22.c' -a "${1}" != "-c" ; then 
  2723.   echo shar: Will not clobber existing file \"'machdep/ultrix-22.c'\"
  2724. else
  2725. echo shar: Extracting \"'machdep/ultrix-22.c'\" \(10062 characters\)
  2726. sed "s/^X//" >'machdep/ultrix-22.c' <<'END_OF_FILE'
  2727. X#ifndef lint
  2728. Xstatic char rcsid[] = "$Header: ultrix-22.c,v 1.8 1994/06/26 04:16:41 forys Exp $";
  2729. X#endif
  2730. X
  2731. X/*
  2732. X**  This program may be freely redistributed for noncommercial purposes.
  2733. X**  This entire comment MUST remain intact.
  2734. X**
  2735. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  2736. X*/
  2737. X
  2738. X#define    NO_MEXTERN
  2739. X#include "conf.h"
  2740. X#undef    NO_MEXTERN
  2741. X
  2742. X#include <sys/user.h>
  2743. X#include <sys/proc.h>
  2744. X
  2745. X#include <stdio.h>
  2746. X
  2747. X/*
  2748. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  2749. X * routines and must be global.  Everyone seems to have their own
  2750. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  2751. X * signals available, not counting zero.
  2752. X */
  2753. Xchar *SigMap[] = { "0",
  2754. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  2755. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  2756. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  2757. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  2758. X    "XFSZ", "VTALRM", "PROF", "WINCH", "LOST", "USR1",    /* 25 - 30 */
  2759. X    "USR2", "32",                        /* 31 - 32 */
  2760. X};
  2761. Xint NSig = NSIG;
  2762. X
  2763. X#define    SETCMD(dst,src,maxlen) {            \
  2764. X    extern char *rindex();                \
  2765. X    if (maxlen > 0) src[maxlen] = '\0';        \
  2766. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  2767. X}
  2768. X
  2769. Xstatic char *TtyDevDir = "/dev";
  2770. X
  2771. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  2772. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  2773. Xint    SigPri;            /* signal to send or priority to set */
  2774. Xpid_T    MyPid;            /* pid of this process */
  2775. Xuid_T    MyUid;            /* uid of this process */
  2776. Xchar    *ProgName;        /* program name */
  2777. X
  2778. X/*
  2779. X * This is the machine-dependent initialization routine.
  2780. X *
  2781. X *   - The following global variables must be initialized:
  2782. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  2783. X *   - The working directory will be changed to that which contains the
  2784. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  2785. X *   - If possible, this routine should raise the priority of this process.
  2786. X */
  2787. Xvoid
  2788. XMdepInit(pname)
  2789. X    char *pname;
  2790. X{
  2791. X    extern char *rindex(), *SysErr();
  2792. X
  2793. X    MyPid = (pid_T) getpid();
  2794. X    MyUid = (uid_T) getuid();
  2795. X    SETCMD(ProgName, pname, 0)
  2796. X
  2797. X    /*
  2798. X     * If we are running as root, raise our priority to better
  2799. X     * catch runaway processes.
  2800. X     */
  2801. X    if (MyUid == ROOTUID)
  2802. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  2803. X
  2804. X    /*
  2805. X     * Determine what we are doing to processes we find.  We will
  2806. X     * either send them a signal (skill), or renice them (snice).
  2807. X     */
  2808. X    Skill = (strcmp(ProgName, "snice") != 0);
  2809. X
  2810. X    /*
  2811. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  2812. X     */
  2813. X    if (chdir(TtyDevDir) < 0) {
  2814. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  2815. X                SysErr());
  2816. X        exit(EX_SERR);
  2817. X    }
  2818. X
  2819. X    /*
  2820. X     * Set up minimum and maximum process priorities.
  2821. X     * Initialize SigPri to either default signal (`skill') or
  2822. X     * default priority (`snice').
  2823. X     */
  2824. X    PrioMin = PRIO_MIN;
  2825. X    PrioMax = PRIO_MAX;
  2826. X    SigPri = Skill? SIGTERM: 4;
  2827. X}
  2828. X
  2829. X/*
  2830. X * Carry out an action on a particular process.  If this is `skill',
  2831. X * then send the process a signal, otherwise this is `snice' so change
  2832. X * it's priority.
  2833. X *
  2834. X * If 0 is returned, the operation was successful, otherwise -1 is
  2835. X * returned and `errno' set.
  2836. X */
  2837. Xint
  2838. XMdepAction(pid)
  2839. X    pid_T pid;
  2840. X{
  2841. X    if (Skill)
  2842. X        return(kill((int)pid, SigPri));
  2843. X    else
  2844. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  2845. X}
  2846. X
  2847. X/*
  2848. X * Now, set up everything we need to write a GetProc() routine.
  2849. X */
  2850. X
  2851. X#include <sys/tty.h>
  2852. X#include <sys/file.h>
  2853. X#include <sys/vm.h>
  2854. X
  2855. X#include <machine/pte.h>
  2856. X
  2857. X#include <nlist.h>
  2858. X
  2859. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  2860. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  2861. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  2862. Xstatic char *kernf =    "/vmunix";    /* kernel image */
  2863. Xstatic int kmem = 0, mem = 0, swap = 0;
  2864. X
  2865. Xstatic struct nlist nl[] = {
  2866. X    { "_nproc" },
  2867. X#define    X_NPROC        0
  2868. X    { "_proc" },
  2869. X#define    X_PROC        1
  2870. X    { "" },
  2871. X#define    X_LAST        2
  2872. X};
  2873. X
  2874. Xstatic    int    nproc = -1;
  2875. Xstatic    struct    proc *procp;
  2876. X
  2877. X#define    NPROCS    32            /* number of procs to read at once */
  2878. X
  2879. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  2880. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  2881. X
  2882. Xextern    off_t lseek();
  2883. X
  2884. X/*
  2885. X * GetProc()
  2886. X *
  2887. X * Fill in and return a `struct ProcInfo' with information about the
  2888. X * next process.  If no processes are left, return NULL.
  2889. X */
  2890. Xstruct ProcInfo *
  2891. XGetProc()
  2892. X{
  2893. X    extern char *SysErr();
  2894. X    static struct user *GetUser();
  2895. X    static struct proc procs[NPROCS], *procsp;
  2896. X    static struct ProcInfo procinfo;
  2897. X    static struct tty tty;
  2898. X    register struct user *auser;
  2899. X    register struct proc *aproc;
  2900. X    static int thisproc = 0;
  2901. X
  2902. X    /*
  2903. X     * If this is our first time here, open various files,
  2904. X     * and set up the nlist.
  2905. X     */
  2906. X    if (nproc == -1) {
  2907. X        char *errstr = "%s: %s: %s\n";
  2908. X        int nfound;
  2909. X
  2910. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  2911. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  2912. X            exit(EX_SERR);
  2913. X        }
  2914. X
  2915. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  2916. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  2917. X            exit(EX_SERR);
  2918. X        }
  2919. X
  2920. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  2921. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  2922. X            exit(EX_SERR);
  2923. X        }
  2924. X
  2925. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  2926. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  2927. X            exit(EX_SERR);
  2928. X        }
  2929. X        if (nfound != 0) {
  2930. X            register int i;
  2931. X
  2932. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  2933. X                    ProgName);
  2934. X            for (i = 0; i < X_LAST; i++)
  2935. X                if (nl[i].n_type == 0)
  2936. X                    fprintf(stderr, " %s", nl[i].n_name);
  2937. X            (void) putc('\n', stderr);
  2938. X            exit(EX_SERR);
  2939. X        }
  2940. X
  2941. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  2942. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  2943. X    }
  2944. X
  2945. X    /*
  2946. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  2947. X     * by the number of proc structures we have read; when it reaches
  2948. X     * zero, we are finished (return NULL).
  2949. X     */
  2950. X    do {
  2951. X        while (thisproc == 0) {
  2952. X            int nread;
  2953. X            int psize;
  2954. X
  2955. X            if (nproc == 0)
  2956. X                return((struct ProcInfo *)NULL);
  2957. X
  2958. X            thisproc = MIN(NPROCS, nproc);
  2959. X            psize = thisproc * sizeof(struct proc);
  2960. X            nproc -= thisproc;
  2961. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  2962. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  2963. X                fprintf(stderr, "%s: read proc: %s\n",
  2964. X                        ProgName, SysErr());
  2965. X                return((struct ProcInfo *)NULL);
  2966. X            } else if (nread != psize) {
  2967. X                thisproc = nread / sizeof(struct proc);
  2968. X                nproc = 0;
  2969. X                fprintf(stderr, "%s: read proc: short read\n",
  2970. X                        ProgName);
  2971. X            }
  2972. X            procsp = procs;
  2973. X            procp += thisproc;
  2974. X        }
  2975. X
  2976. X        aproc = procsp++;
  2977. X        thisproc--;
  2978. X
  2979. X        if (aproc->p_stat != 0) {
  2980. X            /*
  2981. X             * Before we go through the trouble of reading
  2982. X             * in the user struct, let's make sure this isn't
  2983. X             * a "zombie" or "exiting" process.  If it is,
  2984. X             * we have all the information we need; fill in
  2985. X             * procinfo and return.
  2986. X             */
  2987. X            procinfo.pi_flags = 0;
  2988. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  2989. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  2990. X
  2991. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  2992. X                static char *zombie = "<defunct>";
  2993. X                procinfo.pi_flags |= PI_ZOMBIE;
  2994. X                procinfo.pi_cmd = zombie;
  2995. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  2996. X                static char *exiting = "<exiting>";
  2997. X                procinfo.pi_flags |= PI_SWEXIT;
  2998. X                procinfo.pi_cmd = exiting;
  2999. X            }
  3000. X
  3001. X            if (procinfo.pi_flags)
  3002. X                return(&procinfo);
  3003. X            else
  3004. X                auser = GetUser(aproc);
  3005. X        }
  3006. X
  3007. X    } while (aproc->p_stat == 0 || auser == NULL);
  3008. X
  3009. X    /*
  3010. X     * We now have a process (`aproc') and a user (`auser').
  3011. X     * Fill in the rest of `procinfo'.
  3012. X     */
  3013. X    if (aproc->p_ttyp != 0 &&    /* has a controlling terminal? */
  3014. X        lseek(kmem, (off_t)aproc->p_ttyp, L_SET) != -1 &&
  3015. X        read(kmem, (char *)&tty, sizeof(tty)) == sizeof(tty)) {
  3016. X        procinfo.pi_flags |= PI_CTLTTY;
  3017. X        procinfo.pi_tty = (tty_T) tty.t_dev;
  3018. X    }
  3019. X
  3020. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  3021. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  3022. X        procinfo.pi_flags |= PI_ASKUSR;
  3023. X    } else                 /* set path-stripped command name */
  3024. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  3025. X
  3026. X    return(&procinfo);
  3027. X}
  3028. X
  3029. X#define    SKRD(file, src, dst, size)            \
  3030. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  3031. X    (read(file, (char *)(dst), (size)) != (size))
  3032. X
  3033. X/*
  3034. X * GetWord(loc)
  3035. X *
  3036. X * Read in word at `loc' from kernel virtual memory.
  3037. X * If an error occurs, call exit(2) with EX_SERR.
  3038. X */
  3039. Xstatic int
  3040. XGetWord(loc)
  3041. X    off_t loc;
  3042. X{
  3043. X    int val;
  3044. X
  3045. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  3046. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  3047. X                ProgName, (u_long)loc, kmemf);
  3048. X        exit(EX_SERR);
  3049. X    }
  3050. X    return (val);
  3051. X}
  3052. X
  3053. X#define    SW_UADDR    dtob(aproc->p_swaddr)
  3054. X#define    SW_UBYTES    sizeof(struct user)
  3055. X
  3056. X/*
  3057. X * GetUser(aproc)
  3058. X *
  3059. X * Read in the user struct for `aproc' and return a pointer to it.
  3060. X * If an error occurs, return NULL.
  3061. X */
  3062. Xstatic struct user *
  3063. XGetUser(aproc)
  3064. X    struct proc *aproc;
  3065. X{
  3066. X    static char *WarnMsg = "Warning: can't read ";
  3067. X    static union {
  3068. X        struct user user;
  3069. X        char upgs[UPAGES][NBPG];
  3070. X    } u;
  3071. X    static struct pte uptes[UPAGES];
  3072. X    register int i, nbytes;
  3073. X
  3074. X    /*
  3075. X     * If process is not in core, we simply snarf it's user struct
  3076. X     * from the swap device.
  3077. X     */
  3078. X    if ((aproc->p_flag & SLOAD) == 0) {
  3079. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  3080. X            if (Wflag)
  3081. X                printf("%su for pid %d from %s\n",
  3082. X                       WarnMsg, aproc->p_pid, swapf);
  3083. X            return ((struct user *)NULL);
  3084. X        }
  3085. X        return (&u.user);
  3086. X    }
  3087. X
  3088. X    /*
  3089. X     * Process is in core.  Follow p_addr to read in the page
  3090. X     * table entries that map the u-area and then read in the
  3091. X     * physical pages that comprise the u-area.
  3092. X     *
  3093. X     * If at any time, an lseek() or read() fails, print a warning
  3094. X     * message (if `Wflag' is set) and return NULL.
  3095. X     */
  3096. X    if (SKRD(kmem, aproc->p_addr, uptes, sizeof(uptes))) {
  3097. X        if (Wflag)
  3098. X            printf("%suser pt for pid %d from %s\n",
  3099. X                   WarnMsg, aproc->p_pid, kmemf);
  3100. X        return ((struct user *)NULL);
  3101. X    }
  3102. X
  3103. X    nbytes = sizeof(struct user);
  3104. X    for (i = 0; i < UPAGES && nbytes > 0; i++) {
  3105. X        if (SKRD(mem, ptob(uptes[i].pg_pfnum), u.upgs[i], NBPG)) {
  3106. X            if (Wflag)
  3107. X                printf("%suser page %u for pid %d from %s\n",
  3108. X                       WarnMsg, uptes[i].pg_pfnum,
  3109. X                       aproc->p_pid, memf);
  3110. X            return((struct user *)NULL);
  3111. X        }
  3112. X        nbytes -= NBPG;
  3113. X    }
  3114. X    return (&u.user);
  3115. X}
  3116. END_OF_FILE
  3117. if test 10062 -ne `wc -c <'machdep/ultrix-22.c'`; then
  3118.     echo shar: \"'machdep/ultrix-22.c'\" unpacked with wrong size!
  3119. fi
  3120. # end of 'machdep/ultrix-22.c'
  3121. fi
  3122. if test -f 'machdep/umips-21.c' -a "${1}" != "-c" ; then 
  3123.   echo shar: Will not clobber existing file \"'machdep/umips-21.c'\"
  3124. else
  3125. echo shar: Extracting \"'machdep/umips-21.c'\" \(9898 characters\)
  3126. sed "s/^X//" >'machdep/umips-21.c' <<'END_OF_FILE'
  3127. X#ifndef lint
  3128. Xstatic char rcsid[] = "$Header: umips-21.c,v 1.8 1994/06/26 04:17:49 forys Exp $";
  3129. X#endif
  3130. X
  3131. X/*
  3132. X**  This program may be freely redistributed for noncommercial purposes.
  3133. X**  This entire comment MUST remain intact.
  3134. X**
  3135. X**  Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us)
  3136. X*/
  3137. X
  3138. X#define    NO_MEXTERN
  3139. X#include "conf.h"
  3140. X#undef    NO_MEXTERN
  3141. X
  3142. X#include <sys/user.h>
  3143. X#include <sys/proc.h>
  3144. X
  3145. X#include <stdio.h>
  3146. X
  3147. X/*
  3148. X * Define SigNames, NSig, and TtyDevDir here; they are used by other
  3149. X * routines and must be global.  Everyone seems to have their own
  3150. X * idea as to what NSIG should be.  Here, `NSig' is the number of
  3151. X * signals available, not counting zero.
  3152. X */
  3153. Xchar *SigMap[] = { "0",
  3154. X    "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",        /*  1 -  6 */
  3155. X    "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",        /*  7 - 12 */
  3156. X    "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP",        /* 13 - 18 */
  3157. X    "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",        /* 19 - 24 */
  3158. X    "XFSZ", "VTALRM", "PROF", "WINCH", "LOST", "USR1",    /* 25 - 30 */
  3159. X    "USR2", "32",                        /* 31 - 32 */
  3160. X};
  3161. Xint NSig = NSIG;
  3162. X
  3163. X#define    SETCMD(dst,src,maxlen) {            \
  3164. X    extern char *rindex();                \
  3165. X    if (maxlen > 0) src[maxlen] = '\0';        \
  3166. X    dst = (dst = rindex(src, '/')) ? ++dst: src;    \
  3167. X}
  3168. X
  3169. Xstatic char *TtyDevDir = "/dev";
  3170. X
  3171. Xint    Skill;            /* set 1 if running `skill', 0 if `snice' */
  3172. Xint    PrioMin, PrioMax;    /* min and max process priorities */
  3173. Xint    SigPri;            /* signal to send or priority to set */
  3174. Xpid_T    MyPid;            /* pid of this process */
  3175. Xuid_T    MyUid;            /* uid of this process */
  3176. Xchar    *ProgName;        /* program name */
  3177. X
  3178. X/*
  3179. X * This is the machine-dependent initialization routine.
  3180. X *
  3181. X *   - The following global variables must be initialized:
  3182. X *     MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri
  3183. X *   - The working directory will be changed to that which contains the
  3184. X *     tty devices (`TtyDevDir'); this makes argument parsing go faster.
  3185. X *   - If possible, this routine should raise the priority of this process.
  3186. X */
  3187. Xvoid
  3188. XMdepInit(pname)
  3189. X    char *pname;
  3190. X{
  3191. X    extern char *rindex(), *SysErr();
  3192. X
  3193. X    MyPid = (pid_T) getpid();
  3194. X    MyUid = (uid_T) getuid();
  3195. X    SETCMD(ProgName, pname, 0)
  3196. X
  3197. X    /*
  3198. X     * If we are running as root, raise our priority to better
  3199. X     * catch runaway processes.
  3200. X     */
  3201. X    if (MyUid == ROOTUID)
  3202. X        (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN);
  3203. X
  3204. X    /*
  3205. X     * Determine what we are doing to processes we find.  We will
  3206. X     * either send them a signal (skill), or renice them (snice).
  3207. X     */
  3208. X    Skill = (strcmp(ProgName, "snice") != 0);
  3209. X
  3210. X    /*
  3211. X     * chdir to `TtyDevDir' to speed up tty argument parsing.
  3212. X     */
  3213. X    if (chdir(TtyDevDir) < 0) {
  3214. X        fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir,
  3215. X                SysErr());
  3216. X        exit(EX_SERR);
  3217. X    }
  3218. X
  3219. X    /*
  3220. X     * Set up minimum and maximum process priorities.
  3221. X     * Initialize SigPri to either default signal (`skill') or
  3222. X     * default priority (`snice').
  3223. X     */
  3224. X    PrioMin = PRIO_MIN;
  3225. X    PrioMax = PRIO_MAX;
  3226. X    SigPri = Skill? SIGTERM: 4;
  3227. X}
  3228. X
  3229. X/*
  3230. X * Carry out an action on a particular process.  If this is `skill',
  3231. X * then send the process a signal, otherwise this is `snice' so change
  3232. X * it's priority.
  3233. X *
  3234. X * If 0 is returned, the operation was successful, otherwise -1 is
  3235. X * returned and `errno' set.
  3236. X */
  3237. Xint
  3238. XMdepAction(pid)
  3239. X    pid_T pid;
  3240. X{
  3241. X    if (Skill)
  3242. X        return(kill((int)pid, SigPri));
  3243. X    else
  3244. X        return(setpriority(PRIO_PROCESS, (int)pid, SigPri));
  3245. X}
  3246. X
  3247. X/*
  3248. X * Now, set up everything we need to write a GetProc() routine.
  3249. X */
  3250. X
  3251. X#include <sys/file.h>
  3252. X#include <sys/vm.h>
  3253. X
  3254. X#include <machine/pte.h>
  3255. X
  3256. X#include <nlist.h>
  3257. X
  3258. Xstatic char *kmemf =    "/dev/kmem";    /* window into kernel virtual memory */
  3259. Xstatic char *memf =    "/dev/mem";    /* window into physical memory */
  3260. Xstatic char *swapf =    "/dev/drum";    /* paging device */
  3261. Xstatic char *kernf =    "/vmunix";    /* kernel image */
  3262. Xstatic int kmem = 0, mem = 0, swap = 0;
  3263. X
  3264. Xstatic struct nlist nl[] = {
  3265. X    { "_nproc" },
  3266. X#define    X_NPROC        0
  3267. X    { "_proc" },
  3268. X#define    X_PROC        1
  3269. X    { "" },
  3270. X#define    X_LAST        2
  3271. X};
  3272. X
  3273. Xstatic    int    nproc = -1;
  3274. Xstatic    struct    proc *procp;
  3275. X
  3276. X#define    NPROCS    32            /* number of procs to read at once */
  3277. X
  3278. Xstatic    char    *pidmap[] = { "swapper", "init", "pagedaemon" };
  3279. Xstatic    int    pidmapsiz = sizeof(pidmap) / sizeof(pidmap[0]);
  3280. X
  3281. Xextern    off_t lseek();
  3282. X
  3283. X/*
  3284. X * GetProc()
  3285. X *
  3286. X * Fill in and return a `struct ProcInfo' with information about the
  3287. X * next process.  If no processes are left, return NULL.
  3288. X */
  3289. Xstruct ProcInfo *
  3290. XGetProc()
  3291. X{
  3292. X    extern char *SysErr();
  3293. X    static struct user *GetUser();
  3294. X    static struct proc procs[NPROCS], *procsp;
  3295. X    static struct ProcInfo procinfo;
  3296. X    register struct user *auser;
  3297. X    register struct proc *aproc;
  3298. X    static int thisproc = 0;
  3299. X
  3300. X    /*
  3301. X     * If this is our first time here, open various files,
  3302. X     * and set up the nlist.
  3303. X     */
  3304. X    if (nproc == -1) {
  3305. X        char *errstr = "%s: %s: %s\n";
  3306. X        int nfound;
  3307. X
  3308. X        if ((kmem=open(kmemf, 0)) < 0) {    /* open kmem */
  3309. X            fprintf(stderr, errstr, ProgName, kmemf, SysErr());
  3310. X            exit(EX_SERR);
  3311. X        }
  3312. X
  3313. X        if ((mem=open(memf, 0)) < 0) {        /* open mem */
  3314. X            fprintf(stderr, errstr, ProgName, memf, SysErr());
  3315. X            exit(EX_SERR);
  3316. X        }
  3317. X
  3318. X        if ((swap=open(swapf, 0)) < 0) {    /* open swap device */
  3319. X            fprintf(stderr, errstr, ProgName, swapf, SysErr());
  3320. X            exit(EX_SERR);
  3321. X        }
  3322. X
  3323. X        if ((nfound=nlist(kernf, nl)) < 0) {    /* kernel name list */
  3324. X            fprintf(stderr, errstr, ProgName, kernf,"no name list");
  3325. X            exit(EX_SERR);
  3326. X        }
  3327. X        if (nfound != 0) {
  3328. X            register int i;
  3329. X
  3330. X            fprintf(stderr, "%s: nlist: unresolved symbols:",
  3331. X                    ProgName);
  3332. X            for (i = 0; i < X_LAST; i++)
  3333. X                if (nl[i].n_type == 0)
  3334. X                    fprintf(stderr, " %s", nl[i].n_name);
  3335. X            (void) putc('\n', stderr);
  3336. X            exit(EX_SERR);
  3337. X        }
  3338. X
  3339. X        procp = (struct proc *)GetWord((off_t)nl[X_PROC].n_value);
  3340. X        nproc = GetWord((off_t)nl[X_NPROC].n_value);
  3341. X    }
  3342. X
  3343. X    /*
  3344. X     * Read in NPROCS proc structures at-a-time.  Decrement `nproc'
  3345. X     * by the number of proc structures we have read; when it reaches
  3346. X     * zero, we are finished (return NULL).
  3347. X     */
  3348. X    do {
  3349. X        while (thisproc == 0) {
  3350. X            int nread;
  3351. X            int psize;
  3352. X
  3353. X            if (nproc == 0)
  3354. X                return((struct ProcInfo *)NULL);
  3355. X
  3356. X            thisproc = MIN(NPROCS, nproc);
  3357. X            psize = thisproc * sizeof(struct proc);
  3358. X            nproc -= thisproc;
  3359. X            if (lseek(kmem, (off_t)procp, L_SET) == -1 ||
  3360. X                (nread = read(kmem, (char *)procs, psize)) < 0) {
  3361. X                fprintf(stderr, "%s: read proc: %s\n",
  3362. X                        ProgName, SysErr());
  3363. X                return((struct ProcInfo *)NULL);
  3364. X            } else if (nread != psize) {
  3365. X                thisproc = nread / sizeof(struct proc);
  3366. X                nproc = 0;
  3367. X                fprintf(stderr, "%s: read proc: short read\n",
  3368. X                        ProgName);
  3369. X            }
  3370. X            procsp = procs;
  3371. X            procp += thisproc;
  3372. X        }
  3373. X
  3374. X        aproc = procsp++;
  3375. X        thisproc--;
  3376. X
  3377. X        if (aproc->p_stat != 0) {
  3378. X            /*
  3379. X             * Before we go through the trouble of reading
  3380. X             * in the user struct, let's make sure this isn't
  3381. X             * a "zombie" or "exiting" process.  If it is,
  3382. X             * we have all the information we need; fill in
  3383. X             * procinfo and return.
  3384. X             */
  3385. X            procinfo.pi_flags = 0;
  3386. X            procinfo.pi_pid = (pid_T) aproc->p_pid;
  3387. X            procinfo.pi_uid = (uid_T) aproc->p_uid;
  3388. X
  3389. X            if (aproc->p_stat == SZOMB) {        /* zombie */
  3390. X                static char *zombie = "<defunct>";
  3391. X                procinfo.pi_flags |= PI_ZOMBIE;
  3392. X                procinfo.pi_cmd = zombie;
  3393. X            } else if (aproc->p_flag & SWEXIT) {    /* exiting */
  3394. X                static char *exiting = "<exiting>";
  3395. X                procinfo.pi_flags |= PI_SWEXIT;
  3396. X                procinfo.pi_cmd = exiting;
  3397. X            }
  3398. X
  3399. X            if (procinfo.pi_flags)
  3400. X                return(&procinfo);
  3401. X            else
  3402. X                auser = GetUser(aproc);
  3403. X        }
  3404. X
  3405. X    } while (aproc->p_stat == 0 || auser == NULL);
  3406. X
  3407. X    /*
  3408. X     * We now have a process (`aproc') and a user (`auser').
  3409. X     * Fill in the rest of `procinfo'.
  3410. X     */
  3411. X    if (auser->u_ttyp != 0) {    /* has a controlling tty */
  3412. X        procinfo.pi_flags |= PI_CTLTTY;
  3413. X        procinfo.pi_tty = (tty_T) auser->u_ttyd;
  3414. X    }
  3415. X
  3416. X    if (aproc->p_pid < pidmapsiz) {    /* special */
  3417. X        procinfo.pi_cmd = pidmap[aproc->p_pid];
  3418. X        procinfo.pi_flags |= PI_ASKUSR;
  3419. X    } else                 /* set path-stripped command name */
  3420. X        SETCMD(procinfo.pi_cmd, auser->u_comm, MAXCOMLEN)
  3421. X
  3422. X    return(&procinfo);
  3423. X}
  3424. X
  3425. X#define    SKRD(file, src, dst, size)            \
  3426. X    (lseek(file, (off_t)(src), L_SET) == -1) ||    \
  3427. X    (read(file, (char *)(dst), (size)) != (size))
  3428. X
  3429. X/*
  3430. X * GetWord(loc)
  3431. X *
  3432. X * Read in word at `loc' from kernel virtual memory.
  3433. X * If an error occurs, call exit(2) with EX_SERR.
  3434. X */
  3435. Xstatic int
  3436. XGetWord(loc)
  3437. X    off_t loc;
  3438. X{
  3439. X    int val;
  3440. X
  3441. X    if (SKRD(kmem, loc, &val, sizeof(val))) {
  3442. X        fprintf(stderr, "%s: can't read word at %lx in %s\n",
  3443. X                ProgName, (u_long)loc, kmemf);
  3444. X        exit(EX_SERR);
  3445. X    }
  3446. X    return (val);
  3447. X}
  3448. X
  3449. X#define    SW_UADDR    dtob(aproc->p_swaddr)
  3450. X#define    SW_UBYTES    sizeof(struct user)
  3451. X
  3452. X/*
  3453. X * GetUser(aproc)
  3454. X *
  3455. X * Read in the user struct for `aproc' and return a pointer to it.
  3456. X * If an error occurs, return NULL.
  3457. X */
  3458. Xstatic struct user *
  3459. XGetUser(aproc)
  3460. X    struct proc *aproc;
  3461. X{
  3462. X    static char *WarnMsg = "Warning: can't read ";
  3463. X    static union {
  3464. X        struct user user;
  3465. X        char upgs[UPAGES][NBPG];
  3466. X    } u;
  3467. X    static struct pte uptes[UPAGES];
  3468. X    register int i, nbytes;
  3469. X
  3470. X    /*
  3471. X     * If process is not in core, we simply snarf it's user struct
  3472. X     * from the swap device.
  3473. X     */
  3474. X    if ((aproc->p_flag & SLOAD) == 0) {
  3475. X        if (SKRD(swap, SW_UADDR, &u.user, SW_UBYTES)) {
  3476. X            if (Wflag)
  3477. X                printf("%su for pid %d from %s\n",
  3478. X                       WarnMsg, aproc->p_pid, swapf);
  3479. X            return ((struct user *)NULL);
  3480. X        }
  3481. X        return (&u.user);
  3482. X    }
  3483. X
  3484. X    /*
  3485. X     * Process is in core.  Follow p_addr to read in the page
  3486. X     * table entries that map the u-area and then read in the
  3487. X     * physical pages that comprise the u-area.
  3488. X     *
  3489. X     * If at any time, an lseek() or read() fails, print a warning
  3490. X     * message (if `Wflag' is set) and return NULL.
  3491. X     */
  3492. X    if (SKRD(kmem, aproc->p_addr, uptes, sizeof(uptes))) {
  3493. X        if (Wflag)
  3494. X            printf("%suser pt for pid %d from %s\n",
  3495. X                   WarnMsg, aproc->p_pid, kmemf);
  3496. X        return ((struct user *)NULL);
  3497. X    }
  3498. X
  3499. X    nbytes = sizeof(struct user);
  3500. X    for (i = 0; i < UPAGES && nbytes > 0; i++) {
  3501. X        if (SKRD(mem, ptob(uptes[i].pg_pfnum), u.upgs[i], NBPG)) {
  3502. X            if (Wflag)
  3503. X                printf("%suser page %u for pid %d from %s\n",
  3504. X                       WarnMsg, uptes[i].pg_pfnum,
  3505. X                       aproc->p_pid, memf);
  3506. X            return((struct user *)NULL);
  3507. X        }
  3508. X        nbytes -= NBPG;
  3509. X    }
  3510. X    return (&u.user);
  3511. X}
  3512. END_OF_FILE
  3513. if test 9898 -ne `wc -c <'machdep/umips-21.c'`; then
  3514.     echo shar: \"'machdep/umips-21.c'\" unpacked with wrong size!
  3515. fi
  3516. # end of 'machdep/umips-21.c'
  3517. fi
  3518. echo shar: End of archive 2 \(of 3\).
  3519. cp /dev/null ark2isdone
  3520. MISSING=""
  3521. for I in 1 2 3 ; do
  3522.     if test ! -f ark${I}isdone ; then
  3523.     MISSING="${MISSING} ${I}"
  3524.     fi
  3525. done
  3526. if test "${MISSING}" = "" ; then
  3527.     echo You have unpacked all 3 archives.
  3528.     rm -f ark[1-9]isdone
  3529. else
  3530.     echo You still need to unpack the following archives:
  3531.     echo "        " ${MISSING}
  3532. fi
  3533. ##  End of shell archive.
  3534. exit 0
  3535.