home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / unix / bsd / 4495 < prev    next >
Encoding:
Text File  |  1992-08-20  |  29.7 KB  |  1,293 lines

  1. Xref: sparky comp.unix.bsd:4495 comp.bugs.4bsd:206
  2. Path: sparky!uunet!zephyr.ens.tek.com!psgrain!m2xenix!agora!davidg
  3. From: davidg@agora.rain.com (David Greenman)
  4. Newsgroups: comp.unix.bsd,comp.bugs.4bsd
  5. Subject: Fixes for ps's many problems (386BSD)
  6. Message-ID: <1992Aug20.131718.28995@agora.uucp>
  7. Date: 20 Aug 92 13:17:18 GMT
  8. Sender: davidg@agora.uucp (David Greenman)
  9. Organization: Open Communications Forum
  10. Lines: 1281
  11.  
  12.  
  13.    I've been asked by several people to post all the patches necessary
  14. to fix the 'ps' command.
  15.    If you have already installed these fixes, please note fix 2 which
  16. was not in my previous 'ps' patches.
  17.    What follows are patches to ps.c and ps/nlist.c (for ps), a patch to
  18. kvm_mkdb/nlist.c, and a replacement kvm.c (patches are too large).
  19.  
  20. These fix:
  21.  
  22. (ps.c)
  23. 1) The Floating Exception bug when sorting by %CPU (implied with ps aux).
  24.  
  25. (ps/nlist.c, kvm.c)
  26. 2) Resident memory size (RSS) and %MEM are now correct.
  27.  
  28. (kvm.c)
  29. 3) Command+arguments are now properly returned if the information is
  30.    available (not paged out).
  31.  
  32. (kvm.c, kvm_mkdb/nlist.c)
  33. 4) Kernel namelist caching will now work as long as vers.o is the first
  34.    object linked in the kernel (cgd's new Makefile.i386 will do this)
  35.    This speeds up 'ps' & 'w' by about a factor of 3.
  36.  
  37. ---
  38. David Greenman
  39. davidg%implode@percy.rain.com
  40.  
  41. ------------------------------------------------------------------------
  42. *** /usr/src/bin/ps/ps.c.01orig    Mon Jul  1 17:54:45 1991
  43. --- /usr/src/bin/ps/ps.c    Sun Aug  9 06:45:30 1992
  44. ***************
  45. *** 78,83 ****
  46. --- 78,84 ----
  47.   
  48.   uid_t    getuid();
  49.   char    *ttyname();
  50. + double    getpcpu();
  51.   
  52.   char dfmt[] = "pid tt state time command";
  53.   char jfmt[] = "user pid ppid pgid sess jobc state tt time command";
  54. *** /usr/src/bin/ps/nlist.c.01orig    Mon Jul  1 18:00:23 1991
  55. --- /usr/src/bin/ps/nlist.c    Fri Aug 14 10:14:51 1992
  56. ***************
  57. *** 101,106 ****
  58. --- 101,107 ----
  59.           eval = rval = 1;
  60.       }
  61.       mempages -= tmp;
  62. +     mempages = mempages / NBPG;
  63.   #else
  64.       if (kread(X_ECMX, mempages)) {
  65.           (void)fprintf(stderr, "ps: ecmx: %s\n", kvm_geterr());
  66. *** /usr/src/usr.sbin/kvm_mkdb/nlist.c.01orig    Sat Apr 27 16:23:58 1991
  67. --- /usr/src/usr.sbin/kvm_mkdb/nlist.c    Wed Aug  5 03:39:37 1992
  68. ***************
  69. *** 138,143 ****
  70. --- 138,146 ----
  71.   #ifdef vax
  72.               rel_off = nbuf.n_value & ~KERNBASE;
  73.   #endif
  74. + #ifdef i386
  75. +             rel_off = ((nbuf.n_value & ~KERNBASE) + CLBYTES);
  76. + #endif
  77.               /*
  78.                * When loaded, data is rounded to next page cluster
  79.                * after text, but not in file.
  80.  
  81. ------------------------------------------------------------------------
  82. /*-
  83.  * Copyright (c) 1989 The Regents of the University of California.
  84.  * All rights reserved.
  85.  *
  86.  * Redistribution and use in source and binary forms, with or without
  87.  * modification, are permitted provided that the following conditions
  88.  * are met:
  89.  * 1. Redistributions of source code must retain the above copyright
  90.  *    notice, this list of conditions and the following disclaimer.
  91.  * 2. Redistributions in binary form must reproduce the above copyright
  92.  *    notice, this list of conditions and the following disclaimer in the
  93.  *    documentation and/or other materials provided with the distribution.
  94.  * 3. All advertising materials mentioning features or use of this software
  95.  *    must display the following acknowledgement:
  96.  *    This product includes software developed by the University of
  97.  *    California, Berkeley and its contributors.
  98.  * 4. Neither the name of the University nor the names of its contributors
  99.  *    may be used to endorse or promote products derived from this software
  100.  *    without specific prior written permission.
  101.  *
  102.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  103.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  104.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  105.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  106.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  107.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  108.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  109.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  110.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  111.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  112.  * SUCH DAMAGE.
  113.  */
  114.  
  115. /*
  116.  *  Updated for 386BSD 0.1 by David Greenman (davidg%implode@percy.rain.com)
  117.  *     and Paul Kranenburg (pk@cs.few.eur.nl)
  118.  *  20-Aug-1992
  119.  */
  120.  
  121. #if defined(LIBC_SCCS) && !defined(lint)
  122. static char sccsid[] = "@(#)kvm.c    5.18 (Berkeley) 5/7/91";
  123. #endif /* LIBC_SCCS and not lint */
  124.  
  125. #include <sys/param.h>
  126. #include <sys/user.h>
  127. #include <sys/proc.h>
  128. #include <sys/ioctl.h>
  129. #include <sys/kinfo.h>
  130. #include <sys/tty.h>
  131. #include <machine/vmparam.h>
  132. #include <fcntl.h>
  133. #include <nlist.h>
  134. #include <kvm.h>
  135. #include <ndbm.h>
  136. #include <limits.h>
  137. #include <paths.h>
  138. #include <stdio.h>
  139. #include <string.h>
  140.  
  141. #ifdef SPPWAIT
  142. #define NEWVM
  143. #endif
  144.  
  145. #ifdef NEWVM
  146. #define    btop(x)        (((unsigned)(x)) >> PGSHIFT)    /* XXX */
  147. #define    ptob(x)        ((caddr_t)((x) << PGSHIFT))    /* XXX */
  148. #include <vm/vm.h>    /* ??? kinfo_proc currently includes this*/
  149. #include <sys/kinfo_proc.h>
  150. #ifdef hp300
  151. #include <hp300/hp300/pte.h>
  152. #endif
  153. #else /* NEWVM */
  154. #include <machine/pte.h>
  155. #include <sys/vmmac.h>
  156. #include <sys/text.h>
  157. #endif /* NEWVM */
  158.  
  159. /*
  160.  * files
  161.  */
  162. static    const char *unixf, *memf, *kmemf, *swapf;
  163. static    int unixx, mem, kmem, swap;
  164. static    DBM *db;
  165. /*
  166.  * flags
  167.  */
  168. static    int deadkernel;
  169. static    int kvminit = 0;
  170. static    int kvmfilesopen = 0;
  171. /*
  172.  * state
  173.  */
  174. static    struct kinfo_proc *kvmprocbase, *kvmprocptr;
  175. static    int kvmnprocs;
  176. /*
  177.  * u. buffer
  178.  */
  179. static union {
  180.     struct    user user;
  181.     char    upages[UPAGES][NBPG];
  182. } user;
  183. /*
  184.  * random other stuff
  185.  */
  186. #ifndef NEWVM
  187. static    struct pte *Usrptmap, *usrpt;
  188. static    struct    pte *Sysmap;
  189. static    int    Syssize;
  190. #endif
  191. static    int    dmmin, dmmax;
  192. static    int    pcbpf;
  193. static    int    argaddr0;    /* XXX */
  194. static    int    argaddr1;
  195. static    int    nswap;
  196. static    char    *tmp;
  197. #if defined(hp300)
  198. static    int    lowram;
  199. static    struct ste *Sysseg;
  200. #endif
  201. #if defined(i386)
  202. static    struct pde *PTD;
  203. #endif
  204.  
  205. #define basename(cp)    ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
  206. #define    MAXSYMSIZE    256
  207.  
  208. #if defined(hp300)
  209. #define pftoc(f)    ((f) - lowram)
  210. #define iskva(v)    (1)
  211. #endif
  212.  
  213. #ifndef pftoc
  214. #define pftoc(f)    (f)
  215. #endif
  216. #ifndef iskva
  217. #define iskva(v)    ((u_long)(v) & KERNBASE)
  218. #endif
  219.  
  220. static struct nlist nl[] = {
  221.     { "_Usrptmap" },
  222. #define    X_USRPTMAP    0
  223.     { "_usrpt" },
  224. #define    X_USRPT        1
  225.     { "_nswap" },
  226. #define    X_NSWAP        2
  227.     { "_dmmin" },
  228. #define    X_DMMIN        3
  229.     { "_dmmax" },
  230. #define    X_DMMAX        4
  231.     /*
  232.      * everything here and down, only if a dead kernel
  233.      */
  234.     { "_Sysmap" },
  235. #define    X_SYSMAP    5
  236. #define    X_DEADKERNEL    X_SYSMAP
  237.     { "_Syssize" },
  238. #define    X_SYSSIZE    6
  239.     { "_allproc" },
  240. #define X_ALLPROC    7
  241.     { "_zombproc" },
  242. #define X_ZOMBPROC    8
  243.     { "_nproc" },
  244. #define    X_NPROC        9
  245. #define    X_LAST        9
  246. #if defined(hp300)
  247.     { "_Sysseg" },
  248. #define    X_SYSSEG    (X_LAST+1)
  249.     { "_lowram" },
  250. #define    X_LOWRAM    (X_LAST+2)
  251. #endif
  252. #if defined(i386)
  253.     { "_IdlePTD" },
  254. #define    X_IdlePTD    (X_LAST+1)
  255. #endif
  256.     { "" },
  257. };
  258.  
  259. static off_t Vtophys();
  260. static void klseek(), seterr(), setsyserr(), vstodb();
  261. static int getkvars(), kvm_doprocs(), kvm_init();
  262.  
  263. /*
  264.  * returns     0 if files were opened now,
  265.  *         1 if files were already opened,
  266.  *        -1 if files could not be opened.
  267.  */
  268. kvm_openfiles(uf, mf, sf)
  269.     const char *uf, *mf, *sf; 
  270. {
  271.     if (kvmfilesopen)
  272.         return (1);
  273.     unixx = mem = kmem = swap = -1;
  274.     unixf = (uf == NULL) ? _PATH_UNIX : uf; 
  275.     memf = (mf == NULL) ? _PATH_MEM : mf;
  276.  
  277.     if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
  278.         setsyserr("can't open %s", unixf);
  279.         goto failed;
  280.     }
  281.     if ((mem = open(memf, O_RDONLY, 0)) == -1) {
  282.         setsyserr("can't open %s", memf);
  283.         goto failed;
  284.     }
  285.     if (sf != NULL)
  286.         swapf = sf;
  287.     if (mf != NULL) {
  288.         deadkernel++;
  289.         kmemf = mf;
  290.         kmem = mem;
  291.         swap = -1;
  292.     } else {
  293.         kmemf = _PATH_KMEM;
  294.         if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
  295.             setsyserr("can't open %s", kmemf);
  296.             goto failed;
  297.         }
  298.         swapf = (sf == NULL) ?  _PATH_DRUM : sf;
  299.         /*
  300.          * live kernel - avoid looking up nlist entries
  301.          * past X_DEADKERNEL.
  302.          */
  303.         nl[X_DEADKERNEL].n_name = "";
  304.     }
  305.     if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
  306.         seterr("can't open %s", swapf);
  307.         goto failed;
  308.     }
  309.     kvmfilesopen++;
  310.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/
  311.         return (-1);
  312.     return (0);
  313. failed:
  314.     kvm_close();
  315.     return (-1);
  316. }
  317.  
  318. static
  319. kvm_init(uf, mf, sf)
  320.     char *uf, *mf, *sf;
  321. {
  322.     if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
  323.         return (-1);
  324.     if (getkvars() == -1)
  325.         return (-1);
  326.     kvminit = 1;
  327.  
  328.     return (0);
  329. }
  330.  
  331. kvm_close()
  332. {
  333.     if (unixx != -1) {
  334.         close(unixx);
  335.         unixx = -1;
  336.     }
  337.     if (kmem != -1) {
  338.         if (kmem != mem)
  339.             close(kmem);
  340.         /* otherwise kmem is a copy of mem, and will be closed below */
  341.         kmem = -1;
  342.     }
  343.     if (mem != -1) {
  344.         close(mem);
  345.         mem = -1;
  346.     }
  347.     if (swap != -1) {
  348.         close(swap);
  349.         swap = -1;
  350.     }
  351.     if (db != NULL) {
  352.         dbm_close(db);
  353.         db = NULL;
  354.     }
  355.     kvminit = 0;
  356.     kvmfilesopen = 0;
  357.     deadkernel = 0;
  358. #ifndef NEWVM
  359.     if (Sysmap) {
  360.         free(Sysmap);
  361.         Sysmap = NULL;
  362.     }
  363. #endif
  364. }
  365.  
  366. kvm_nlist(nl)
  367.     struct nlist *nl;
  368. {
  369.     datum key, data;
  370.     char dbname[MAXPATHLEN];
  371.     char dbversion[_POSIX2_LINE_MAX];
  372.     char kversion[_POSIX2_LINE_MAX];
  373.     int dbversionlen;
  374.     char symbuf[MAXSYMSIZE];
  375.     struct nlist nbuf, *n;
  376.     int num, did;
  377.  
  378.     if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
  379.         return (-1);
  380.     if (deadkernel)
  381.         goto hard2;
  382.     /*
  383.      * initialize key datum
  384.      */
  385.     key.dptr = symbuf;
  386.  
  387.     if (db != NULL)
  388.         goto win;    /* off to the races */
  389.     /*
  390.      * open database
  391.      */
  392.     sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf));
  393.     if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
  394.         goto hard2;
  395.     /*
  396.      * read version out of database
  397.      */
  398.     bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
  399.     key.dsize = (sizeof ("VERSION") - 1);
  400.     data = dbm_fetch(db, key);
  401.     if (data.dptr == NULL)
  402.         goto hard1;
  403.     bcopy(data.dptr, dbversion, data.dsize);
  404.     dbversionlen = data.dsize;
  405.     /*
  406.      * read version string from kernel memory
  407.      */
  408.     bcopy("_version", symbuf, sizeof ("_version")-1);
  409.     key.dsize = (sizeof ("_version")-1);
  410.     data = dbm_fetch(db, key);
  411.     if (data.dptr == NULL)
  412.         goto hard1;
  413.     if (data.dsize != sizeof (struct nlist))
  414.         goto hard1;
  415.     bcopy(data.dptr, &nbuf, sizeof (struct nlist));
  416.     lseek(kmem, nbuf.n_value, 0);
  417.     if (read(kmem, kversion, dbversionlen) != dbversionlen)
  418.         goto hard1;
  419.     /*
  420.      * if they match, we win - otherwise do it the hard way
  421.      */
  422.     if (bcmp(dbversion, kversion, dbversionlen) != 0)
  423.         goto hard1;
  424.     /*
  425.      * getem from the database.
  426.      */
  427. win:
  428.     num = did = 0;
  429.     for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
  430.         int len;
  431.         /*
  432.          * clear out fields from users buffer
  433.          */
  434.         n->n_type = 0;
  435.         n->n_other = 0;
  436.         n->n_desc = 0;
  437.         n->n_value = 0;
  438.         /*
  439.          * query db
  440.          */
  441.         if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
  442.             seterr("symbol too large");
  443.             return (-1);
  444.         }
  445.         (void)strcpy(symbuf, n->n_name);
  446.         key.dsize = len;
  447.         data = dbm_fetch(db, key);
  448.         if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
  449.             continue;
  450.         bcopy(data.dptr, &nbuf, sizeof (struct nlist));
  451.         n->n_value = nbuf.n_value;
  452.         n->n_type = nbuf.n_type;
  453.         n->n_desc = nbuf.n_desc;
  454.         n->n_other = nbuf.n_other;
  455.         did++;
  456.     }
  457.     return (num - did);
  458. hard1:
  459.     dbm_close(db);
  460.     db = NULL;
  461. hard2:
  462.     num = nlist(unixf, nl);
  463.     if (num == -1)
  464.         seterr("nlist (hard way) failed");
  465.     return (num);
  466. }
  467.  
  468. kvm_getprocs(what, arg)
  469.     int what, arg;
  470. {
  471.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
  472.         return (NULL);
  473.     if (!deadkernel) {
  474.         int ret, copysize;
  475.  
  476.         if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
  477.             setsyserr("can't get estimate for kerninfo");
  478.             return (-1);
  479.         }
  480.         copysize = ret;
  481.         if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize)) 
  482.              == NULL) {
  483.             seterr("out of memory");
  484.             return (-1);
  485.         }
  486.         if ((ret = getkerninfo(what, kvmprocbase, ©size, 
  487.              arg)) == -1) {
  488.             setsyserr("can't get proc list");
  489.             return (-1);
  490.         }
  491.         if (copysize % sizeof (struct kinfo_proc)) {
  492.             seterr("proc size mismatch (got %d total, kinfo_proc: %d)",
  493.                 copysize, sizeof (struct kinfo_proc));
  494.             return (-1);
  495.         }
  496.         kvmnprocs = copysize / sizeof (struct kinfo_proc);
  497.     } else {
  498.         int nproc;
  499.  
  500.         if (kvm_read((void *) nl[X_NPROC].n_value, &nproc,
  501.             sizeof (int)) != sizeof (int)) {
  502.             seterr("can't read nproc");
  503.             return (-1);
  504.         }
  505.         if ((kvmprocbase = (struct kinfo_proc *)
  506.              malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
  507.             seterr("out of memory (addr: %x nproc = %d)",
  508.                 nl[X_NPROC].n_value, nproc);
  509.             return (-1);
  510.         }
  511.         kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
  512.         realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
  513.     }
  514.     kvmprocptr = kvmprocbase;
  515.  
  516.     return (kvmnprocs);
  517. }
  518.  
  519. /*
  520.  * XXX - should NOT give up so easily - especially since the kernel
  521.  * may be corrupt (it died).  Should gather as much information as possible.
  522.  * Follows proc ptrs instead of reading table since table may go
  523.  * away soon.
  524.  */
  525. static
  526. kvm_doprocs(what, arg, buff)
  527.     int what, arg;
  528.     char *buff;
  529. {
  530.     struct proc *p, proc;
  531.     register char *bp = buff;
  532.     int i = 0;
  533.     int doingzomb = 0;
  534.     struct eproc eproc;
  535.     struct pgrp pgrp;
  536.     struct session sess;
  537.     struct tty tty;
  538. #ifndef NEWVM
  539.     struct text text;
  540. #endif
  541.  
  542.     /* allproc */
  543.     if (kvm_read((void *) nl[X_ALLPROC].n_value, &p, 
  544.         sizeof (struct proc *)) != sizeof (struct proc *)) {
  545.         seterr("can't read allproc");
  546.         return (-1);
  547.     }
  548.  
  549. again:
  550.     for (; p; p = proc.p_nxt) {
  551.         if (kvm_read(p, &proc, sizeof (struct proc)) !=
  552.             sizeof (struct proc)) {
  553.             seterr("can't read proc at %x", p);
  554.             return (-1);
  555.         }
  556. #ifdef NEWVM
  557.         if (kvm_read(proc.p_cred, &eproc.e_pcred,
  558.             sizeof (struct pcred)) == sizeof (struct pcred))
  559.             (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred,
  560.                 sizeof (struct ucred));
  561.         switch(ki_op(what)) {
  562.             
  563.         case KINFO_PROC_PID:
  564.             if (proc.p_pid != (pid_t)arg)
  565.                 continue;
  566.             break;
  567.  
  568.  
  569.         case KINFO_PROC_UID:
  570.             if (eproc.e_ucred.cr_uid != (uid_t)arg)
  571.                 continue;
  572.             break;
  573.  
  574.         case KINFO_PROC_RUID:
  575.             if (eproc.e_pcred.p_ruid != (uid_t)arg)
  576.                 continue;
  577.             break;
  578.         }
  579. #else
  580.         switch(ki_op(what)) {
  581.             
  582.         case KINFO_PROC_PID:
  583.             if (proc.p_pid != (pid_t)arg)
  584.                 continue;
  585.             break;
  586.  
  587.  
  588.         case KINFO_PROC_UID:
  589.             if (proc.p_uid != (uid_t)arg)
  590.                 continue;
  591.             break;
  592.  
  593.         case KINFO_PROC_RUID:
  594.             if (proc.p_ruid != (uid_t)arg)
  595.                 continue;
  596.             break;
  597.         }
  598. #endif
  599.         /*
  600.          * gather eproc
  601.          */
  602.         eproc.e_paddr = p;
  603.         if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) !=
  604.                 sizeof (struct pgrp)) {
  605.             seterr("can't read pgrp at %x", proc.p_pgrp);
  606.             return (-1);
  607.         }
  608.         eproc.e_sess = pgrp.pg_session;
  609.         eproc.e_pgid = pgrp.pg_id;
  610.         eproc.e_jobc = pgrp.pg_jobc;
  611.         if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
  612.            != sizeof (struct session)) {
  613.             seterr("can't read session at %x", pgrp.pg_session);
  614.             return (-1);
  615.         }
  616.         if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
  617.             if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
  618.                 != sizeof (struct tty)) {
  619.                 seterr("can't read tty at %x", sess.s_ttyp);
  620.                 return (-1);
  621.             }
  622.             eproc.e_tdev = tty.t_dev;
  623.             eproc.e_tsess = tty.t_session;
  624.             if (tty.t_pgrp != NULL) {
  625.                 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
  626.                     pgrp)) != sizeof (struct pgrp)) {
  627.                     seterr("can't read tpgrp at &x", 
  628.                         tty.t_pgrp);
  629.                     return (-1);
  630.                 }
  631.                 eproc.e_tpgid = pgrp.pg_id;
  632.             } else
  633.                 eproc.e_tpgid = -1;
  634.         } else
  635.             eproc.e_tdev = NODEV;
  636.         if (proc.p_wmesg)
  637.             kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
  638. #ifdef NEWVM
  639.         (void) kvm_read(proc.p_vmspace, &eproc.e_vm,
  640.             sizeof (struct vmspace));
  641.         eproc.e_xsize = eproc.e_xrssize =
  642.             eproc.e_xccount = eproc.e_xswrss = 0;
  643. #else
  644.         if (proc.p_textp) {
  645.             kvm_read(proc.p_textp, &text, sizeof (text));
  646.             eproc.e_xsize = text.x_size;
  647.             eproc.e_xrssize = text.x_rssize;
  648.             eproc.e_xccount = text.x_ccount;
  649.             eproc.e_xswrss = text.x_swrss;
  650.         } else {
  651.             eproc.e_xsize = eproc.e_xrssize =
  652.               eproc.e_xccount = eproc.e_xswrss = 0;
  653.         }
  654. #endif
  655.  
  656.         switch(ki_op(what)) {
  657.  
  658.         case KINFO_PROC_PGRP:
  659.             if (eproc.e_pgid != (pid_t)arg)
  660.                 continue;
  661.             break;
  662.  
  663.         case KINFO_PROC_TTY:
  664.             if ((proc.p_flag&SCTTY) == 0 || 
  665.                  eproc.e_tdev != (dev_t)arg)
  666.                 continue;
  667.             break;
  668.         }
  669.  
  670.         i++;
  671.         bcopy(&proc, bp, sizeof (struct proc));
  672.         bp += sizeof (struct proc);
  673.         bcopy(&eproc, bp, sizeof (struct eproc));
  674.         bp+= sizeof (struct eproc);
  675.     }
  676.     if (!doingzomb) {
  677.         /* zombproc */
  678.         if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p, 
  679.             sizeof (struct proc *)) != sizeof (struct proc *)) {
  680.             seterr("can't read zombproc");
  681.             return (-1);
  682.         }
  683.         doingzomb = 1;
  684.         goto again;
  685.     }
  686.  
  687.     return (i);
  688. }
  689.  
  690. struct proc *
  691. kvm_nextproc()
  692. {
  693.  
  694.     if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
  695.         return (NULL);
  696.     if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
  697.         seterr("end of proc list");
  698.         return (NULL);
  699.     }
  700.     return((struct proc *)(kvmprocptr++));
  701. }
  702.  
  703. struct eproc *
  704. kvm_geteproc(p)
  705.     const struct proc *p;
  706. {
  707.     return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
  708. }
  709.  
  710. kvm_setproc()
  711. {
  712.     kvmprocptr = kvmprocbase;
  713. }
  714.  
  715. kvm_freeprocs()
  716. {
  717.  
  718.     if (kvmprocbase) {
  719.         free(kvmprocbase);
  720.         kvmprocbase = NULL;
  721.     }
  722. }
  723.  
  724. #ifdef i386
  725. /* See also ./sys/kern/kern_execve.c */
  726. #define ARGSIZE        (roundup(ARG_MAX, NBPG))
  727. #endif
  728.  
  729. #ifdef NEWVM
  730. struct user *
  731. kvm_getu(p)
  732.     const struct proc *p;
  733. {
  734.     register struct kinfo_proc *kp = (struct kinfo_proc *)p;
  735.     register int i;
  736.     register char *up;
  737.  
  738.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
  739.         return (NULL);
  740.     if (p->p_stat == SZOMB) {
  741.         seterr("zombie process");
  742.         return (NULL);
  743.     }
  744.     /*
  745.      * Reading from swap is too complicated right now.
  746.      */
  747.     if ((p->p_flag & SLOAD) == 0)
  748.         return(NULL);
  749.     /*
  750.      * Read u-area one page at a time for the benefit of post-mortems
  751.      */
  752.     up = (char *) p->p_addr;
  753.     for (i = 0; i < UPAGES; i++) {
  754.         klseek(kmem, (long)up, 0);
  755.         if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) {
  756.             seterr("cant read page %x of u of pid %d from %s",
  757.                 up, p->p_pid, kmemf);
  758.             return(NULL);
  759.         }
  760.         up += CLBYTES;
  761.     }
  762.     pcbpf = (int) btop(p->p_addr);    /* what should this be really? */
  763.     /*
  764.      * Conjure up a physical address for the arguments.
  765.      */
  766.     argaddr0 = argaddr1 = 0;
  767. #ifdef hp300
  768.     if (kp->kp_eproc.e_vm.vm_pmap.pm_ptab) {
  769.         struct pte pte[CLSIZE*2];
  770.  
  771.         klseek(kmem,
  772.             (long)&kp->kp_eproc.e_vm.vm_pmap.pm_ptab
  773.             [btoc(USRSTACK-CLBYTES*2)], 0);
  774.         if (read(kmem, (char *)&pte, sizeof(pte)) == sizeof(pte)) {
  775. #if CLBYTES < 2048
  776.             argaddr0 = ctob(pftoc(pte[CLSIZE*0].pg_pfnum));
  777. #endif
  778.             argaddr1 = ctob(pftoc(pte[CLSIZE*1].pg_pfnum));
  779.         }
  780.     }
  781. #endif
  782.     kp->kp_eproc.e_vm.vm_rssize =
  783.         kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */
  784.  
  785. #ifdef i386
  786.     if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) {
  787.         struct pde pde;
  788.         u_int vaddr = (u_int)kp->kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ - ARGSIZE;
  789.  
  790.         klseek(kmem,
  791.         (long)(&kp->kp_eproc.e_vm.vm_pmap.pm_pdir[pdei(vaddr)]), 0);
  792.  
  793.         if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde
  794.                 && pde.pd_v) {
  795.  
  796.             struct pte pte;
  797.  
  798.             lseek(mem, (long)ctob(pde.pd_pfnum) +
  799.                 (ptei(vaddr) * sizeof pte), 0);
  800.             if (read(mem, (char *)&pte, sizeof pte) == sizeof pte
  801.                     && pte.pg_v)
  802.                 argaddr1 = (long)ctob(pte.pg_pfnum);
  803.         }
  804.     }
  805. #endif
  806.     return(&user.user);
  807. }
  808. #else
  809. struct user *
  810. kvm_getu(p)
  811.     const struct proc *p;
  812. {
  813.     struct pte *pteaddr, apte;
  814.     struct pte arguutl[HIGHPAGES+(CLSIZE*2)];
  815.     register int i;
  816.     int ncl;
  817.  
  818.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
  819.         return (NULL);
  820.     if (p->p_stat == SZOMB) {
  821.         seterr("zombie process");
  822.         return (NULL);
  823.     }
  824.     if ((p->p_flag & SLOAD) == 0) {
  825.         if (swap < 0) {
  826.             seterr("no swap");
  827.             return (NULL);
  828.         }
  829.         (void) lseek(swap, (long)dtob(p->p_swaddr), 0);
  830.         if (read(swap, (char *)&user.user, sizeof (struct user)) != 
  831.             sizeof (struct user)) {
  832.             seterr("can't read u for pid %d from %s",
  833.                 p->p_pid, swapf);
  834.             return (NULL);
  835.         }
  836.         pcbpf = 0;
  837.         argaddr0 = 0;
  838.         argaddr1 = 0;
  839.         return (&user.user);
  840.     }
  841.     pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1];
  842.     klseek(kmem, (long)pteaddr, 0);
  843.     if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
  844.         seterr("can't read indir pte to get u for pid %d from %s",
  845.             p->p_pid, kmemf);
  846.         return (NULL);
  847.     }
  848.     lseek(mem, (long)ctob(pftoc(apte.pg_pfnum+1)) - sizeof(arguutl), 0);
  849.     if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
  850.         seterr("can't read page table for u of pid %d from %s",
  851.             p->p_pid, memf);
  852.         return (NULL);
  853.     }
  854.     if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
  855.         argaddr0 = ctob(pftoc(arguutl[0].pg_pfnum));
  856.     else
  857.         argaddr0 = 0;
  858.     if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum)
  859.         argaddr1 = ctob(pftoc(arguutl[CLSIZE*1].pg_pfnum));
  860.     else
  861.         argaddr1 = 0;
  862.     pcbpf = arguutl[CLSIZE*2].pg_pfnum;
  863.     ncl = (sizeof (struct user) + CLBYTES - 1) / CLBYTES;
  864.     while (--ncl >= 0) {
  865.         i = ncl * CLSIZE;
  866.         lseek(mem,
  867.               (long)ctob(pftoc(arguutl[(CLSIZE*2)+i].pg_pfnum)), 0);
  868.         if (read(mem, user.upages[i], CLBYTES) != CLBYTES) {
  869.             seterr("can't read page %d of u of pid %d from %s",
  870.                 arguutl[(CLSIZE*2)+i].pg_pfnum, p->p_pid, memf);
  871.             return(NULL);
  872.         }
  873.     }
  874.     return (&user.user);
  875. }
  876. #endif
  877.  
  878. char *
  879. kvm_getargs(p, up)
  880.     const struct proc *p;
  881.     const struct user *up;
  882. {
  883. #ifdef i386
  884.     /* See also ./sys/kern/kern_execve.c */
  885.     static char cmdbuf[ARGSIZE];
  886.     static union {
  887.         char    argc[ARGSIZE];
  888.         int    argi[ARGSIZE/sizeof (int)];
  889.     } argspac;
  890. #else
  891.     static char cmdbuf[CLBYTES*2];
  892.     static union {
  893.         char    argc[CLBYTES*2];
  894.         int    argi[CLBYTES*2/sizeof (int)];
  895.     } argspac;
  896. #endif
  897.     register char *cp;
  898.     register int *ip;
  899.     char c;
  900.     int nbad;
  901. #ifndef NEWVM
  902.     struct dblock db;
  903. #endif
  904.     const char *file;
  905.     int stkoff = 0;
  906.  
  907. #if defined(NEWVM) && defined(hp300)
  908.     stkoff = 20;            /* XXX for sigcode */
  909. #endif
  910.     if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
  911.         goto retucomm;
  912.     if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
  913. #ifdef NEWVM
  914.         goto retucomm;    /* XXX for now */
  915. #else
  916.         if (swap < 0 || p->p_ssize == 0)
  917.             goto retucomm;
  918.         vstodb(0, CLSIZE, &up->u_smap, &db, 1);
  919.         (void) lseek(swap, (long)dtob(db.db_base), 0);
  920.         if (read(swap, (char *)&argspac.argc[CLBYTES], CLBYTES)
  921.             != CLBYTES)
  922.             goto bad;
  923.         vstodb(1, CLSIZE, &up->u_smap, &db, 1);
  924.         (void) lseek(swap, (long)dtob(db.db_base), 0);
  925.         if (read(swap, (char *)&argspac.argc[0], CLBYTES) != CLBYTES)
  926.             goto bad;
  927.         file = swapf;
  928. #endif
  929.     } else {
  930. #ifdef i386
  931.         lseek(mem, (long)argaddr1, 0);
  932.         if (read(mem, &argspac.argc[0], ARGSIZE) != ARGSIZE)
  933.             goto bad;
  934. #else
  935.         if (argaddr0) {
  936.             lseek(mem, (long)argaddr0, 0);
  937.             if (read(mem, (char *)&argspac, CLBYTES) != CLBYTES)
  938.                 goto bad;
  939.         } else
  940.             bzero(&argspac, CLBYTES);
  941.         lseek(mem, (long)argaddr1, 0);
  942.         if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES)
  943.             goto bad;
  944. #endif
  945.         file = (char *) memf;
  946.     }
  947. #ifdef i386
  948.     ip = &argspac.argi[(ARGSIZE-ARG_MAX)/sizeof (int)];
  949.  
  950.     nbad = 0;
  951.     for (cp = (char *)ip; cp < &argspac.argc[ARGSIZE-stkoff]; cp++) {
  952. #else
  953.     ip = &argspac.argi[CLBYTES*2/sizeof (int)];
  954.     ip -= 2;                /* last arg word and .long 0 */
  955.     ip -= stkoff / sizeof (int);
  956.     while (*--ip) {
  957.         if (ip == argspac.argi)
  958.             goto retucomm;
  959.     }
  960.     *(char *)ip = ' ';
  961.     ip++;
  962.     nbad = 0;
  963.  
  964.     for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) {
  965. #endif
  966.         c = *cp;
  967.         if (c == 0) {    /* convert null between arguments to space */
  968.             *cp = ' ';
  969.             if (*(cp+1) == 0) break;    /* if null argument follows then no more args */
  970.             }
  971.         else if (c < ' ' || c > 0176) {
  972.             if (++nbad >= 5*(0+1)) {    /* eflg -> 0 XXX */ /* limit number of bad chars to 5 */
  973.                 *cp++ = '?';
  974.                 break;
  975.             }
  976.             *cp = '?';
  977.         }
  978.         else if (0 == 0 && c == '=') {        /* eflg -> 0 XXX */
  979.             while (*--cp != ' ')
  980.                 if (cp <= (char *)ip)
  981.                     break;
  982.             break;
  983.         }
  984.     }
  985.     *cp = 0;
  986.     while (*--cp == ' ')
  987.         *cp = 0;
  988.     cp = (char *)ip;
  989.     (void) strcpy(cmdbuf, cp);
  990.     if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
  991.         (void) strcat(cmdbuf, " (");
  992.         (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
  993.         (void) strcat(cmdbuf, ")");
  994.     }
  995.     return (cmdbuf);
  996.  
  997. bad:
  998.     seterr("error locating command name for pid %d from %s",
  999.         p->p_pid, file);
  1000. retucomm:
  1001.     (void) strcpy(cmdbuf, " (");
  1002.     (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
  1003.     (void) strcat(cmdbuf, ")");
  1004.     return (cmdbuf);
  1005. }
  1006.  
  1007.  
  1008. static
  1009. getkvars()
  1010. {
  1011.     if (kvm_nlist(nl) == -1)
  1012.         return (-1);
  1013.     if (deadkernel) {
  1014.         /* We must do the sys map first because klseek uses it */
  1015.         long    addr;
  1016.  
  1017. #ifndef NEWVM
  1018.         Syssize = nl[X_SYSSIZE].n_value;
  1019.         Sysmap = (struct pte *)
  1020.             calloc((unsigned) Syssize, sizeof (struct pte));
  1021.         if (Sysmap == NULL) {
  1022.             seterr("out of space for Sysmap");
  1023.             return (-1);
  1024.         }
  1025.         addr = (long) nl[X_SYSMAP].n_value;
  1026.         addr &= ~KERNBASE;
  1027.         (void) lseek(kmem, addr, 0);
  1028.         if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte))
  1029.             != Syssize * sizeof (struct pte)) {
  1030.             seterr("can't read Sysmap");
  1031.             return (-1);
  1032.         }
  1033. #endif
  1034. #if defined(hp300)
  1035.         addr = (long) nl[X_LOWRAM].n_value;
  1036.         (void) lseek(kmem, addr, 0);
  1037.         if (read(kmem, (char *) &lowram, sizeof (lowram))
  1038.             != sizeof (lowram)) {
  1039.             seterr("can't read lowram");
  1040.             return (-1);
  1041.         }
  1042.         lowram = btop(lowram);
  1043.         Sysseg = (struct ste *) malloc(NBPG);
  1044.         if (Sysseg == NULL) {
  1045.             seterr("out of space for Sysseg");
  1046.             return (-1);
  1047.         }
  1048.         addr = (long) nl[X_SYSSEG].n_value;
  1049.         (void) lseek(kmem, addr, 0);
  1050.         read(kmem, (char *)&addr, sizeof(addr));
  1051.         (void) lseek(kmem, (long)addr, 0);
  1052.         if (read(kmem, (char *) Sysseg, NBPG) != NBPG) {
  1053.             seterr("can't read Sysseg");
  1054.             return (-1);
  1055.         }
  1056. #endif
  1057. #if defined(i386)
  1058.         PTD = (struct pde *) malloc(NBPG);
  1059.         if (PTD == NULL) {
  1060.             seterr("out of space for PTD");
  1061.             return (-1);
  1062.         }
  1063.         addr = (long) nl[X_IdlePTD].n_value;
  1064.         (void) lseek(kmem, addr, 0);
  1065.         read(kmem, (char *)&addr, sizeof(addr));
  1066.         (void) lseek(kmem, (long)addr, 0);
  1067.         if (read(kmem, (char *) PTD, NBPG) != NBPG) {
  1068.             seterr("can't read PTD");
  1069.             return (-1);
  1070.         }
  1071. #endif
  1072.     }
  1073. #ifndef NEWVM
  1074.     usrpt = (struct pte *)nl[X_USRPT].n_value;
  1075.     Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value;
  1076. #endif
  1077.     if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) !=
  1078.         sizeof (long)) {
  1079.         seterr("can't read nswap");
  1080.         return (-1);
  1081.     }
  1082.     if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) !=
  1083.         sizeof (long)) {
  1084.         seterr("can't read dmmin");
  1085.         return (-1);
  1086.     }
  1087.     if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) !=
  1088.         sizeof (long)) {
  1089.         seterr("can't read dmmax");
  1090.         return (-1);
  1091.     }
  1092.     return (0);
  1093. }
  1094.  
  1095. kvm_read(loc, buf, len)
  1096.     void *loc;
  1097.     void *buf;
  1098. {
  1099.     if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
  1100.         return (-1);
  1101.     if (iskva(loc)) {
  1102.         klseek(kmem, (off_t) loc, 0);
  1103.         if (read(kmem, buf, len) != len) {
  1104.             seterr("error reading kmem at %x", loc);
  1105.             return (-1);
  1106.         }
  1107.     } else {
  1108.         lseek(mem, (off_t) loc, 0);
  1109.         if (read(mem, buf, len) != len) {
  1110.             seterr("error reading mem at %x", loc);
  1111.             return (-1);
  1112.         }
  1113.     }
  1114.     return (len);
  1115. }
  1116.  
  1117. static void
  1118. klseek(fd, loc, off)
  1119.     int fd;
  1120.     off_t loc;
  1121.     int off;
  1122. {
  1123.  
  1124.     if (deadkernel) {
  1125.         if ((loc = Vtophys(loc)) == -1)
  1126.             return;
  1127.     }
  1128.     (void) lseek(fd, (off_t)loc, off);
  1129. }
  1130.  
  1131. #ifndef NEWVM
  1132. /*
  1133.  * Given a base/size pair in virtual swap area,
  1134.  * return a physical base/size pair which is the
  1135.  * (largest) initial, physically contiguous block.
  1136.  */
  1137. static void
  1138. vstodb(vsbase, vssize, dmp, dbp, rev)
  1139.     register int vsbase;
  1140.     int vssize;
  1141.     struct dmap *dmp;
  1142.     register struct dblock *dbp;
  1143. {
  1144.     register int blk = dmmin;
  1145.     register swblk_t *ip = dmp->dm_map;
  1146.  
  1147.     vsbase = ctod(vsbase);
  1148.     vssize = ctod(vssize);
  1149.     if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
  1150.         /*panic("vstodb")*/;
  1151.     while (vsbase >= blk) {
  1152.         vsbase -= blk;
  1153.         if (blk < dmmax)
  1154.             blk *= 2;
  1155.         ip++;
  1156.     }
  1157.     if (*ip <= 0 || *ip + blk > nswap)
  1158.         /*panic("vstodb")*/;
  1159.     dbp->db_size = MIN(vssize, blk - vsbase);
  1160.     dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
  1161. }
  1162. #endif
  1163.  
  1164. #ifdef NEWVM
  1165. static off_t
  1166. Vtophys(loc)
  1167.     u_long    loc;
  1168. {
  1169.     off_t newloc = (off_t) -1;
  1170. #ifdef hp300
  1171.     int p, ste, pte;
  1172.  
  1173.     ste = *(int *)&Sysseg[loc >> SG_ISHIFT];
  1174.     if ((ste & SG_V) == 0) {
  1175.         seterr("vtophys: segment not valid");
  1176.         return((off_t) -1);
  1177.     }
  1178.     p = btop(loc & SG_PMASK);
  1179.     newloc = (ste & SG_FRAME) + (p * sizeof(struct pte));
  1180.     (void) lseek(kmem, (long)(newloc-(off_t)ptob(lowram)), 0);
  1181.     if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
  1182.         seterr("vtophys: cannot locate pte");
  1183.         return((off_t) -1);
  1184.     }
  1185.     newloc = pte & PG_FRAME;
  1186.     if (pte == PG_NV || newloc < (off_t)ptob(lowram)) {
  1187.         seterr("vtophys: page not valid");
  1188.         return((off_t) -1);
  1189.     }
  1190.     newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET);
  1191. #endif
  1192. #ifdef i386
  1193.     struct pde pde;
  1194.     struct pte pte;
  1195.     int p;
  1196.  
  1197.     pde = PTD[loc >> PD_SHIFT];
  1198.     if (pde.pd_v == 0) {
  1199.         seterr("vtophys: page directory entry not valid");
  1200.         return((off_t) -1);
  1201.     }
  1202.     p = btop(loc & PT_MASK);
  1203.     newloc = pde.pd_pfnum + (p * sizeof(struct pte));
  1204.     (void) lseek(kmem, (long)newloc, 0);
  1205.     if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
  1206.         seterr("vtophys: cannot obtain desired pte");
  1207.         return((off_t) -1);
  1208.     }
  1209.     newloc = pte.pg_pfnum;
  1210.     if (pte.pg_v == 0) {
  1211.         seterr("vtophys: page table entry not valid");
  1212.         return((off_t) -1);
  1213.     }
  1214.     newloc += (loc & PGOFSET);
  1215. #endif
  1216.     return((off_t) newloc);
  1217. }
  1218. #else
  1219. static off_t
  1220. vtophys(loc)
  1221.     long loc;
  1222. {
  1223.     int p;
  1224.     off_t newloc;
  1225.     register struct pte *pte;
  1226.  
  1227.     newloc = loc & ~KERNBASE;
  1228.     p = btop(newloc);
  1229. #if defined(vax) || defined(tahoe)
  1230.     if ((loc & KERNBASE) == 0) {
  1231.         seterr("vtophys: translating non-kernel address");
  1232.         return((off_t) -1);
  1233.     }
  1234. #endif
  1235.     if (p >= Syssize) {
  1236.         seterr("vtophys: page out of bound (%d>=%d)", p, Syssize);
  1237.         return((off_t) -1);
  1238.     }
  1239.     pte = &Sysmap[p];
  1240.     if (pte->pg_v == 0 && (pte->pg_fod || pte->pg_pfnum == 0)) {
  1241.         seterr("vtophys: page not valid");
  1242.         return((off_t) -1);
  1243.     }
  1244. #if defined(hp300)
  1245.     if (pte->pg_pfnum < lowram) {
  1246.         seterr("vtophys: non-RAM page (%d<%d)", pte->pg_pfnum, lowram);
  1247.         return((off_t) -1);
  1248.     }
  1249. #endif
  1250.     loc = (long) (ptob(pftoc(pte->pg_pfnum)) + (loc & PGOFSET));
  1251.     return(loc);
  1252. }
  1253. #endif
  1254.  
  1255. #include <varargs.h>
  1256. static char errbuf[_POSIX2_LINE_MAX];
  1257.  
  1258. static void
  1259. seterr(va_alist)
  1260.     va_dcl
  1261. {
  1262.     char *fmt;
  1263.     va_list ap;
  1264.  
  1265.     va_start(ap);
  1266.     fmt = va_arg(ap, char *);
  1267.     (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
  1268.     va_end(ap);
  1269. }
  1270.  
  1271. static void
  1272. setsyserr(va_alist)
  1273.     va_dcl
  1274. {
  1275.     char *fmt, *cp;
  1276.     va_list ap;
  1277.     extern int errno;
  1278.  
  1279.     va_start(ap);
  1280.     fmt = va_arg(ap, char *);
  1281.     (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
  1282.     for (cp=errbuf; *cp; cp++)
  1283.         ;
  1284.     snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s", strerror(errno));
  1285.     va_end(ap);
  1286. }
  1287.  
  1288. char *
  1289. kvm_geterr()
  1290. {
  1291.     return (errbuf);
  1292. }
  1293.