|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.