157843Smckusick /*- 257843Smckusick * Copyright (c) 1982, 1986, 1989, 1993 Regents of the University of California. 339963Smarc * All rights reserved. 439963Smarc * 557843Smckusick * This code is derived from software contributed to Berkeley by 657843Smckusick * Mike Karels at Berkeley Software Design, Inc. 757843Smckusick * 844435Sbostic * %sccs.include.redist.c% 939963Smarc * 10*59161Smckusick * @(#)kern_sysctl.c 7.33 (Berkeley) 04/19/93 1139963Smarc */ 1239963Smarc 1357843Smckusick /* 1457843Smckusick * sysctl system call. 1557843Smckusick */ 1657843Smckusick 1756517Sbostic #include <sys/param.h> 1857843Smckusick #include <sys/systm.h> 1957843Smckusick #include <sys/malloc.h> 2056517Sbostic #include <sys/proc.h> 2157843Smckusick #include <sys/file.h> 2257843Smckusick #include <sys/sysctl.h> 2357843Smckusick #include <sys/unistd.h> 2457843Smckusick #include <sys/buf.h> 2556517Sbostic #include <sys/ioctl.h> 2656517Sbostic #include <sys/tty.h> 2739963Smarc 2856517Sbostic #include <vm/vm.h> 2948407Skarels 3056517Sbostic #include <sys/kinfo_proc.h> 3148407Skarels 3257843Smckusick sysctlfn kern_sysctl; 3357843Smckusick sysctlfn hw_sysctl; 34*59161Smckusick #ifdef DEBUG 35*59161Smckusick sysctlfn debug_sysctl; 36*59161Smckusick #endif 3757843Smckusick extern sysctlfn vm_sysctl; 3857843Smckusick extern sysctlfn fs_sysctl; 3957843Smckusick extern sysctlfn net_sysctl; 4057843Smckusick extern sysctlfn cpu_sysctl; 4140068Smarc 4257843Smckusick /* 4357843Smckusick * Locking and stats 4457843Smckusick */ 4557843Smckusick static struct sysctl_lock { 4657843Smckusick int sl_lock; 4757843Smckusick int sl_want; 4857843Smckusick int sl_locked; 4957843Smckusick } memlock; 5057843Smckusick 5157843Smckusick struct sysctl_args { 5257843Smckusick int *name; 5357843Smckusick u_int namelen; 5457843Smckusick void *old; 5558466Sbostic size_t *oldlenp; 5657843Smckusick void *new; 5758466Sbostic size_t newlen; 5854923Storek }; 5957843Smckusick 6057843Smckusick sysctl(p, uap, retval) 6143444Smckusick struct proc *p; 6257843Smckusick register struct sysctl_args *uap; 6343444Smckusick int *retval; 6443444Smckusick { 6557843Smckusick int error, dolock = 1; 6657843Smckusick u_int savelen, oldlen = 0; 6757843Smckusick sysctlfn *fn; 6857843Smckusick int name[CTL_MAXNAME]; 6939963Smarc 7057843Smckusick if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 7157843Smckusick return (error); 7257843Smckusick /* 7357843Smckusick * all top-level sysctl names are non-terminal 7457843Smckusick */ 7557843Smckusick if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 7657843Smckusick return (EINVAL); 7757843Smckusick if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) 7857843Smckusick return (error); 7939963Smarc 8057843Smckusick switch (name[0]) { 8157843Smckusick case CTL_KERN: 8257843Smckusick fn = kern_sysctl; 8357843Smckusick if (name[2] != KERN_VNODE) /* XXX */ 8457843Smckusick dolock = 0; 8539963Smarc break; 8657843Smckusick case CTL_HW: 8757843Smckusick fn = hw_sysctl; 8840068Smarc break; 8957843Smckusick case CTL_VM: 9057843Smckusick fn = vm_sysctl; 9141181Smarc break; 9257843Smckusick case CTL_NET: 9357843Smckusick fn = net_sysctl; 9450149Smarc break; 9557843Smckusick #ifdef notyet 9657843Smckusick case CTL_FS: 9757843Smckusick fn = fs_sysctl; 9850909Smckusick break; 9957843Smckusick case CTL_MACHDEP: 10057843Smckusick fn = cpu_sysctl; 10152669Smckusick break; 10257843Smckusick #endif 103*59161Smckusick #ifdef DEBUG 104*59161Smckusick case CTL_DEBUG: 105*59161Smckusick fn = debug_sysctl; 106*59161Smckusick break; 107*59161Smckusick #endif 10839963Smarc default: 10957843Smckusick return (EOPNOTSUPP); 11039963Smarc } 11157843Smckusick 11257843Smckusick if (uap->oldlenp && 11357843Smckusick (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 11457843Smckusick return (error); 11557843Smckusick if (uap->old != NULL) { 11657843Smckusick if (!useracc(uap->old, oldlen, B_WRITE)) 11757843Smckusick return (EFAULT); 11857843Smckusick while (memlock.sl_lock) { 11957843Smckusick memlock.sl_want = 1; 12057843Smckusick sleep((caddr_t)&memlock, PRIBIO+1); 12157843Smckusick memlock.sl_locked++; 12257843Smckusick } 12357843Smckusick memlock.sl_lock = 1; 12457843Smckusick if (dolock) 12557843Smckusick vslock(uap->old, oldlen); 12657843Smckusick savelen = oldlen; 12740813Smarc } 12857843Smckusick error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 12958415Smckusick uap->new, uap->newlen, p); 13057843Smckusick if (uap->old != NULL) { 13157843Smckusick if (dolock) 13257843Smckusick vsunlock(uap->old, savelen, B_WRITE); 13357843Smckusick memlock.sl_lock = 0; 13457843Smckusick if (memlock.sl_want) { 13557843Smckusick memlock.sl_want = 0; 13657843Smckusick wakeup((caddr_t)&memlock); 13757843Smckusick } 13840206Smarc } 13957843Smckusick if (error) 14057843Smckusick return (error); 14157843Smckusick if (uap->oldlenp) 14257843Smckusick error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 14357843Smckusick *retval = oldlen; 14457843Smckusick return (0); 14557843Smckusick } 14640206Smarc 14757843Smckusick /* 14857843Smckusick * Attributes stored in the kernel. 14957843Smckusick */ 15057843Smckusick char hostname[MAXHOSTNAMELEN]; 15157843Smckusick int hostnamelen; 15257843Smckusick long hostid; 15358415Smckusick int securelevel; 15457843Smckusick 15558415Smckusick /* 15658415Smckusick * kernel related system variables. 15758415Smckusick */ 15858415Smckusick kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 15957843Smckusick int *name; 16057843Smckusick u_int namelen; 16157843Smckusick void *oldp; 16258466Sbostic size_t *oldlenp; 16357843Smckusick void *newp; 16458466Sbostic size_t newlen; 16558415Smckusick struct proc *p; 16657843Smckusick { 16758415Smckusick int error, level; 16857843Smckusick extern char ostype[], osrelease[], version[]; 16957843Smckusick 17057843Smckusick /* all sysctl names at this level are terminal */ 17157843Smckusick if (namelen != 1 && name[0] != KERN_PROC) 17257843Smckusick return (ENOTDIR); /* overloaded */ 17357843Smckusick 17457843Smckusick switch (name[0]) { 17557843Smckusick case KERN_OSTYPE: 17657843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 17757843Smckusick case KERN_OSRELEASE: 17857843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 17957843Smckusick case KERN_OSREV: 18057843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 18157843Smckusick case KERN_VERSION: 18257843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, version)); 18357843Smckusick case KERN_POSIX1: 18457843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 18557843Smckusick case KERN_MAXPROC: 18657843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 18757843Smckusick case KERN_MAXFILES: 18857843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 18957843Smckusick case KERN_ARGMAX: 19057843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 19157843Smckusick case KERN_HOSTNAME: 19257843Smckusick error = sysctl_string(oldp, oldlenp, newp, newlen, 19357843Smckusick hostname, sizeof(hostname)); 19457843Smckusick if (!error) 19557843Smckusick hostnamelen = newlen; 19657843Smckusick return (error); 19757843Smckusick case KERN_HOSTID: 19857843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &hostid)); 19958415Smckusick case KERN_SECURELVL: 20058415Smckusick level = securelevel; 20158415Smckusick if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 20258415Smckusick newp == NULL) 20358415Smckusick return (error); 20458415Smckusick if (level < securelevel && p->p_pid != 1) 20558415Smckusick return (EPERM); 20658415Smckusick securelevel = level; 20758415Smckusick return (0); 20857843Smckusick case KERN_CLOCKRATE: 20957843Smckusick return (sysctl_clockrate(oldp, oldlenp)); 21057843Smckusick case KERN_FILE: 21157843Smckusick return (sysctl_file(oldp, oldlenp)); 21257843Smckusick case KERN_VNODE: 21357843Smckusick return (sysctl_vnode(oldp, oldlenp)); 21457843Smckusick case KERN_PROC: 21557843Smckusick return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 21657843Smckusick default: 21757843Smckusick return (EOPNOTSUPP); 21852405Storek } 21957843Smckusick /* NOTREACHED */ 22057843Smckusick } 22157843Smckusick 22258415Smckusick /* 22358415Smckusick * hardware related system variables. 22458415Smckusick */ 22558415Smckusick hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 22657843Smckusick int *name; 22757843Smckusick u_int namelen; 22857843Smckusick void *oldp; 22958466Sbostic size_t *oldlenp; 23057843Smckusick void *newp; 23158466Sbostic size_t newlen; 23258415Smckusick struct proc *p; 23357843Smckusick { 23457843Smckusick extern char machine[], cpu_model[]; 23557843Smckusick 23657843Smckusick /* all sysctl names at this level are terminal */ 23757843Smckusick if (namelen != 1) 23857843Smckusick return (ENOTDIR); /* overloaded */ 23957843Smckusick 24057843Smckusick switch (name[0]) { 24157843Smckusick case HW_MACHINE: 24257843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 24357843Smckusick case HW_MODEL: 24457843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 24557843Smckusick case HW_NCPU: 24657843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 24757843Smckusick case HW_CPUSPEED: 24857843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed)); 24957843Smckusick case HW_PHYSMEM: 25057843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 25157843Smckusick case HW_USERMEM: 25257843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 25357843Smckusick ctob(physmem - cnt.v_wire_count))); 25457843Smckusick case HW_PAGESIZE: 25557843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 25657843Smckusick default: 25757843Smckusick return (EOPNOTSUPP); 25857843Smckusick } 25957843Smckusick /* NOTREACHED */ 26057843Smckusick } 26157843Smckusick 262*59161Smckusick #ifdef DEBUG 26357843Smckusick /* 264*59161Smckusick * Debugging related system variables. 265*59161Smckusick */ 266*59161Smckusick struct ctldebug debug0, debug1, debug2, debug3, debug4; 267*59161Smckusick struct ctldebug debug5, debug6, debug7, debug8, debug9; 268*59161Smckusick struct ctldebug debug10, debug11, debug12, debug13, debug14; 269*59161Smckusick struct ctldebug debug15, debug16, debug17, debug18, debug19; 270*59161Smckusick static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 271*59161Smckusick &debug0, &debug1, &debug2, &debug3, &debug4, 272*59161Smckusick &debug5, &debug6, &debug7, &debug8, &debug9, 273*59161Smckusick &debug10, &debug11, &debug12, &debug13, &debug14, 274*59161Smckusick &debug15, &debug16, &debug17, &debug18, &debug19, 275*59161Smckusick }; 276*59161Smckusick int 277*59161Smckusick debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 278*59161Smckusick int *name; 279*59161Smckusick u_int namelen; 280*59161Smckusick void *oldp; 281*59161Smckusick size_t *oldlenp; 282*59161Smckusick void *newp; 283*59161Smckusick size_t newlen; 284*59161Smckusick struct proc *p; 285*59161Smckusick { 286*59161Smckusick struct ctldebug *cdp; 287*59161Smckusick 288*59161Smckusick /* all sysctl names at this level are name and field */ 289*59161Smckusick if (namelen != 2) 290*59161Smckusick return (ENOTDIR); /* overloaded */ 291*59161Smckusick cdp = debugvars[name[0]]; 292*59161Smckusick if (cdp->debugname == 0) 293*59161Smckusick return (EOPNOTSUPP); 294*59161Smckusick switch (name[1]) { 295*59161Smckusick case CTL_DEBUG_NAME: 296*59161Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 297*59161Smckusick case CTL_DEBUG_VALUE: 298*59161Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 299*59161Smckusick default: 300*59161Smckusick return (EOPNOTSUPP); 301*59161Smckusick } 302*59161Smckusick /* NOTREACHED */ 303*59161Smckusick } 304*59161Smckusick #endif /* DEBUG */ 305*59161Smckusick 306*59161Smckusick /* 30757843Smckusick * Validate parameters and get old / set new parameters 30857843Smckusick * for an integer-valued sysctl function. 30957843Smckusick */ 31057843Smckusick sysctl_int(oldp, oldlenp, newp, newlen, valp) 31157843Smckusick void *oldp; 31258466Sbostic size_t *oldlenp; 31357843Smckusick void *newp; 31458466Sbostic size_t newlen; 31557843Smckusick int *valp; 31657843Smckusick { 31757843Smckusick int error = 0; 31857843Smckusick 31957843Smckusick if (oldp && *oldlenp < sizeof(int)) 32057843Smckusick return (ENOMEM); 32157843Smckusick if (newp && newlen != sizeof(int)) 32257843Smckusick return (EINVAL); 32357843Smckusick *oldlenp = sizeof(int); 32457843Smckusick if (oldp) 32557843Smckusick error = copyout(valp, oldp, sizeof(int)); 32657843Smckusick if (error == 0 && newp) 32757843Smckusick error = copyin(newp, valp, sizeof(int)); 32843444Smckusick return (error); 32939963Smarc } 33039963Smarc 33157843Smckusick /* 33257843Smckusick * As above, but read-only. 33357843Smckusick */ 33457843Smckusick sysctl_rdint(oldp, oldlenp, newp, val) 33557843Smckusick void *oldp; 33658466Sbostic size_t *oldlenp; 33757843Smckusick void *newp; 33857843Smckusick int val; 33957843Smckusick { 34057843Smckusick int error = 0; 34157843Smckusick 34257843Smckusick if (oldp && *oldlenp < sizeof(int)) 34357843Smckusick return (ENOMEM); 34457843Smckusick if (newp) 34557843Smckusick return (EPERM); 34657843Smckusick *oldlenp = sizeof(int); 34757843Smckusick if (oldp) 34857843Smckusick error = copyout((caddr_t)&val, oldp, sizeof(int)); 34957843Smckusick return (error); 35057843Smckusick } 35157843Smckusick 35257843Smckusick /* 35357843Smckusick * Validate parameters and get old / set new parameters 35457843Smckusick * for a string-valued sysctl function. 35557843Smckusick */ 35657843Smckusick sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 35757843Smckusick void *oldp; 35858466Sbostic size_t *oldlenp; 35957843Smckusick void *newp; 36058466Sbostic size_t newlen; 36157843Smckusick char *str; 36257843Smckusick int maxlen; 36357843Smckusick { 36457843Smckusick int len, error = 0; 36557843Smckusick 36657843Smckusick len = strlen(str) + 1; 36757843Smckusick if (oldp && *oldlenp < len) 36857843Smckusick return (ENOMEM); 36957843Smckusick if (newp && newlen >= maxlen) 37057843Smckusick return (EINVAL); 37158128Sralph if (oldp) { 37258128Sralph *oldlenp = len; 37357843Smckusick error = copyout(str, oldp, len); 37458128Sralph } 37557843Smckusick if (error == 0 && newp) { 37657843Smckusick error = copyin(newp, str, newlen); 37757843Smckusick str[newlen] = 0; 37857843Smckusick } 37957843Smckusick return (error); 38057843Smckusick } 38157843Smckusick 38257843Smckusick /* 38357843Smckusick * As above, but read-only. 38457843Smckusick */ 38557843Smckusick sysctl_rdstring(oldp, oldlenp, newp, str) 38657843Smckusick void *oldp; 38758466Sbostic size_t *oldlenp; 38857843Smckusick void *newp; 38957843Smckusick char *str; 39057843Smckusick { 39157843Smckusick int len, error = 0; 39257843Smckusick 39357843Smckusick len = strlen(str) + 1; 39457843Smckusick if (oldp && *oldlenp < len) 39557843Smckusick return (ENOMEM); 39657843Smckusick if (newp) 39757843Smckusick return (EPERM); 39857843Smckusick *oldlenp = len; 39957843Smckusick if (oldp) 40057843Smckusick error = copyout(str, oldp, len); 40157843Smckusick return (error); 40257843Smckusick } 40357843Smckusick 40457843Smckusick /* 40557843Smckusick * Validate parameters and get old parameters 40657843Smckusick * for a structure oriented sysctl function. 40757843Smckusick */ 40857843Smckusick sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 40957843Smckusick void *oldp; 41058466Sbostic size_t *oldlenp; 41158466Sbostic void *newp, *sp; 41257843Smckusick int len; 41357843Smckusick { 41457843Smckusick int error = 0; 41557843Smckusick 41657843Smckusick if (oldp && *oldlenp < len) 41757843Smckusick return (ENOMEM); 41857843Smckusick if (newp) 41957843Smckusick return (EPERM); 42057843Smckusick *oldlenp = len; 42157843Smckusick if (oldp) 42257843Smckusick error = copyout(sp, oldp, len); 42357843Smckusick return (error); 42457843Smckusick } 42557843Smckusick 42657843Smckusick /* 42757843Smckusick * Get file structures. 42857843Smckusick */ 42957843Smckusick sysctl_file(where, sizep) 43057843Smckusick char *where; 43158466Sbostic size_t *sizep; 43257843Smckusick { 43357843Smckusick int buflen, error; 43457843Smckusick struct file *fp; 43557843Smckusick char *start = where; 43657843Smckusick 43757843Smckusick buflen = *sizep; 43857843Smckusick if (where == NULL) { 43957843Smckusick /* 44057843Smckusick * overestimate by 10 files 44157843Smckusick */ 44257843Smckusick *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 44357843Smckusick return (0); 44457843Smckusick } 44557843Smckusick 44657843Smckusick /* 44757843Smckusick * first copyout filehead 44857843Smckusick */ 44957843Smckusick if (buflen < sizeof(filehead)) { 45057843Smckusick *sizep = 0; 45157843Smckusick return (0); 45257843Smckusick } 45357843Smckusick if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) 45457843Smckusick return (error); 45557843Smckusick buflen += sizeof(filehead); 45657843Smckusick where += sizeof(filehead); 45757843Smckusick 45857843Smckusick /* 45957843Smckusick * followed by an array of file structures 46057843Smckusick */ 46157843Smckusick for (fp = filehead; fp != NULL; fp = fp->f_filef) { 46257843Smckusick if (buflen < sizeof(struct file)) { 46357843Smckusick *sizep = where - start; 46457843Smckusick return (ENOMEM); 46557843Smckusick } 46657843Smckusick if (error = copyout((caddr_t)fp, where, sizeof (struct file))) 46757843Smckusick return (error); 46857843Smckusick buflen -= sizeof(struct file); 46957843Smckusick where += sizeof(struct file); 47057843Smckusick } 47157843Smckusick *sizep = where - start; 47257843Smckusick return (0); 47357843Smckusick } 47457843Smckusick 47539963Smarc /* 47639963Smarc * try over estimating by 5 procs 47739963Smarc */ 47857843Smckusick #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 47939963Smarc 48057843Smckusick sysctl_doproc(name, namelen, where, sizep) 48157843Smckusick int *name; 48258466Sbostic u_int namelen; 48339963Smarc char *where; 48458466Sbostic size_t *sizep; 48539963Smarc { 48639963Smarc register struct proc *p; 48743419Smarc register struct kinfo_proc *dp = (struct kinfo_proc *)where; 48857843Smckusick register int needed = 0; 48957843Smckusick int buflen = where != NULL ? *sizep : 0; 49039963Smarc int doingzomb; 49140067Smarc struct eproc eproc; 49239963Smarc int error = 0; 49339963Smarc 49457843Smckusick if (namelen != 2) 49557843Smckusick return (EINVAL); 49654755Storek p = (struct proc *)allproc; 49739963Smarc doingzomb = 0; 49839963Smarc again: 49939963Smarc for (; p != NULL; p = p->p_nxt) { 50053819Smckusick /* 50153819Smckusick * Skip embryonic processes. 50253819Smckusick */ 50353819Smckusick if (p->p_stat == SIDL) 50453819Smckusick continue; 50539963Smarc /* 50639963Smarc * TODO - make more efficient (see notes below). 50739963Smarc * do by session. 50839963Smarc */ 50957843Smckusick switch (name[0]) { 51039963Smarc 51157843Smckusick case KERN_PROC_PID: 51239963Smarc /* could do this with just a lookup */ 51357843Smckusick if (p->p_pid != (pid_t)name[1]) 51439963Smarc continue; 51539963Smarc break; 51639963Smarc 51757843Smckusick case KERN_PROC_PGRP: 51839963Smarc /* could do this by traversing pgrp */ 51957843Smckusick if (p->p_pgrp->pg_id != (pid_t)name[1]) 52039963Smarc continue; 52139963Smarc break; 52239963Smarc 52357843Smckusick case KERN_PROC_TTY: 52439963Smarc if ((p->p_flag&SCTTY) == 0 || 52539963Smarc p->p_session->s_ttyp == NULL || 52657843Smckusick p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 52739963Smarc continue; 52839963Smarc break; 52939963Smarc 53057843Smckusick case KERN_PROC_UID: 53157843Smckusick if (p->p_ucred->cr_uid != (uid_t)name[1]) 53239963Smarc continue; 53339963Smarc break; 53439963Smarc 53557843Smckusick case KERN_PROC_RUID: 53657843Smckusick if (p->p_cred->p_ruid != (uid_t)name[1]) 53739963Smarc continue; 53839963Smarc break; 53939963Smarc } 54057843Smckusick if (buflen >= sizeof(struct kinfo_proc)) { 54148407Skarels fill_eproc(p, &eproc); 54243419Smarc if (error = copyout((caddr_t)p, &dp->kp_proc, 54357843Smckusick sizeof(struct proc))) 54439963Smarc return (error); 54543419Smarc if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 54657843Smckusick sizeof(eproc))) 54739963Smarc return (error); 54843419Smarc dp++; 54957843Smckusick buflen -= sizeof(struct kinfo_proc); 55039963Smarc } 55157843Smckusick needed += sizeof(struct kinfo_proc); 55239963Smarc } 55339963Smarc if (doingzomb == 0) { 55439963Smarc p = zombproc; 55539963Smarc doingzomb++; 55639963Smarc goto again; 55739963Smarc } 55857843Smckusick if (where != NULL) { 55957843Smckusick *sizep = (caddr_t)dp - where; 56057843Smckusick if (needed > *sizep) 56157843Smckusick return (ENOMEM); 56257843Smckusick } else { 56357843Smckusick needed += KERN_PROCSLOP; 56457843Smckusick *sizep = needed; 56557843Smckusick } 56639963Smarc return (0); 56739963Smarc } 56848407Skarels 56948407Skarels /* 57048407Skarels * Fill in an eproc structure for the specified process. 57148407Skarels */ 57248407Skarels void 57348407Skarels fill_eproc(p, ep) 57448407Skarels register struct proc *p; 57548407Skarels register struct eproc *ep; 57648407Skarels { 57748407Skarels register struct tty *tp; 57848407Skarels 57948407Skarels ep->e_paddr = p; 58048407Skarels ep->e_sess = p->p_pgrp->pg_session; 58148407Skarels ep->e_pcred = *p->p_cred; 58248407Skarels ep->e_ucred = *p->p_ucred; 58352405Storek if (p->p_stat == SIDL || p->p_stat == SZOMB) { 58452405Storek ep->e_vm.vm_rssize = 0; 58552405Storek ep->e_vm.vm_tsize = 0; 58652405Storek ep->e_vm.vm_dsize = 0; 58752405Storek ep->e_vm.vm_ssize = 0; 58852405Storek #ifndef sparc 58952405Storek /* ep->e_vm.vm_pmap = XXX; */ 59052405Storek #endif 59152405Storek } else { 59252405Storek register struct vmspace *vm = p->p_vmspace; 59352405Storek 59452405Storek ep->e_vm.vm_rssize = vm->vm_rssize; 59552405Storek ep->e_vm.vm_tsize = vm->vm_tsize; 59652405Storek ep->e_vm.vm_dsize = vm->vm_dsize; 59752405Storek ep->e_vm.vm_ssize = vm->vm_ssize; 59852405Storek #ifndef sparc 59952405Storek ep->e_vm.vm_pmap = vm->vm_pmap; 60052405Storek #endif 60152405Storek } 60249141Skarels if (p->p_pptr) 60349141Skarels ep->e_ppid = p->p_pptr->p_pid; 60449141Skarels else 60549141Skarels ep->e_ppid = 0; 60648407Skarels ep->e_pgid = p->p_pgrp->pg_id; 60748407Skarels ep->e_jobc = p->p_pgrp->pg_jobc; 60848407Skarels if ((p->p_flag&SCTTY) && 60948407Skarels (tp = ep->e_sess->s_ttyp)) { 61048407Skarels ep->e_tdev = tp->t_dev; 61150022Skarels ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 61248407Skarels ep->e_tsess = tp->t_session; 61348407Skarels } else 61448407Skarels ep->e_tdev = NODEV; 61548407Skarels ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 61648407Skarels if (SESS_LEADER(p)) 61748407Skarels ep->e_flag |= EPROC_SLEADER; 61848407Skarels if (p->p_wmesg) 61948407Skarels strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 62048407Skarels ep->e_xsize = ep->e_xrssize = 0; 62148407Skarels ep->e_xccount = ep->e_xswrss = 0; 62248407Skarels } 62350149Smarc 62457843Smckusick #ifdef COMPAT_43 62557843Smckusick #include <sys/socket.h> 62657906Smckusick #define KINFO_PROC (0<<8) 62757906Smckusick #define KINFO_RT (1<<8) 62857906Smckusick #define KINFO_VNODE (2<<8) 62957906Smckusick #define KINFO_FILE (3<<8) 63057906Smckusick #define KINFO_METER (4<<8) 63157906Smckusick #define KINFO_LOADAVG (5<<8) 63257906Smckusick #define KINFO_CLOCKRATE (6<<8) 63357843Smckusick 63457843Smckusick struct getkerninfo_args { 63557843Smckusick int op; 63657843Smckusick char *where; 63757843Smckusick int *size; 63857843Smckusick int arg; 63957843Smckusick }; 64057843Smckusick 64158943Smckusick ogetkerninfo(p, uap, retval) 64257843Smckusick struct proc *p; 64357843Smckusick register struct getkerninfo_args *uap; 64457843Smckusick int *retval; 64550149Smarc { 64657843Smckusick int error, name[5]; 64757843Smckusick u_int size; 64850149Smarc 64958461Smckusick if (uap->size && 65058466Sbostic (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 65157843Smckusick return (error); 65250149Smarc 65357906Smckusick switch (uap->op & 0xff00) { 65450149Smarc 65557843Smckusick case KINFO_RT: 65657843Smckusick name[0] = PF_ROUTE; 65757843Smckusick name[1] = 0; 65857843Smckusick name[2] = (uap->op & 0xff0000) >> 16; 65957843Smckusick name[3] = uap->op & 0xff; 66057843Smckusick name[4] = uap->arg; 66158415Smckusick error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 66257843Smckusick break; 66357843Smckusick 66457843Smckusick case KINFO_VNODE: 66557843Smckusick name[0] = KERN_VNODE; 66658415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 66757843Smckusick break; 66857843Smckusick 66957843Smckusick case KINFO_PROC: 67057843Smckusick name[0] = KERN_PROC; 67157843Smckusick name[1] = uap->op & 0xff; 67257843Smckusick name[2] = uap->arg; 67358415Smckusick error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 67457843Smckusick break; 67557843Smckusick 67657843Smckusick case KINFO_FILE: 67757843Smckusick name[0] = KERN_FILE; 67858415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 67957843Smckusick break; 68057843Smckusick 68157843Smckusick case KINFO_METER: 68257843Smckusick name[0] = VM_METER; 68358415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 68457843Smckusick break; 68557843Smckusick 68657843Smckusick case KINFO_LOADAVG: 68757843Smckusick name[0] = VM_LOADAVG; 68858415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 68957843Smckusick break; 69057843Smckusick 69157843Smckusick case KINFO_CLOCKRATE: 69257843Smckusick name[0] = KERN_CLOCKRATE; 69358415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 69457843Smckusick break; 69557843Smckusick 69657843Smckusick default: 69758415Smckusick return (EOPNOTSUPP); 69850149Smarc } 69957843Smckusick if (error) 70057843Smckusick return (error); 70157843Smckusick *retval = size; 70258461Smckusick if (uap->size) 70358461Smckusick error = copyout((caddr_t)&size, (caddr_t)uap->size, 70458461Smckusick sizeof(size)); 70558461Smckusick return (error); 70650149Smarc } 70757843Smckusick #endif /* COMPAT_43 */ 708