139963Smarc /* 239963Smarc * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 339963Smarc * All rights reserved. 439963Smarc * 544435Sbostic * %sccs.include.redist.c% 639963Smarc * 7*47545Skarels * @(#)kern_sysctl.c 7.13 (Berkeley) 03/17/91 839963Smarc */ 939963Smarc 1039965Smckusick #include "param.h" 1139965Smckusick #include "user.h" 1239965Smckusick #include "proc.h" 1339963Smarc #include "kinfo.h" 1439963Smarc #include "ioctl.h" 1539963Smarc #include "tty.h" 1639963Smarc #include "buf.h" 1739963Smarc 1840068Smarc #define snderr(e) { error = (e); goto release;} 1941181Smarc extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode(); 2040068Smarc struct kinfo_lock kinfo_lock; 2140068Smarc 2243444Smckusick /* ARGSUSED */ 2343444Smckusick getkerninfo(p, uap, retval) 2443444Smckusick struct proc *p; 2543444Smckusick register struct args { 2639963Smarc int op; 2739963Smarc char *where; 2839963Smarc int *size; 2939963Smarc int arg; 3043444Smckusick } *uap; 3143444Smckusick int *retval; 3243444Smckusick { 3340206Smarc 34*47545Skarels int bufsize; /* max size of users buffer */ 35*47545Skarels int needed, locked, (*server)(), error = 0; 3639963Smarc 37*47545Skarels if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize, 38*47545Skarels sizeof (bufsize))) 3940813Smarc goto done; 4040068Smarc 4139963Smarc switch (ki_type(uap->op)) { 4239963Smarc 4339963Smarc case KINFO_PROC: 4440068Smarc server = kinfo_doproc; 4539963Smarc break; 4639963Smarc 4740068Smarc case KINFO_RT: 4840068Smarc server = kinfo_rtable; 4940068Smarc break; 5040068Smarc 5141181Smarc case KINFO_VNODE: 5241181Smarc server = kinfo_vnode; 5341181Smarc break; 5441181Smarc 5539963Smarc default: 5640206Smarc error = EINVAL; 5740813Smarc goto done; 5839963Smarc } 5940813Smarc if (uap->where == NULL || uap->size == NULL) { 6040813Smarc error = (*server)(uap->op, NULL, NULL, uap->arg, &needed); 6140813Smarc goto done; 6240813Smarc } 6340206Smarc while (kinfo_lock.kl_lock) { 6440206Smarc kinfo_lock.kl_want++; 6540206Smarc sleep(&kinfo_lock, PRIBIO+1); 6640206Smarc kinfo_lock.kl_want--; 6740206Smarc kinfo_lock.kl_locked++; 6840206Smarc } 6940206Smarc kinfo_lock.kl_lock++; 7040206Smarc 7140813Smarc if (!useracc(uap->where, bufsize, B_WRITE)) 7240068Smarc snderr(EFAULT); 7341181Smarc if (server != kinfo_vnode) /* XXX */ 7441181Smarc vslock(uap->where, bufsize); 7540813Smarc locked = bufsize; 7640813Smarc error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed); 7741181Smarc if (server != kinfo_vnode) /* XXX */ 7841181Smarc vsunlock(uap->where, locked, B_WRITE); 7940813Smarc if (error == 0) 8040813Smarc error = copyout((caddr_t)&bufsize, 8140813Smarc (caddr_t)uap->size, sizeof (bufsize)); 8240068Smarc release: 8340068Smarc kinfo_lock.kl_lock--; 8440068Smarc if (kinfo_lock.kl_want) 8540068Smarc wakeup(&kinfo_lock); 8640813Smarc done: 8743444Smckusick if (!error) 8843444Smckusick *retval = needed; 8943444Smckusick return (error); 9039963Smarc } 9139963Smarc 9239963Smarc /* 9339963Smarc * try over estimating by 5 procs 9439963Smarc */ 9539963Smarc #define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc)) 9639963Smarc 9740206Smarc kinfo_doproc(op, where, acopysize, arg, aneeded) 9839963Smarc char *where; 9939963Smarc int *acopysize, *aneeded; 10039963Smarc { 10139963Smarc register struct proc *p; 10243419Smarc register struct kinfo_proc *dp = (struct kinfo_proc *)where; 10339963Smarc register needed = 0; 10439963Smarc int buflen; 10539963Smarc int doingzomb; 10640067Smarc struct eproc eproc; 10739963Smarc int error = 0; 10839963Smarc 10939963Smarc if (where != NULL) 11039963Smarc buflen = *acopysize; 11139963Smarc 11239963Smarc p = allproc; 11339963Smarc doingzomb = 0; 11439963Smarc again: 11539963Smarc for (; p != NULL; p = p->p_nxt) { 11639963Smarc /* 11739963Smarc * TODO - make more efficient (see notes below). 11839963Smarc * do by session. 11939963Smarc */ 12039963Smarc switch (ki_op(op)) { 12139963Smarc 12239963Smarc case KINFO_PROC_PID: 12339963Smarc /* could do this with just a lookup */ 12439963Smarc if (p->p_pid != (pid_t)arg) 12539963Smarc continue; 12639963Smarc break; 12739963Smarc 12839963Smarc case KINFO_PROC_PGRP: 12939963Smarc /* could do this by traversing pgrp */ 13039963Smarc if (p->p_pgrp->pg_id != (pid_t)arg) 13139963Smarc continue; 13239963Smarc break; 13339963Smarc 13439963Smarc case KINFO_PROC_TTY: 13539963Smarc if ((p->p_flag&SCTTY) == 0 || 13639963Smarc p->p_session->s_ttyp == NULL || 13739963Smarc p->p_session->s_ttyp->t_dev != (dev_t)arg) 13839963Smarc continue; 13939963Smarc break; 14039963Smarc 14139963Smarc case KINFO_PROC_UID: 142*47545Skarels if (p->p_ucred->cr_uid != (uid_t)arg) 14339963Smarc continue; 14439963Smarc break; 14539963Smarc 14639963Smarc case KINFO_PROC_RUID: 147*47545Skarels if (p->p_cred->p_ruid != (uid_t)arg) 14839963Smarc continue; 14939963Smarc break; 15039963Smarc } 15139963Smarc if (where != NULL && buflen >= sizeof (struct kinfo_proc)) { 15243419Smarc register struct tty *tp; 15340206Smarc 15443419Smarc if (error = copyout((caddr_t)p, &dp->kp_proc, 15539963Smarc sizeof (struct proc))) 15639963Smarc return (error); 15740206Smarc eproc.e_paddr = p; 15840206Smarc eproc.e_sess = p->p_pgrp->pg_session; 159*47545Skarels eproc.e_pcred = *p->p_cred; 160*47545Skarels eproc.e_ucred = *p->p_ucred; 161*47545Skarels eproc.e_vm = *p->p_vmspace; 16240206Smarc eproc.e_pgid = p->p_pgrp->pg_id; 16340206Smarc eproc.e_jobc = p->p_pgrp->pg_jobc; 16443419Smarc if ((p->p_flag&SCTTY) && 16543419Smarc (tp = eproc.e_sess->s_ttyp)) { 16640206Smarc eproc.e_tdev = tp->t_dev; 16740206Smarc eproc.e_tpgid = tp->t_pgrp ? 16839963Smarc tp->t_pgrp->pg_id : -1; 16940206Smarc eproc.e_tsess = tp->t_session; 17039963Smarc } else 17140206Smarc eproc.e_tdev = NODEV; 17243419Smarc eproc.e_flag = eproc.e_sess->s_ttyvp ? EPROC_CTTY : 0; 17343419Smarc if (SESS_LEADER(p)) 17443419Smarc eproc.e_flag |= EPROC_SLEADER; 17540206Smarc if (p->p_wmesg) 17640206Smarc strncpy(eproc.e_wmesg, p->p_wmesg, WMESGLEN); 17745728Smckusick eproc.e_xsize = eproc.e_xrssize = 0; 17845728Smckusick eproc.e_xccount = eproc.e_xswrss = 0; 17943419Smarc if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 18040067Smarc sizeof (eproc))) 18139963Smarc return (error); 18243419Smarc dp++; 18339963Smarc buflen -= sizeof (struct kinfo_proc); 18439963Smarc } 18539963Smarc needed += sizeof (struct kinfo_proc); 18639963Smarc } 18739963Smarc if (doingzomb == 0) { 18839963Smarc p = zombproc; 18939963Smarc doingzomb++; 19039963Smarc goto again; 19139963Smarc } 19239963Smarc if (where != NULL) 19343419Smarc *acopysize = (caddr_t)dp - where; 19440068Smarc else 19540068Smarc needed += KINFO_PROCSLOP; 19639963Smarc *aneeded = needed; 19739963Smarc 19839963Smarc return (0); 19939963Smarc } 200