home *** CD-ROM | disk | FTP | other *** search
- /* History:
- 5/1/91 DJB baseline
- Convex support added by Dan Bernstein.
- Translated to independent library with strerr support by Dan Bernstein.
- Code for this library derived from Abell version of ofiles.
- Contributors and possible contributors: C. Spencer, Michael Ditto,
- Tom Dunigan, Alexander Dupuy, Greg Nebbett, Richart Tobin, Mike Spitzer,
- Ray Moody, Vik Lall, Vic Abell.
- */
-
- /*
-
- struct user *getuser(p) struct proc *p; returns a pointer to a (not
- necessarily atomic) copy in user memory of the u area for process p.
- Upon errors it returns 0.
-
- This is one of the nastiest, most machine-dependent pieces of code I've
- ever had the pleasure of working with to achieve an essentially
- machine-independent result.
-
- int getuserinit() does optional initialization to cooperate with other
- libraries.
-
- getuserstrerr is a strerrfun for getuser() and getuserinit().
-
- */
-
- #include "getuser.h"
- #include "confgetusersupport.h"
- #include "confusrptnlist.h"
- #include "structuser.h"
- #include "structpte.h"
- #include "structproc.h"
- #include "confneedmachparam.h"
- #ifdef NEED_MACHPARAM
- #include <machine/machparam.h>
- #endif
- #include <sys/vmmac.h>
- #include "confgetuserdynix.h"
- #include "confgetusermips.h"
- #include "confgetuserconvex.h"
- #include "confkvm.h"
- #ifdef KVM
- #include <kvm.h>
- #include <fcntl.h> /* XXX: really under KVM? */
- #endif
- #include "nlistlist.h"
- #include "kmem.h"
- #include "mmem.h"
- #include "smem.h"
- #include "strerr.h"
- #include "confhavepflag.h"
-
- static int getusererrno = 0;
-
- static struct strerrtab e[] = {
- { 0, "getuser error 0", 0 }
- #define GU_INIT 1
- , { GU_INIT, "cannot init getuser: ", nliststrerr }
- #define GU_NLIST 2
- , { GU_NLIST, "cannot nlist: ", nliststrerr }
- #ifndef GETUSERSUPPORT
- #define GU_NLPFOUND 3
- , { GU_NLPFOUND, NLISTPAGES, nlistnotin }
- #define GU_NLBFOUND 4
- , { GU_NLBFOUND, NLISTBASE, nlistnotin }
- #endif
- #define GU_KVM 5 /* stupid kvm library, no error reporting */
- , { GU_KVM, "vendor kvm library failed", 0 } /* credit where due :-) */
- #define GU_ALLOC 6
- , { GU_ALLOC, "out of memory", 0 }
- #define GU_SLOAD 7
- , { GU_SLOAD, "cannot swap in u area: ", smemstrerr }
- #define GU_UAREA 8
- , { GU_UAREA, "cannot read u area: ", kmemstrerr }
- #define GU_DMAP 9
- , { GU_DMAP, "cannot read dmap: ", kmemstrerr }
- #define GU_BLKNO 10
- , { GU_BLKNO, "cannot read blkno: ", kmemstrerr }
- #define GU_PTE 11
- , { GU_PTE, "cannot read pte: ", kmemstrerr }
- #define GU_UPGTBL 12
- , { GU_UPGTBL, "cannot read upgtbl: ", mmemstrerr }
- #define GU_UPAGE 13
- , { GU_UPAGE, "cannot read upage: ", mmemstrerr }
- };
-
- char *getuserstrerr(ke) strerrfun *ke;
- {
- return strerrtaberr(ke,getusererrno,e,sizeof(e)/sizeof(*e),"unknown getuser error");
- }
-
- #ifndef GETUSERSUPPORT
- static short nlpagest;
- static unsigned long nlpagesv;
- static short nlbaset;
- static unsigned long nlbasev;
- struct pte *usrpt, *Usrptma;
- #endif
-
- static int init = 0;
-
- int getuserinit()
- {
- #ifndef GETUSERSUPPORT
- if (nlistadd(NLISTPAGES,&nlpagest,&nlpagesv) == -1)
- RETERN(-1,getusererrno,GU_INIT)
- if (nlistadd(NLISTBASE,&nlbaset,&nlbasev) == -1)
- RETERN(-1,getusererrno,GU_INIT)
- #endif
- init = 1;
- return 0;
- }
-
- static int pergu()
- {
- if (!init)
- if (getuserinit() == -1)
- return -1;
- #ifndef GETUSERSUPPORT
- if (nlpagest == -1)
- {
- if (nlistdo() == -1)
- RETERN(-1,getusererrno,GU_NLIST)
- if (!nlpagest)
- RETERN(-1,getusererrno,GU_NLPFOUND)
- if (!nlbaset)
- RETERN(-1,getusererrno,GU_NLBFOUND)
- }
- Usrptma = (struct pte *) nlpagesv;
- usrpt = (struct pte *) nlbasev; /* used by <vmmac.h> */
- #endif
- return 0;
- }
-
- #ifdef KVM
- static kvm_t *kd = 0;
-
- struct user *getuser(p)
- struct proc *p;
- {
- if (pergu() == -1)
- return 0;
- if (!kd)
- if (!(kd = kvm_open((char *)0,(char *)0,(char *)0,O_RDONLY)))
- RETERN(0,getusererrno,GU_KVM)
- return kvm_getu(kd,p);
- }
- #else
- #ifdef GETUSER_CONVEX
- struct user *getuser(p)
- struct proc *p;
- {
- static struct user u;
- if (pergu() == -1)
- return 0;
- Getprocu(p,&u,sizeof(struct user)); /*XXX*/
- return &u;
- }
- #else
- #ifdef GETUSER_DYNIX
- struct user *getuser(p)
- struct proc *p;
- {
- int btr;
- static struct user *u;
- char *valloc();
-
- u = 0;
- if (pergu() == -1)
- return 0;
- if (!u)
- if (!(u = (struct user *) valloc(ctob(UPAGES))))
- RETERN(0,getusererrno,GU_ALLOC)
- btr = ctob(UPAGES);
- if ((p->p_flag & SLOAD) == 0)
- {
- if (smemcpy((char *)u,(char *) dtob(p->p_swaddr),btr) == -1)
- {
- free((char *) u);
- getusererrno = GU_SLOAD;
- return 0;
- }
- }
- else
- if (kmemcpy((char *)u,(char *)p->p_uarea,btr) == -1)
- {
- free((char *) u);
- getusererrno = GU_UAREA;
- return 0;
- }
- return u;
- }
- #else
- struct user *getuser(p)
- struct proc *p;
- {
- struct pte *ptep, apte;
- #ifdef GETUSER_MIPS
- struct pte wpte[UPAGES];
- int ncl;
- #endif
- struct pte mypgtbl[NBPG/sizeof(struct pte)];
- int upage;
- char *up;
- static struct user user;
-
- if (pergu() == -1)
- return 0;
- /* easy way */
- #ifndef HAVE_PFLAG
- if ((p->p_sched & SLOAD) == 0)
- {
- struct dmap l_dmap;
- int ublkno;
- /* code adapted from ps.c (or so says ofiles.c) */
- if (kmemcpy(&l_dmap,(char *)(p->p_smap),sizeof(struct dmap)) == -1)
- RETERN(0,getusererrno,GU_DMAP)
- if (kmemcpy(&ublkno,(char *)(l_dmap.dm_ptdaddr),sizeof(int)) == -1)
- RETERN(0,getusererrno,GU_BLKNO)
- if (kmemcpy((char *)&user,(char *)dtob(ublkno),sizeof(struct user)) == -1)
- RETERN(0,getusererrno,GU_UAREA)
- /* that's it? wow ---DJB */
- }
- #else
- if ((p->p_flag & SLOAD) == 0)
- {
- if (kmemcpy((char *)&user,(char *)dtob(p->p_swaddr),sizeof(struct user)) == -1)
- RETERN(0,getusererrno,GU_UAREA)
- }
- #endif
- else
- { /* boo */
- #ifdef GETUSER_MIPS
- if (kmemcpy((char *)wpte,(char *)p->p_addr,sizeof(wpte)) == -1)
- RETERN(0,getusererrno,GU_PTE)
-
- /* now collect various pages of u area */
- ncl = (sizeof(struct user) + NBPG*CLSIZE - 1)/(NBPG*CLSIZE);
- up = (char *) &user;
- for (upage = 0; upage < ncl; upage += CLSIZE)
- {
- if (mmemcpy(up,(char *)ctob(wpte[upage].pg_pfnum),NBPG*CLSIZE) == -1)
- RETERN(0,getusererrno,GU_UPAGE)
- up += (NBPG*CLSIZE);
- }
- #else
- ptep = &Usrptma[btokmx(p->p_p0br) + p->p_szpt - 1];
-
- /* get the page table for the user page */
- if (kmemcpy((char *)&apte,(char *)ptep,sizeof(apte)) == -1)
- RETERN(0,getusererrno,GU_PTE)
-
- /* now get this user's page table */
- if (mmemcpy((char *)mypgtbl,(char *)ctob(apte.pg_pfnum),sizeof(mypgtbl)) == -1)
- RETERN(0,getusererrno,GU_UPGTBL)
- /* now collect various pages of u area */
- up = (char *) &user;
- for (upage = 0; upage < sizeof(struct user)/NBPG; upage++)
- {
- if (mmemcpy(up,(char *)ctob(mypgtbl[NPTEPG-UPAGES+upage].pg_pfnum),NBPG) == -1)
- RETERN(0,getusererrno,GU_UPAGE)
- up += NBPG;
- }
- #endif
- }
- return &user;
- }
- #endif
-
- #endif
- #endif
-