139963Smarc /* 239963Smarc * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 339963Smarc * All rights reserved. 439963Smarc * 5*44435Sbostic * %sccs.include.redist.c% 639963Smarc * 7*44435Sbostic * @(#)kern_sysctl.c 7.11 (Berkeley) 06/28/90 839963Smarc */ 939963Smarc 1039965Smckusick #include "param.h" 1139965Smckusick #include "user.h" 1239965Smckusick #include "proc.h" 1340206Smarc #include "text.h" 1439963Smarc #include "kinfo.h" 1539963Smarc #include "vm.h" 1639963Smarc #include "ioctl.h" 1739963Smarc #include "tty.h" 1839963Smarc #include "buf.h" 1939963Smarc 2040068Smarc 2140068Smarc #define snderr(e) { error = (e); goto release;} 2241181Smarc extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode(); 2340068Smarc struct kinfo_lock kinfo_lock; 2440068Smarc 2543444Smckusick /* ARGSUSED */ 2643444Smckusick getkerninfo(p, uap, retval) 2743444Smckusick struct proc *p; 2843444Smckusick register struct args { 2939963Smarc int op; 3039963Smarc char *where; 3139963Smarc int *size; 3239963Smarc int arg; 3343444Smckusick } *uap; 3443444Smckusick int *retval; 3543444Smckusick { 3640206Smarc 3740068Smarc int bufsize, /* max size of users buffer */ 3840206Smarc needed, locked, (*server)(), error = 0; 3939963Smarc 4040206Smarc if (error = copyin((caddr_t)uap->size, 4140206Smarc (caddr_t)&bufsize, sizeof (bufsize))) 4240813Smarc goto done; 4340068Smarc 4439963Smarc switch (ki_type(uap->op)) { 4539963Smarc 4639963Smarc case KINFO_PROC: 4740068Smarc server = kinfo_doproc; 4839963Smarc break; 4939963Smarc 5040068Smarc case KINFO_RT: 5140068Smarc server = kinfo_rtable; 5240068Smarc break; 5340068Smarc 5441181Smarc case KINFO_VNODE: 5541181Smarc server = kinfo_vnode; 5641181Smarc break; 5741181Smarc 5839963Smarc default: 5940206Smarc error = EINVAL; 6040813Smarc goto done; 6139963Smarc } 6240813Smarc if (uap->where == NULL || uap->size == NULL) { 6340813Smarc error = (*server)(uap->op, NULL, NULL, uap->arg, &needed); 6440813Smarc goto done; 6540813Smarc } 6640206Smarc while (kinfo_lock.kl_lock) { 6740206Smarc kinfo_lock.kl_want++; 6840206Smarc sleep(&kinfo_lock, PRIBIO+1); 6940206Smarc kinfo_lock.kl_want--; 7040206Smarc kinfo_lock.kl_locked++; 7140206Smarc } 7240206Smarc kinfo_lock.kl_lock++; 7340206Smarc 7440813Smarc if (!useracc(uap->where, bufsize, B_WRITE)) 7540068Smarc snderr(EFAULT); 7640068Smarc /* 7740068Smarc * lock down target pages - NEED DEADLOCK AVOIDANCE 7840068Smarc */ 7940813Smarc if (bufsize > ((int)ptob(freemem) - (20 * 1024))) /* XXX */ 8040068Smarc snderr(ENOMEM); 8141181Smarc if (server != kinfo_vnode) /* XXX */ 8241181Smarc vslock(uap->where, bufsize); 8340813Smarc locked = bufsize; 8440813Smarc error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed); 8541181Smarc if (server != kinfo_vnode) /* XXX */ 8641181Smarc vsunlock(uap->where, locked, B_WRITE); 8740813Smarc if (error == 0) 8840813Smarc error = copyout((caddr_t)&bufsize, 8940813Smarc (caddr_t)uap->size, sizeof (bufsize)); 9040068Smarc release: 9140068Smarc kinfo_lock.kl_lock--; 9240068Smarc if (kinfo_lock.kl_want) 9340068Smarc wakeup(&kinfo_lock); 9440813Smarc done: 9543444Smckusick if (!error) 9643444Smckusick *retval = needed; 9743444Smckusick return (error); 9839963Smarc } 9939963Smarc 10039963Smarc /* 10139963Smarc * try over estimating by 5 procs 10239963Smarc */ 10339963Smarc #define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc)) 10439963Smarc 10540206Smarc kinfo_doproc(op, where, acopysize, arg, aneeded) 10639963Smarc char *where; 10739963Smarc int *acopysize, *aneeded; 10839963Smarc { 10939963Smarc register struct proc *p; 11043419Smarc register struct kinfo_proc *dp = (struct kinfo_proc *)where; 11139963Smarc register needed = 0; 11239963Smarc int buflen; 11339963Smarc int doingzomb; 11440067Smarc struct eproc eproc; 11539963Smarc int error = 0; 11639963Smarc 11739963Smarc if (where != NULL) 11839963Smarc buflen = *acopysize; 11939963Smarc 12039963Smarc p = allproc; 12139963Smarc doingzomb = 0; 12239963Smarc again: 12339963Smarc for (; p != NULL; p = p->p_nxt) { 12439963Smarc /* 12539963Smarc * TODO - make more efficient (see notes below). 12639963Smarc * do by session. 12739963Smarc */ 12839963Smarc switch (ki_op(op)) { 12939963Smarc 13039963Smarc case KINFO_PROC_PID: 13139963Smarc /* could do this with just a lookup */ 13239963Smarc if (p->p_pid != (pid_t)arg) 13339963Smarc continue; 13439963Smarc break; 13539963Smarc 13639963Smarc case KINFO_PROC_PGRP: 13739963Smarc /* could do this by traversing pgrp */ 13839963Smarc if (p->p_pgrp->pg_id != (pid_t)arg) 13939963Smarc continue; 14039963Smarc break; 14139963Smarc 14239963Smarc case KINFO_PROC_TTY: 14339963Smarc if ((p->p_flag&SCTTY) == 0 || 14439963Smarc p->p_session->s_ttyp == NULL || 14539963Smarc p->p_session->s_ttyp->t_dev != (dev_t)arg) 14639963Smarc continue; 14739963Smarc break; 14839963Smarc 14939963Smarc case KINFO_PROC_UID: 15039963Smarc if (p->p_uid != (uid_t)arg) 15139963Smarc continue; 15239963Smarc break; 15339963Smarc 15439963Smarc case KINFO_PROC_RUID: 15539963Smarc if (p->p_ruid != (uid_t)arg) 15639963Smarc continue; 15739963Smarc break; 15839963Smarc } 15939963Smarc if (where != NULL && buflen >= sizeof (struct kinfo_proc)) { 16040206Smarc register struct text *txt; 16143419Smarc register struct tty *tp; 16240206Smarc 16343419Smarc if (error = copyout((caddr_t)p, &dp->kp_proc, 16439963Smarc sizeof (struct proc))) 16539963Smarc return (error); 16640206Smarc eproc.e_paddr = p; 16740206Smarc eproc.e_sess = p->p_pgrp->pg_session; 16840206Smarc eproc.e_pgid = p->p_pgrp->pg_id; 16940206Smarc eproc.e_jobc = p->p_pgrp->pg_jobc; 17043419Smarc if ((p->p_flag&SCTTY) && 17143419Smarc (tp = eproc.e_sess->s_ttyp)) { 17240206Smarc eproc.e_tdev = tp->t_dev; 17340206Smarc eproc.e_tpgid = tp->t_pgrp ? 17439963Smarc tp->t_pgrp->pg_id : -1; 17540206Smarc eproc.e_tsess = tp->t_session; 17639963Smarc } else 17740206Smarc eproc.e_tdev = NODEV; 17843419Smarc eproc.e_flag = eproc.e_sess->s_ttyvp ? EPROC_CTTY : 0; 17943419Smarc if (SESS_LEADER(p)) 18043419Smarc eproc.e_flag |= EPROC_SLEADER; 18140206Smarc if (p->p_wmesg) 18240206Smarc strncpy(eproc.e_wmesg, p->p_wmesg, WMESGLEN); 18340206Smarc if (txt = p->p_textp) { 18440206Smarc eproc.e_xsize = txt->x_size; 18540206Smarc eproc.e_xrssize = txt->x_rssize; 18640206Smarc eproc.e_xccount = txt->x_ccount; 18740206Smarc eproc.e_xswrss = txt->x_swrss; 18840206Smarc } else { 18940206Smarc eproc.e_xsize = eproc.e_xrssize = 19040206Smarc eproc.e_xccount = eproc.e_xswrss = 0; 19140206Smarc } 19243419Smarc if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 19340067Smarc sizeof (eproc))) 19439963Smarc return (error); 19543419Smarc dp++; 19639963Smarc buflen -= sizeof (struct kinfo_proc); 19739963Smarc } 19839963Smarc needed += sizeof (struct kinfo_proc); 19939963Smarc } 20039963Smarc if (doingzomb == 0) { 20139963Smarc p = zombproc; 20239963Smarc doingzomb++; 20339963Smarc goto again; 20439963Smarc } 20539963Smarc if (where != NULL) 20643419Smarc *acopysize = (caddr_t)dp - where; 20740068Smarc else 20840068Smarc needed += KINFO_PROCSLOP; 20939963Smarc *aneeded = needed; 21039963Smarc 21139963Smarc return (0); 21239963Smarc } 213