home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3299 / getuser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  6.5 KB  |  273 lines

  1. /* History:
  2. 5/1/91 DJB baseline
  3. Convex support added by Dan Bernstein.
  4. Translated to independent library with strerr support by Dan Bernstein.
  5. Code for this library derived from Abell version of ofiles.
  6. Contributors and possible contributors: C. Spencer, Michael Ditto,
  7. Tom Dunigan, Alexander Dupuy, Greg Nebbett, Richart Tobin, Mike Spitzer,
  8. Ray Moody, Vik Lall, Vic Abell.
  9. */
  10.  
  11. /*
  12.  
  13. struct user *getuser(p) struct proc *p; returns a pointer to a (not
  14. necessarily atomic) copy in user memory of the u area for process p.
  15. Upon errors it returns 0.
  16.  
  17. This is one of the nastiest, most machine-dependent pieces of code I've
  18. ever had the pleasure of working with to achieve an essentially
  19. machine-independent result.
  20.  
  21. int getuserinit() does optional initialization to cooperate with other
  22. libraries.
  23.  
  24. getuserstrerr is a strerrfun for getuser() and getuserinit().
  25.  
  26. */
  27.  
  28. #include "getuser.h"
  29. #include "confgetusersupport.h"
  30. #include "confusrptnlist.h"
  31. #include "structuser.h"
  32. #include "structpte.h"
  33. #include "structproc.h"
  34. #include "confneedmachparam.h"
  35. #ifdef NEED_MACHPARAM
  36. #include <machine/machparam.h>
  37. #endif
  38. #include <sys/vmmac.h>
  39. #include "confgetuserdynix.h"
  40. #include "confgetusermips.h"
  41. #include "confgetuserconvex.h"
  42. #include "confkvm.h"
  43. #ifdef KVM
  44. #include <kvm.h>
  45. #include <fcntl.h> /* XXX: really under KVM? */
  46. #endif
  47. #include "nlistlist.h"
  48. #include "kmem.h"
  49. #include "mmem.h"
  50. #include "smem.h"
  51. #include "strerr.h"
  52. #include "confhavepflag.h"
  53.  
  54. static int getusererrno = 0;
  55.  
  56. static struct strerrtab e[] = {
  57.   { 0, "getuser error 0", 0 }
  58. #define GU_INIT 1
  59. , { GU_INIT, "cannot init getuser: ", nliststrerr }
  60. #define GU_NLIST 2
  61. , { GU_NLIST, "cannot nlist: ", nliststrerr }
  62. #ifndef GETUSERSUPPORT
  63. #define GU_NLPFOUND 3
  64. , { GU_NLPFOUND, NLISTPAGES, nlistnotin }
  65. #define GU_NLBFOUND 4
  66. , { GU_NLBFOUND, NLISTBASE, nlistnotin }
  67. #endif
  68. #define GU_KVM 5 /* stupid kvm library, no error reporting */
  69. , { GU_KVM, "vendor kvm library failed", 0 } /* credit where due :-) */
  70. #define GU_ALLOC 6
  71. , { GU_ALLOC, "out of memory", 0 }
  72. #define GU_SLOAD 7
  73. , { GU_SLOAD, "cannot swap in u area: ", smemstrerr }
  74. #define GU_UAREA 8
  75. , { GU_UAREA, "cannot read u area: ", kmemstrerr }
  76. #define GU_DMAP 9
  77. , { GU_DMAP, "cannot read dmap: ", kmemstrerr }
  78. #define GU_BLKNO 10
  79. , { GU_BLKNO, "cannot read blkno: ", kmemstrerr }
  80. #define GU_PTE 11
  81. , { GU_PTE, "cannot read pte: ", kmemstrerr }
  82. #define GU_UPGTBL 12
  83. , { GU_UPGTBL, "cannot read upgtbl: ", mmemstrerr }
  84. #define GU_UPAGE 13
  85. , { GU_UPAGE, "cannot read upage: ", mmemstrerr }
  86. };
  87.  
  88. char *getuserstrerr(ke) strerrfun *ke;
  89. {
  90.  return strerrtaberr(ke,getusererrno,e,sizeof(e)/sizeof(*e),"unknown getuser error");
  91. }
  92.  
  93. #ifndef GETUSERSUPPORT
  94. static short nlpagest;
  95. static unsigned long nlpagesv;
  96. static short nlbaset;
  97. static unsigned long nlbasev;
  98. struct pte *usrpt, *Usrptma;
  99. #endif
  100.  
  101. static int init = 0;
  102.  
  103. int getuserinit()
  104. {
  105. #ifndef GETUSERSUPPORT
  106.  if (nlistadd(NLISTPAGES,&nlpagest,&nlpagesv) == -1)
  107.    RETERN(-1,getusererrno,GU_INIT)
  108.  if (nlistadd(NLISTBASE,&nlbaset,&nlbasev) == -1)
  109.    RETERN(-1,getusererrno,GU_INIT)
  110. #endif
  111.  init = 1;
  112.  return 0;
  113. }
  114.  
  115. static int pergu()
  116. {
  117.  if (!init)
  118.    if (getuserinit() == -1)
  119.      return -1;
  120. #ifndef GETUSERSUPPORT
  121.  if (nlpagest == -1)
  122.   {
  123.    if (nlistdo() == -1)
  124.      RETERN(-1,getusererrno,GU_NLIST)
  125.    if (!nlpagest)
  126.      RETERN(-1,getusererrno,GU_NLPFOUND)
  127.    if (!nlbaset)
  128.      RETERN(-1,getusererrno,GU_NLBFOUND)
  129.   }
  130.  Usrptma = (struct pte *) nlpagesv;
  131.  usrpt = (struct pte *) nlbasev; /* used by <vmmac.h> */
  132. #endif
  133.  return 0;
  134. }
  135.  
  136. #ifdef KVM
  137. static kvm_t *kd = 0;
  138.  
  139. struct user *getuser(p)
  140. struct proc *p;
  141. {
  142.  if (pergu() == -1)
  143.    return 0;
  144.  if (!kd)
  145.    if (!(kd = kvm_open((char *)0,(char *)0,(char *)0,O_RDONLY)))
  146.      RETERN(0,getusererrno,GU_KVM)
  147.  return kvm_getu(kd,p);
  148. }
  149. #else
  150. #ifdef GETUSER_CONVEX
  151. struct user *getuser(p)
  152. struct proc *p;
  153. {
  154.  static struct user u;
  155.  if (pergu() == -1)
  156.    return 0;
  157.  Getprocu(p,&u,sizeof(struct user)); /*XXX*/
  158.  return &u;
  159. }
  160. #else
  161. #ifdef GETUSER_DYNIX
  162. struct user *getuser(p)
  163. struct proc *p;
  164. {
  165.  int btr;
  166.  static struct user *u;
  167.  char *valloc();
  168.  
  169.  u = 0;
  170.  if (pergu() == -1)
  171.    return 0;
  172.  if (!u)
  173.    if (!(u = (struct user *) valloc(ctob(UPAGES))))
  174.      RETERN(0,getusererrno,GU_ALLOC)
  175.  btr = ctob(UPAGES);
  176.  if ((p->p_flag & SLOAD) == 0)
  177.   {
  178.    if (smemcpy((char *)u,(char *) dtob(p->p_swaddr),btr) == -1)
  179.     {
  180.      free((char *) u);
  181.      getusererrno = GU_SLOAD;
  182.      return 0;
  183.     }
  184.   }
  185.  else
  186.    if (kmemcpy((char *)u,(char *)p->p_uarea,btr) == -1)
  187.     {
  188.      free((char *) u);
  189.      getusererrno = GU_UAREA;
  190.      return 0;
  191.     }
  192.  return u;
  193. }
  194. #else
  195. struct user *getuser(p)
  196. struct proc *p;
  197. {
  198.  struct pte *ptep, apte;
  199. #ifdef GETUSER_MIPS
  200.  struct pte wpte[UPAGES];
  201.  int ncl;
  202. #endif
  203.  struct pte mypgtbl[NBPG/sizeof(struct pte)];
  204.  int upage;
  205.  char *up;
  206.  static struct user user;
  207.  
  208.  if (pergu() == -1)
  209.    return 0;
  210.  /* easy way */
  211. #ifndef HAVE_PFLAG
  212.  if ((p->p_sched & SLOAD) == 0)
  213.   {
  214.    struct dmap l_dmap;
  215.    int ublkno;
  216.    /* code adapted from ps.c (or so says ofiles.c) */
  217.    if (kmemcpy(&l_dmap,(char *)(p->p_smap),sizeof(struct dmap)) == -1)
  218.      RETERN(0,getusererrno,GU_DMAP)
  219.    if (kmemcpy(&ublkno,(char *)(l_dmap.dm_ptdaddr),sizeof(int)) == -1)
  220.      RETERN(0,getusererrno,GU_BLKNO)
  221.    if (kmemcpy((char *)&user,(char *)dtob(ublkno),sizeof(struct user)) == -1)
  222.      RETERN(0,getusererrno,GU_UAREA)
  223.    /* that's it? wow ---DJB */
  224.   }
  225. #else
  226.  if ((p->p_flag & SLOAD) == 0)
  227.   {
  228.    if (kmemcpy((char *)&user,(char *)dtob(p->p_swaddr),sizeof(struct user)) == -1)
  229.      RETERN(0,getusererrno,GU_UAREA)
  230.   }
  231. #endif
  232.  else
  233.   {   /* boo */
  234. #ifdef GETUSER_MIPS
  235.    if (kmemcpy((char *)wpte,(char *)p->p_addr,sizeof(wpte)) == -1)
  236.      RETERN(0,getusererrno,GU_PTE)
  237.    
  238.    /* now collect various pages of u area */
  239.    ncl = (sizeof(struct user) + NBPG*CLSIZE - 1)/(NBPG*CLSIZE);
  240.    up = (char *) &user;
  241.    for (upage = 0; upage < ncl; upage += CLSIZE)
  242.     {
  243.      if (mmemcpy(up,(char *)ctob(wpte[upage].pg_pfnum),NBPG*CLSIZE) == -1)
  244.        RETERN(0,getusererrno,GU_UPAGE)
  245.      up += (NBPG*CLSIZE);
  246.     }
  247. #else
  248.    ptep = &Usrptma[btokmx(p->p_p0br) + p->p_szpt - 1];
  249.  
  250.    /* get the page table for the user page */
  251.    if (kmemcpy((char *)&apte,(char *)ptep,sizeof(apte)) == -1)
  252.      RETERN(0,getusererrno,GU_PTE)
  253.  
  254.    /* now get this user's page table */
  255.    if (mmemcpy((char *)mypgtbl,(char *)ctob(apte.pg_pfnum),sizeof(mypgtbl)) == -1)
  256.      RETERN(0,getusererrno,GU_UPGTBL)
  257.    /* now collect various pages of u area */
  258.    up = (char *) &user;
  259.    for (upage = 0; upage < sizeof(struct user)/NBPG; upage++)
  260.     {
  261.      if (mmemcpy(up,(char *)ctob(mypgtbl[NPTEPG-UPAGES+upage].pg_pfnum),NBPG) == -1)
  262.        RETERN(0,getusererrno,GU_UPAGE)
  263.      up += NBPG;
  264.     }
  265. #endif
  266.   }
  267.  return &user;
  268. }
  269. #endif
  270.  
  271. #endif
  272. #endif
  273.