home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / kern_kinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-26  |  7.2 KB  |  301 lines

  1. /*
  2.  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)kern_kinfo.c    7.17 (Berkeley) 6/26/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "proc.h"
  38. #include "kinfo.h"
  39. #include "ioctl.h"
  40. #include "tty.h"
  41. #include "buf.h"
  42. #include "file.h"
  43.  
  44. #include "vm/vm.h"
  45.  
  46. #include "kinfo_proc.h"
  47.  
  48. #define snderr(e) { error = (e); goto release;}
  49. extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode(), kinfo_file();
  50. struct kinfo_lock kinfo_lock;
  51.  
  52. /* ARGSUSED */
  53. getkerninfo(p, uap, retval)
  54.     struct proc *p;
  55.     register struct args {
  56.         int    op;
  57.         char    *where;
  58.         int    *size;
  59.         int    arg;
  60.     } *uap;
  61.     int *retval;
  62. {
  63.  
  64.     int bufsize;        /* max size of users buffer */
  65.     int needed, locked, (*server)(), error = 0;
  66.  
  67.     if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize,
  68.         sizeof (bufsize)))
  69.         goto done;
  70.  
  71.     switch (ki_type(uap->op)) {
  72.  
  73.     case KINFO_PROC:
  74.         server = kinfo_doproc;
  75.         break;
  76.  
  77.     case KINFO_RT:
  78.         server = kinfo_rtable;
  79.         break;
  80.  
  81.     case KINFO_VNODE:
  82.         server = kinfo_vnode;
  83.         break;
  84.  
  85.     case KINFO_FILE:
  86.         server = kinfo_file;
  87.         break;
  88.  
  89.     default:
  90.         error = EINVAL;
  91.         goto done;
  92.     }
  93.     if (uap->where == NULL || uap->size == NULL) {
  94.         error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
  95.         goto done;
  96.     }
  97.     while (kinfo_lock.kl_lock) {
  98.         kinfo_lock.kl_want++;
  99.         sleep(&kinfo_lock, PRIBIO+1);
  100.         kinfo_lock.kl_want--;
  101.         kinfo_lock.kl_locked++;
  102.     }
  103.     kinfo_lock.kl_lock++;
  104.  
  105.     if (!useracc(uap->where, bufsize, B_WRITE))
  106.         snderr(EFAULT);
  107.     if (server != kinfo_vnode)    /* XXX */
  108.         vslock(uap->where, bufsize);
  109.     locked = bufsize;
  110.     error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed);
  111.     if (server != kinfo_vnode)    /* XXX */
  112.         vsunlock(uap->where, locked, B_WRITE);
  113.     if (error == 0)
  114.         error = copyout((caddr_t)&bufsize,
  115.                 (caddr_t)uap->size, sizeof (bufsize));
  116. release:
  117.     kinfo_lock.kl_lock--;
  118.     if (kinfo_lock.kl_want)
  119.         wakeup(&kinfo_lock);
  120. done:
  121.     if (!error)
  122.         *retval = needed;
  123.     return (error);
  124. }
  125.  
  126. /* 
  127.  * try over estimating by 5 procs 
  128.  */
  129. #define KINFO_PROCSLOP    (5 * sizeof (struct kinfo_proc))
  130.  
  131. kinfo_doproc(op, where, acopysize, arg, aneeded)
  132.     char *where;
  133.     int *acopysize, *aneeded;
  134. {
  135.     register struct proc *p;
  136.     register struct kinfo_proc *dp = (struct kinfo_proc *)where;
  137.     register needed = 0;
  138.     int buflen;
  139.     int doingzomb;
  140.     struct eproc eproc;
  141.     int error = 0;
  142.  
  143.     if (where != NULL)
  144.         buflen = *acopysize;
  145.  
  146.     p = allproc;
  147.     doingzomb = 0;
  148. again:
  149.     for (; p != NULL; p = p->p_nxt) {
  150.         /* 
  151.          * TODO - make more efficient (see notes below).
  152.          * do by session. 
  153.          */
  154.         switch (ki_op(op)) {
  155.  
  156.         case KINFO_PROC_PID:
  157.             /* could do this with just a lookup */
  158.             if (p->p_pid != (pid_t)arg)
  159.                 continue;
  160.             break;
  161.  
  162.         case KINFO_PROC_PGRP:
  163.             /* could do this by traversing pgrp */
  164.             if (p->p_pgrp->pg_id != (pid_t)arg)
  165.                 continue;
  166.             break;
  167.  
  168.         case KINFO_PROC_TTY:
  169.             if ((p->p_flag&SCTTY) == 0 || 
  170.                 p->p_session->s_ttyp == NULL ||
  171.                 p->p_session->s_ttyp->t_dev != (dev_t)arg)
  172.                 continue;
  173.             break;
  174.  
  175.         case KINFO_PROC_UID:
  176.             if (p->p_ucred->cr_uid != (uid_t)arg)
  177.                 continue;
  178.             break;
  179.  
  180.         case KINFO_PROC_RUID:
  181.             if (p->p_cred->p_ruid != (uid_t)arg)
  182.                 continue;
  183.             break;
  184.         }
  185.         if (where != NULL && buflen >= sizeof (struct kinfo_proc)) {
  186.             fill_eproc(p, &eproc);
  187.             if (error = copyout((caddr_t)p, &dp->kp_proc, 
  188.                 sizeof (struct proc)))
  189.                 return (error);
  190.             if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 
  191.                 sizeof (eproc)))
  192.                 return (error);
  193.             dp++;
  194.             buflen -= sizeof (struct kinfo_proc);
  195.         }
  196.         needed += sizeof (struct kinfo_proc);
  197.     }
  198.     if (doingzomb == 0) {
  199.         p = zombproc;
  200.         doingzomb++;
  201.         goto again;
  202.     }
  203.     if (where != NULL)
  204.         *acopysize = (caddr_t)dp - where;
  205.     else
  206.         needed += KINFO_PROCSLOP;
  207.     *aneeded = needed;
  208.  
  209.     return (0);
  210. }
  211.  
  212. /*
  213.  * Fill in an eproc structure for the specified process.
  214.  */
  215. void
  216. fill_eproc(p, ep)
  217.     register struct proc *p;
  218.     register struct eproc *ep;
  219. {
  220.     register struct tty *tp;
  221.  
  222.     ep->e_paddr = p;
  223.     ep->e_sess = p->p_pgrp->pg_session;
  224.     ep->e_pcred = *p->p_cred;
  225.     ep->e_ucred = *p->p_ucred;
  226.     ep->e_vm = *p->p_vmspace;
  227.     if (p->p_pptr)
  228.         ep->e_ppid = p->p_pptr->p_pid;
  229.     else
  230.         ep->e_ppid = 0;
  231.     ep->e_pgid = p->p_pgrp->pg_id;
  232.     ep->e_jobc = p->p_pgrp->pg_jobc;
  233.     if ((p->p_flag&SCTTY) && 
  234.          (tp = ep->e_sess->s_ttyp)) {
  235.         ep->e_tdev = tp->t_dev;
  236.         ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
  237.         ep->e_tsess = tp->t_session;
  238.     } else
  239.         ep->e_tdev = NODEV;
  240.     ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
  241.     if (SESS_LEADER(p))
  242.         ep->e_flag |= EPROC_SLEADER;
  243.     if (p->p_wmesg)
  244.         strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
  245.     ep->e_xsize = ep->e_xrssize = 0;
  246.     ep->e_xccount = ep->e_xswrss = 0;
  247. }
  248.  
  249. /*
  250.  * Get file structures.
  251.  */
  252. kinfo_file(op, where, acopysize, arg, aneeded)
  253.     register char *where;
  254.     int *acopysize, *aneeded;
  255. {
  256.     int buflen, needed, error;
  257.     struct file *fp;
  258.     char *start = where;
  259.  
  260.     if (where == NULL) {
  261.         /*
  262.          * overestimate by 10 files
  263.          */
  264.         *aneeded = sizeof (filehead) + 
  265.             (nfiles + 10) * sizeof (struct file);
  266.         return (0);
  267.     }
  268.     buflen = *acopysize;
  269.     needed = 0;
  270.  
  271.     /*
  272.      * first copyout filehead
  273.      */
  274.     if (buflen > sizeof (filehead)) {
  275.         if (error = copyout((caddr_t)&filehead, where,
  276.             sizeof (filehead)))
  277.             return (error);
  278.         buflen -= sizeof (filehead);
  279.         where += sizeof (filehead);
  280.     }
  281.     needed += sizeof (filehead);
  282.  
  283.     /*
  284.      * followed by an array of file structures
  285.      */
  286.     for (fp = filehead; fp != NULL; fp = fp->f_filef) {
  287.         if (buflen > sizeof (struct file)) {
  288.             if (error = copyout((caddr_t)fp, where,
  289.                 sizeof (struct file)))
  290.                 return (error);
  291.             buflen -= sizeof (struct file);
  292.             where += sizeof (struct file);
  293.         }
  294.         needed += sizeof (struct file);
  295.     }
  296.     *acopysize = where - start;
  297.     *aneeded = needed;
  298.  
  299.     return (0);
  300. }
  301.