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*59977Smckusick * @(#)kern_sysctl.c 7.40 (Berkeley) 05/12/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> 2259314Smckusick #include <sys/vnode.h> 2357843Smckusick #include <sys/unistd.h> 2457843Smckusick #include <sys/buf.h> 2556517Sbostic #include <sys/ioctl.h> 2656517Sbostic #include <sys/tty.h> 2756517Sbostic #include <vm/vm.h> 2859354Smckusick #include <sys/sysctl.h> 2948407Skarels 3057843Smckusick sysctlfn kern_sysctl; 3157843Smckusick sysctlfn hw_sysctl; 3259161Smckusick #ifdef DEBUG 3359161Smckusick sysctlfn debug_sysctl; 3459161Smckusick #endif 3557843Smckusick extern sysctlfn vm_sysctl; 3657843Smckusick extern sysctlfn fs_sysctl; 3757843Smckusick extern sysctlfn net_sysctl; 3857843Smckusick extern sysctlfn cpu_sysctl; 3940068Smarc 4057843Smckusick /* 4157843Smckusick * Locking and stats 4257843Smckusick */ 4357843Smckusick static struct sysctl_lock { 4457843Smckusick int sl_lock; 4557843Smckusick int sl_want; 4657843Smckusick int sl_locked; 4757843Smckusick } memlock; 4857843Smckusick 4957843Smckusick struct sysctl_args { 5057843Smckusick int *name; 5157843Smckusick u_int namelen; 5257843Smckusick void *old; 5358466Sbostic size_t *oldlenp; 5457843Smckusick void *new; 5558466Sbostic size_t newlen; 5654923Storek }; 5757843Smckusick 5859718Sbostic int 5959718Sbostic __sysctl(p, uap, retval) 6043444Smckusick struct proc *p; 6157843Smckusick register struct sysctl_args *uap; 6243444Smckusick int *retval; 6343444Smckusick { 6457843Smckusick int error, dolock = 1; 6557843Smckusick u_int savelen, oldlen = 0; 6657843Smckusick sysctlfn *fn; 6757843Smckusick int name[CTL_MAXNAME]; 6839963Smarc 6957843Smckusick if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 7057843Smckusick return (error); 7157843Smckusick /* 7257843Smckusick * all top-level sysctl names are non-terminal 7357843Smckusick */ 7457843Smckusick if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 7557843Smckusick return (EINVAL); 7657843Smckusick if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) 7757843Smckusick return (error); 7839963Smarc 7957843Smckusick switch (name[0]) { 8057843Smckusick case CTL_KERN: 8157843Smckusick fn = kern_sysctl; 8257843Smckusick if (name[2] != KERN_VNODE) /* XXX */ 8357843Smckusick dolock = 0; 8439963Smarc break; 8557843Smckusick case CTL_HW: 8657843Smckusick fn = hw_sysctl; 8740068Smarc break; 8857843Smckusick case CTL_VM: 8957843Smckusick fn = vm_sysctl; 9041181Smarc break; 9157843Smckusick case CTL_NET: 9257843Smckusick fn = net_sysctl; 9350149Smarc break; 9457843Smckusick #ifdef notyet 9557843Smckusick case CTL_FS: 9657843Smckusick fn = fs_sysctl; 9750909Smckusick break; 9857843Smckusick case CTL_MACHDEP: 9957843Smckusick fn = cpu_sysctl; 10052669Smckusick break; 10157843Smckusick #endif 10259161Smckusick #ifdef DEBUG 10359161Smckusick case CTL_DEBUG: 10459161Smckusick fn = debug_sysctl; 10559161Smckusick break; 10659161Smckusick #endif 10739963Smarc default: 10857843Smckusick return (EOPNOTSUPP); 10939963Smarc } 11057843Smckusick 11157843Smckusick if (uap->oldlenp && 11257843Smckusick (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 11357843Smckusick return (error); 11457843Smckusick if (uap->old != NULL) { 11557843Smckusick if (!useracc(uap->old, oldlen, B_WRITE)) 11657843Smckusick return (EFAULT); 11757843Smckusick while (memlock.sl_lock) { 11857843Smckusick memlock.sl_want = 1; 11957843Smckusick sleep((caddr_t)&memlock, PRIBIO+1); 12057843Smckusick memlock.sl_locked++; 12157843Smckusick } 12257843Smckusick memlock.sl_lock = 1; 12357843Smckusick if (dolock) 12457843Smckusick vslock(uap->old, oldlen); 12557843Smckusick savelen = oldlen; 12640813Smarc } 12757843Smckusick error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 12858415Smckusick uap->new, uap->newlen, p); 12957843Smckusick if (uap->old != NULL) { 13057843Smckusick if (dolock) 13157843Smckusick vsunlock(uap->old, savelen, B_WRITE); 13257843Smckusick memlock.sl_lock = 0; 13357843Smckusick if (memlock.sl_want) { 13457843Smckusick memlock.sl_want = 0; 13557843Smckusick wakeup((caddr_t)&memlock); 13657843Smckusick } 13740206Smarc } 13857843Smckusick if (error) 13957843Smckusick return (error); 14057843Smckusick if (uap->oldlenp) 14157843Smckusick error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 14257843Smckusick *retval = oldlen; 14357843Smckusick return (0); 14457843Smckusick } 14540206Smarc 14657843Smckusick /* 14757843Smckusick * Attributes stored in the kernel. 14857843Smckusick */ 14957843Smckusick char hostname[MAXHOSTNAMELEN]; 15057843Smckusick int hostnamelen; 15157843Smckusick long hostid; 15258415Smckusick int securelevel; 15357843Smckusick 15458415Smckusick /* 15558415Smckusick * kernel related system variables. 15658415Smckusick */ 15758415Smckusick kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 15857843Smckusick int *name; 15957843Smckusick u_int namelen; 16057843Smckusick void *oldp; 16158466Sbostic size_t *oldlenp; 16257843Smckusick void *newp; 16358466Sbostic size_t newlen; 16458415Smckusick struct proc *p; 16557843Smckusick { 16658415Smckusick int error, level; 16757843Smckusick extern char ostype[], osrelease[], version[]; 16857843Smckusick 16957843Smckusick /* all sysctl names at this level are terminal */ 17059312Smckusick if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) 17157843Smckusick return (ENOTDIR); /* overloaded */ 17257843Smckusick 17357843Smckusick switch (name[0]) { 17457843Smckusick case KERN_OSTYPE: 17557843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 17657843Smckusick case KERN_OSRELEASE: 17757843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 17857843Smckusick case KERN_OSREV: 17957843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 18057843Smckusick case KERN_VERSION: 18157843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, version)); 18259718Sbostic case KERN_MAXVNODES: 18359718Sbostic return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 18457843Smckusick case KERN_MAXPROC: 18557843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 18657843Smckusick case KERN_MAXFILES: 18757843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 18857843Smckusick case KERN_ARGMAX: 18957843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 19058415Smckusick case KERN_SECURELVL: 19158415Smckusick level = securelevel; 19258415Smckusick if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 19358415Smckusick newp == NULL) 19458415Smckusick return (error); 19558415Smckusick if (level < securelevel && p->p_pid != 1) 19658415Smckusick return (EPERM); 19758415Smckusick securelevel = level; 19858415Smckusick return (0); 19959718Sbostic case KERN_HOSTNAME: 20059718Sbostic error = sysctl_string(oldp, oldlenp, newp, newlen, 20159718Sbostic hostname, sizeof(hostname)); 20259718Sbostic if (!error) 20359718Sbostic hostnamelen = newlen; 20459718Sbostic return (error); 20559718Sbostic case KERN_HOSTID: 20659718Sbostic return (sysctl_int(oldp, oldlenp, newp, newlen, &hostid)); 20757843Smckusick case KERN_CLOCKRATE: 20857843Smckusick return (sysctl_clockrate(oldp, oldlenp)); 20957843Smckusick case KERN_VNODE: 21057843Smckusick return (sysctl_vnode(oldp, oldlenp)); 21157843Smckusick case KERN_PROC: 21257843Smckusick return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 21359718Sbostic case KERN_FILE: 21459718Sbostic return (sysctl_file(oldp, oldlenp)); 21559312Smckusick #ifdef GPROF 21659312Smckusick case KERN_PROF: 21759312Smckusick return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 21859312Smckusick newp, newlen)); 21959312Smckusick #endif 22059718Sbostic case KERN_POSIX1: 22159718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 22259718Sbostic case KERN_NGROUPS: 22359718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 22459718Sbostic case KERN_JOB_CONTROL: 22559718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, 1)); 22659718Sbostic case KERN_SAVED_IDS: 22759718Sbostic #ifdef _POSIX_SAVED_IDS 22859718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, 1)); 22959718Sbostic #else 23059718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, 0)); 23159718Sbostic #endif 23259718Sbostic case KERN_LINK_MAX: 23359718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, LINK_MAX)); 23459718Sbostic case KERN_MAX_CANON: 23559718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, MAX_CANON)); 23659718Sbostic case KERN_MAX_INPUT: 23759718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, MAX_INPUT)); 23859718Sbostic case KERN_NAME_MAX: 23959718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, NAME_MAX)); 24059718Sbostic case KERN_PATH_MAX: 24159718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, PATH_MAX)); 24259718Sbostic case KERN_PIPE_BUF: 24359718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, PIPE_BUF)); 24459718Sbostic case KERN_CHOWN_RESTRICTED: 24559718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, 1)); 24659718Sbostic case KERN_NO_TRUNC: 24759749Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 1)); 24859718Sbostic case KERN_VDISABLE: 24959718Sbostic return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VDISABLE)); 25057843Smckusick default: 25157843Smckusick return (EOPNOTSUPP); 25252405Storek } 25357843Smckusick /* NOTREACHED */ 25457843Smckusick } 25557843Smckusick 25658415Smckusick /* 25758415Smckusick * hardware related system variables. 25858415Smckusick */ 25958415Smckusick hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 26057843Smckusick int *name; 26157843Smckusick u_int namelen; 26257843Smckusick void *oldp; 26358466Sbostic size_t *oldlenp; 26457843Smckusick void *newp; 26558466Sbostic size_t newlen; 26658415Smckusick struct proc *p; 26757843Smckusick { 26857843Smckusick extern char machine[], cpu_model[]; 26957843Smckusick 27057843Smckusick /* all sysctl names at this level are terminal */ 27157843Smckusick if (namelen != 1) 27257843Smckusick return (ENOTDIR); /* overloaded */ 27357843Smckusick 27457843Smckusick switch (name[0]) { 27557843Smckusick case HW_MACHINE: 27657843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 27757843Smckusick case HW_MODEL: 27857843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 27957843Smckusick case HW_NCPU: 28057843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 28159618Smckusick case HW_BYTEORDER: 28259618Smckusick return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 28357843Smckusick case HW_PHYSMEM: 28457843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 28557843Smckusick case HW_USERMEM: 28657843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 28757843Smckusick ctob(physmem - cnt.v_wire_count))); 28857843Smckusick case HW_PAGESIZE: 28957843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 29057843Smckusick default: 29157843Smckusick return (EOPNOTSUPP); 29257843Smckusick } 29357843Smckusick /* NOTREACHED */ 29457843Smckusick } 29557843Smckusick 29659161Smckusick #ifdef DEBUG 29757843Smckusick /* 29859161Smckusick * Debugging related system variables. 29959161Smckusick */ 30059161Smckusick struct ctldebug debug0, debug1, debug2, debug3, debug4; 30159161Smckusick struct ctldebug debug5, debug6, debug7, debug8, debug9; 30259161Smckusick struct ctldebug debug10, debug11, debug12, debug13, debug14; 30359161Smckusick struct ctldebug debug15, debug16, debug17, debug18, debug19; 30459161Smckusick static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 30559161Smckusick &debug0, &debug1, &debug2, &debug3, &debug4, 30659161Smckusick &debug5, &debug6, &debug7, &debug8, &debug9, 30759161Smckusick &debug10, &debug11, &debug12, &debug13, &debug14, 30859161Smckusick &debug15, &debug16, &debug17, &debug18, &debug19, 30959161Smckusick }; 31059161Smckusick int 31159161Smckusick debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 31259161Smckusick int *name; 31359161Smckusick u_int namelen; 31459161Smckusick void *oldp; 31559161Smckusick size_t *oldlenp; 31659161Smckusick void *newp; 31759161Smckusick size_t newlen; 31859161Smckusick struct proc *p; 31959161Smckusick { 32059161Smckusick struct ctldebug *cdp; 32159161Smckusick 32259161Smckusick /* all sysctl names at this level are name and field */ 32359161Smckusick if (namelen != 2) 32459161Smckusick return (ENOTDIR); /* overloaded */ 32559161Smckusick cdp = debugvars[name[0]]; 32659161Smckusick if (cdp->debugname == 0) 32759161Smckusick return (EOPNOTSUPP); 32859161Smckusick switch (name[1]) { 32959161Smckusick case CTL_DEBUG_NAME: 33059161Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 33159161Smckusick case CTL_DEBUG_VALUE: 33259161Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 33359161Smckusick default: 33459161Smckusick return (EOPNOTSUPP); 33559161Smckusick } 33659161Smckusick /* NOTREACHED */ 33759161Smckusick } 33859161Smckusick #endif /* DEBUG */ 33959161Smckusick 34059161Smckusick /* 34157843Smckusick * Validate parameters and get old / set new parameters 34257843Smckusick * for an integer-valued sysctl function. 34357843Smckusick */ 34457843Smckusick sysctl_int(oldp, oldlenp, newp, newlen, valp) 34557843Smckusick void *oldp; 34658466Sbostic size_t *oldlenp; 34757843Smckusick void *newp; 34858466Sbostic size_t newlen; 34957843Smckusick int *valp; 35057843Smckusick { 35157843Smckusick int error = 0; 35257843Smckusick 35357843Smckusick if (oldp && *oldlenp < sizeof(int)) 35457843Smckusick return (ENOMEM); 35557843Smckusick if (newp && newlen != sizeof(int)) 35657843Smckusick return (EINVAL); 35757843Smckusick *oldlenp = sizeof(int); 35857843Smckusick if (oldp) 35957843Smckusick error = copyout(valp, oldp, sizeof(int)); 36057843Smckusick if (error == 0 && newp) 36157843Smckusick error = copyin(newp, valp, sizeof(int)); 36243444Smckusick return (error); 36339963Smarc } 36439963Smarc 36557843Smckusick /* 36657843Smckusick * As above, but read-only. 36757843Smckusick */ 36857843Smckusick sysctl_rdint(oldp, oldlenp, newp, val) 36957843Smckusick void *oldp; 37058466Sbostic size_t *oldlenp; 37157843Smckusick void *newp; 37257843Smckusick int val; 37357843Smckusick { 37457843Smckusick int error = 0; 37557843Smckusick 37657843Smckusick if (oldp && *oldlenp < sizeof(int)) 37757843Smckusick return (ENOMEM); 37857843Smckusick if (newp) 37957843Smckusick return (EPERM); 38057843Smckusick *oldlenp = sizeof(int); 38157843Smckusick if (oldp) 38257843Smckusick error = copyout((caddr_t)&val, oldp, sizeof(int)); 38357843Smckusick return (error); 38457843Smckusick } 38557843Smckusick 38657843Smckusick /* 38757843Smckusick * Validate parameters and get old / set new parameters 38857843Smckusick * for a string-valued sysctl function. 38957843Smckusick */ 39057843Smckusick sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 39157843Smckusick void *oldp; 39258466Sbostic size_t *oldlenp; 39357843Smckusick void *newp; 39458466Sbostic size_t newlen; 39557843Smckusick char *str; 39657843Smckusick int maxlen; 39757843Smckusick { 39857843Smckusick int len, error = 0; 39957843Smckusick 40057843Smckusick len = strlen(str) + 1; 40157843Smckusick if (oldp && *oldlenp < len) 40257843Smckusick return (ENOMEM); 40357843Smckusick if (newp && newlen >= maxlen) 40457843Smckusick return (EINVAL); 40558128Sralph if (oldp) { 40658128Sralph *oldlenp = len; 40757843Smckusick error = copyout(str, oldp, len); 40858128Sralph } 40957843Smckusick if (error == 0 && newp) { 41057843Smckusick error = copyin(newp, str, newlen); 41157843Smckusick str[newlen] = 0; 41257843Smckusick } 41357843Smckusick return (error); 41457843Smckusick } 41557843Smckusick 41657843Smckusick /* 41757843Smckusick * As above, but read-only. 41857843Smckusick */ 41957843Smckusick sysctl_rdstring(oldp, oldlenp, newp, str) 42057843Smckusick void *oldp; 42158466Sbostic size_t *oldlenp; 42257843Smckusick void *newp; 42357843Smckusick char *str; 42457843Smckusick { 42557843Smckusick int len, error = 0; 42657843Smckusick 42757843Smckusick len = strlen(str) + 1; 42857843Smckusick if (oldp && *oldlenp < len) 42957843Smckusick return (ENOMEM); 43057843Smckusick if (newp) 43157843Smckusick return (EPERM); 43257843Smckusick *oldlenp = len; 43357843Smckusick if (oldp) 43457843Smckusick error = copyout(str, oldp, len); 43557843Smckusick return (error); 43657843Smckusick } 43757843Smckusick 43857843Smckusick /* 43959312Smckusick * Validate parameters and get old / set new parameters 44059312Smckusick * for a structure oriented sysctl function. 44159312Smckusick */ 44259312Smckusick sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 44359312Smckusick void *oldp; 44459312Smckusick size_t *oldlenp; 44559312Smckusick void *newp; 44659312Smckusick size_t newlen; 44759312Smckusick void *sp; 44859312Smckusick int len; 44959312Smckusick { 45059312Smckusick int error = 0; 45159312Smckusick 45259312Smckusick if (oldp && *oldlenp < len) 45359312Smckusick return (ENOMEM); 45459312Smckusick if (newp && newlen > len) 45559312Smckusick return (EINVAL); 45659312Smckusick if (oldp) { 45759312Smckusick *oldlenp = len; 45859312Smckusick error = copyout(sp, oldp, len); 45959312Smckusick } 46059312Smckusick if (error == 0 && newp) 46159312Smckusick error = copyin(newp, sp, len); 46259312Smckusick return (error); 46359312Smckusick } 46459312Smckusick 46559312Smckusick /* 46657843Smckusick * Validate parameters and get old parameters 46757843Smckusick * for a structure oriented sysctl function. 46857843Smckusick */ 46957843Smckusick sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 47057843Smckusick void *oldp; 47158466Sbostic size_t *oldlenp; 47258466Sbostic void *newp, *sp; 47357843Smckusick int len; 47457843Smckusick { 47557843Smckusick int error = 0; 47657843Smckusick 47757843Smckusick if (oldp && *oldlenp < len) 47857843Smckusick return (ENOMEM); 47957843Smckusick if (newp) 48057843Smckusick return (EPERM); 48157843Smckusick *oldlenp = len; 48257843Smckusick if (oldp) 48357843Smckusick error = copyout(sp, oldp, len); 48457843Smckusick return (error); 48557843Smckusick } 48657843Smckusick 48757843Smckusick /* 48857843Smckusick * Get file structures. 48957843Smckusick */ 49057843Smckusick sysctl_file(where, sizep) 49157843Smckusick char *where; 49258466Sbostic size_t *sizep; 49357843Smckusick { 49457843Smckusick int buflen, error; 49557843Smckusick struct file *fp; 49657843Smckusick char *start = where; 49757843Smckusick 49857843Smckusick buflen = *sizep; 49957843Smckusick if (where == NULL) { 50057843Smckusick /* 50157843Smckusick * overestimate by 10 files 50257843Smckusick */ 50357843Smckusick *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 50457843Smckusick return (0); 50557843Smckusick } 50657843Smckusick 50757843Smckusick /* 50857843Smckusick * first copyout filehead 50957843Smckusick */ 51057843Smckusick if (buflen < sizeof(filehead)) { 51157843Smckusick *sizep = 0; 51257843Smckusick return (0); 51357843Smckusick } 51457843Smckusick if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) 51557843Smckusick return (error); 51657843Smckusick buflen += sizeof(filehead); 51757843Smckusick where += sizeof(filehead); 51857843Smckusick 51957843Smckusick /* 52057843Smckusick * followed by an array of file structures 52157843Smckusick */ 52257843Smckusick for (fp = filehead; fp != NULL; fp = fp->f_filef) { 52357843Smckusick if (buflen < sizeof(struct file)) { 52457843Smckusick *sizep = where - start; 52557843Smckusick return (ENOMEM); 52657843Smckusick } 52757843Smckusick if (error = copyout((caddr_t)fp, where, sizeof (struct file))) 52857843Smckusick return (error); 52957843Smckusick buflen -= sizeof(struct file); 53057843Smckusick where += sizeof(struct file); 53157843Smckusick } 53257843Smckusick *sizep = where - start; 53357843Smckusick return (0); 53457843Smckusick } 53557843Smckusick 53659312Smckusick /* 53759312Smckusick * try over estimating by 5 procs 53839963Smarc */ 53957843Smckusick #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 54039963Smarc 54157843Smckusick sysctl_doproc(name, namelen, where, sizep) 54257843Smckusick int *name; 54358466Sbostic u_int namelen; 54439963Smarc char *where; 54558466Sbostic size_t *sizep; 54639963Smarc { 54739963Smarc register struct proc *p; 54843419Smarc register struct kinfo_proc *dp = (struct kinfo_proc *)where; 54957843Smckusick register int needed = 0; 55057843Smckusick int buflen = where != NULL ? *sizep : 0; 55139963Smarc int doingzomb; 55240067Smarc struct eproc eproc; 55339963Smarc int error = 0; 55439963Smarc 555*59977Smckusick if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 55657843Smckusick return (EINVAL); 55754755Storek p = (struct proc *)allproc; 55839963Smarc doingzomb = 0; 55939963Smarc again: 56039963Smarc for (; p != NULL; p = p->p_nxt) { 56153819Smckusick /* 56253819Smckusick * Skip embryonic processes. 56353819Smckusick */ 56453819Smckusick if (p->p_stat == SIDL) 56553819Smckusick continue; 56659312Smckusick /* 56739963Smarc * TODO - make more efficient (see notes below). 56859312Smckusick * do by session. 56939963Smarc */ 57057843Smckusick switch (name[0]) { 57139963Smarc 57257843Smckusick case KERN_PROC_PID: 57339963Smarc /* could do this with just a lookup */ 57457843Smckusick if (p->p_pid != (pid_t)name[1]) 57539963Smarc continue; 57639963Smarc break; 57739963Smarc 57857843Smckusick case KERN_PROC_PGRP: 57939963Smarc /* could do this by traversing pgrp */ 58057843Smckusick if (p->p_pgrp->pg_id != (pid_t)name[1]) 58139963Smarc continue; 58239963Smarc break; 58339963Smarc 58457843Smckusick case KERN_PROC_TTY: 58559312Smckusick if ((p->p_flag&SCTTY) == 0 || 58639963Smarc p->p_session->s_ttyp == NULL || 58757843Smckusick p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 58839963Smarc continue; 58939963Smarc break; 59039963Smarc 59157843Smckusick case KERN_PROC_UID: 59257843Smckusick if (p->p_ucred->cr_uid != (uid_t)name[1]) 59339963Smarc continue; 59439963Smarc break; 59539963Smarc 59657843Smckusick case KERN_PROC_RUID: 59757843Smckusick if (p->p_cred->p_ruid != (uid_t)name[1]) 59839963Smarc continue; 59939963Smarc break; 60039963Smarc } 60157843Smckusick if (buflen >= sizeof(struct kinfo_proc)) { 60248407Skarels fill_eproc(p, &eproc); 60359312Smckusick if (error = copyout((caddr_t)p, &dp->kp_proc, 60457843Smckusick sizeof(struct proc))) 60539963Smarc return (error); 60659312Smckusick if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 60757843Smckusick sizeof(eproc))) 60839963Smarc return (error); 60943419Smarc dp++; 61057843Smckusick buflen -= sizeof(struct kinfo_proc); 61139963Smarc } 61257843Smckusick needed += sizeof(struct kinfo_proc); 61339963Smarc } 61439963Smarc if (doingzomb == 0) { 61539963Smarc p = zombproc; 61639963Smarc doingzomb++; 61739963Smarc goto again; 61839963Smarc } 61957843Smckusick if (where != NULL) { 62057843Smckusick *sizep = (caddr_t)dp - where; 62157843Smckusick if (needed > *sizep) 62257843Smckusick return (ENOMEM); 62357843Smckusick } else { 62457843Smckusick needed += KERN_PROCSLOP; 62557843Smckusick *sizep = needed; 62657843Smckusick } 62739963Smarc return (0); 62839963Smarc } 62948407Skarels 63048407Skarels /* 63148407Skarels * Fill in an eproc structure for the specified process. 63248407Skarels */ 63348407Skarels void 63448407Skarels fill_eproc(p, ep) 63548407Skarels register struct proc *p; 63648407Skarels register struct eproc *ep; 63748407Skarels { 63848407Skarels register struct tty *tp; 63948407Skarels 64048407Skarels ep->e_paddr = p; 64148407Skarels ep->e_sess = p->p_pgrp->pg_session; 64248407Skarels ep->e_pcred = *p->p_cred; 64348407Skarels ep->e_ucred = *p->p_ucred; 64452405Storek if (p->p_stat == SIDL || p->p_stat == SZOMB) { 64552405Storek ep->e_vm.vm_rssize = 0; 64652405Storek ep->e_vm.vm_tsize = 0; 64752405Storek ep->e_vm.vm_dsize = 0; 64852405Storek ep->e_vm.vm_ssize = 0; 64952405Storek #ifndef sparc 65052405Storek /* ep->e_vm.vm_pmap = XXX; */ 65152405Storek #endif 65252405Storek } else { 65352405Storek register struct vmspace *vm = p->p_vmspace; 65452405Storek 65552405Storek ep->e_vm.vm_rssize = vm->vm_rssize; 65652405Storek ep->e_vm.vm_tsize = vm->vm_tsize; 65752405Storek ep->e_vm.vm_dsize = vm->vm_dsize; 65852405Storek ep->e_vm.vm_ssize = vm->vm_ssize; 65952405Storek #ifndef sparc 66052405Storek ep->e_vm.vm_pmap = vm->vm_pmap; 66152405Storek #endif 66252405Storek } 66349141Skarels if (p->p_pptr) 66449141Skarels ep->e_ppid = p->p_pptr->p_pid; 66549141Skarels else 66649141Skarels ep->e_ppid = 0; 66748407Skarels ep->e_pgid = p->p_pgrp->pg_id; 66848407Skarels ep->e_jobc = p->p_pgrp->pg_jobc; 66959312Smckusick if ((p->p_flag&SCTTY) && 67048407Skarels (tp = ep->e_sess->s_ttyp)) { 67148407Skarels ep->e_tdev = tp->t_dev; 67250022Skarels ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 67348407Skarels ep->e_tsess = tp->t_session; 67448407Skarels } else 67548407Skarels ep->e_tdev = NODEV; 67648407Skarels ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 67748407Skarels if (SESS_LEADER(p)) 67848407Skarels ep->e_flag |= EPROC_SLEADER; 67948407Skarels if (p->p_wmesg) 68048407Skarels strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 68148407Skarels ep->e_xsize = ep->e_xrssize = 0; 68248407Skarels ep->e_xccount = ep->e_xswrss = 0; 68348407Skarels } 68450149Smarc 68557843Smckusick #ifdef COMPAT_43 68657843Smckusick #include <sys/socket.h> 68757906Smckusick #define KINFO_PROC (0<<8) 68857906Smckusick #define KINFO_RT (1<<8) 68957906Smckusick #define KINFO_VNODE (2<<8) 69057906Smckusick #define KINFO_FILE (3<<8) 69157906Smckusick #define KINFO_METER (4<<8) 69257906Smckusick #define KINFO_LOADAVG (5<<8) 69357906Smckusick #define KINFO_CLOCKRATE (6<<8) 69457843Smckusick 69557843Smckusick struct getkerninfo_args { 69657843Smckusick int op; 69757843Smckusick char *where; 69857843Smckusick int *size; 69957843Smckusick int arg; 70057843Smckusick }; 70157843Smckusick 70258943Smckusick ogetkerninfo(p, uap, retval) 70357843Smckusick struct proc *p; 70457843Smckusick register struct getkerninfo_args *uap; 70557843Smckusick int *retval; 70650149Smarc { 70757843Smckusick int error, name[5]; 70857843Smckusick u_int size; 70950149Smarc 71058461Smckusick if (uap->size && 71158466Sbostic (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 71257843Smckusick return (error); 71350149Smarc 71457906Smckusick switch (uap->op & 0xff00) { 71550149Smarc 71657843Smckusick case KINFO_RT: 71757843Smckusick name[0] = PF_ROUTE; 71857843Smckusick name[1] = 0; 71957843Smckusick name[2] = (uap->op & 0xff0000) >> 16; 72057843Smckusick name[3] = uap->op & 0xff; 72157843Smckusick name[4] = uap->arg; 72258415Smckusick error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 72357843Smckusick break; 72457843Smckusick 72557843Smckusick case KINFO_VNODE: 72657843Smckusick name[0] = KERN_VNODE; 72758415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 72857843Smckusick break; 72957843Smckusick 73057843Smckusick case KINFO_PROC: 73157843Smckusick name[0] = KERN_PROC; 73257843Smckusick name[1] = uap->op & 0xff; 73357843Smckusick name[2] = uap->arg; 73458415Smckusick error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 73557843Smckusick break; 73657843Smckusick 73757843Smckusick case KINFO_FILE: 73857843Smckusick name[0] = KERN_FILE; 73958415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 74057843Smckusick break; 74157843Smckusick 74257843Smckusick case KINFO_METER: 74357843Smckusick name[0] = VM_METER; 74458415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 74557843Smckusick break; 74657843Smckusick 74757843Smckusick case KINFO_LOADAVG: 74857843Smckusick name[0] = VM_LOADAVG; 74958415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 75057843Smckusick break; 75157843Smckusick 75257843Smckusick case KINFO_CLOCKRATE: 75357843Smckusick name[0] = KERN_CLOCKRATE; 75458415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 75557843Smckusick break; 75657843Smckusick 75757843Smckusick default: 75858415Smckusick return (EOPNOTSUPP); 75950149Smarc } 76057843Smckusick if (error) 76157843Smckusick return (error); 76257843Smckusick *retval = size; 76358461Smckusick if (uap->size) 76458461Smckusick error = copyout((caddr_t)&size, (caddr_t)uap->size, 76558461Smckusick sizeof(size)); 76658461Smckusick return (error); 76750149Smarc } 76857843Smckusick #endif /* COMPAT_43 */ 769