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*59618Smckusick * @(#)kern_sysctl.c 7.37 (Berkeley) 05/01/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 5857843Smckusick sysctl(p, uap, retval) 5943444Smckusick struct proc *p; 6057843Smckusick register struct sysctl_args *uap; 6143444Smckusick int *retval; 6243444Smckusick { 6357843Smckusick int error, dolock = 1; 6457843Smckusick u_int savelen, oldlen = 0; 6557843Smckusick sysctlfn *fn; 6657843Smckusick int name[CTL_MAXNAME]; 6739963Smarc 6857843Smckusick if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 6957843Smckusick return (error); 7057843Smckusick /* 7157843Smckusick * all top-level sysctl names are non-terminal 7257843Smckusick */ 7357843Smckusick if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 7457843Smckusick return (EINVAL); 7557843Smckusick if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) 7657843Smckusick return (error); 7739963Smarc 7857843Smckusick switch (name[0]) { 7957843Smckusick case CTL_KERN: 8057843Smckusick fn = kern_sysctl; 8157843Smckusick if (name[2] != KERN_VNODE) /* XXX */ 8257843Smckusick dolock = 0; 8339963Smarc break; 8457843Smckusick case CTL_HW: 8557843Smckusick fn = hw_sysctl; 8640068Smarc break; 8757843Smckusick case CTL_VM: 8857843Smckusick fn = vm_sysctl; 8941181Smarc break; 9057843Smckusick case CTL_NET: 9157843Smckusick fn = net_sysctl; 9250149Smarc break; 9357843Smckusick #ifdef notyet 9457843Smckusick case CTL_FS: 9557843Smckusick fn = fs_sysctl; 9650909Smckusick break; 9757843Smckusick case CTL_MACHDEP: 9857843Smckusick fn = cpu_sysctl; 9952669Smckusick break; 10057843Smckusick #endif 10159161Smckusick #ifdef DEBUG 10259161Smckusick case CTL_DEBUG: 10359161Smckusick fn = debug_sysctl; 10459161Smckusick break; 10559161Smckusick #endif 10639963Smarc default: 10757843Smckusick return (EOPNOTSUPP); 10839963Smarc } 10957843Smckusick 11057843Smckusick if (uap->oldlenp && 11157843Smckusick (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 11257843Smckusick return (error); 11357843Smckusick if (uap->old != NULL) { 11457843Smckusick if (!useracc(uap->old, oldlen, B_WRITE)) 11557843Smckusick return (EFAULT); 11657843Smckusick while (memlock.sl_lock) { 11757843Smckusick memlock.sl_want = 1; 11857843Smckusick sleep((caddr_t)&memlock, PRIBIO+1); 11957843Smckusick memlock.sl_locked++; 12057843Smckusick } 12157843Smckusick memlock.sl_lock = 1; 12257843Smckusick if (dolock) 12357843Smckusick vslock(uap->old, oldlen); 12457843Smckusick savelen = oldlen; 12540813Smarc } 12657843Smckusick error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 12758415Smckusick uap->new, uap->newlen, p); 12857843Smckusick if (uap->old != NULL) { 12957843Smckusick if (dolock) 13057843Smckusick vsunlock(uap->old, savelen, B_WRITE); 13157843Smckusick memlock.sl_lock = 0; 13257843Smckusick if (memlock.sl_want) { 13357843Smckusick memlock.sl_want = 0; 13457843Smckusick wakeup((caddr_t)&memlock); 13557843Smckusick } 13640206Smarc } 13757843Smckusick if (error) 13857843Smckusick return (error); 13957843Smckusick if (uap->oldlenp) 14057843Smckusick error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 14157843Smckusick *retval = oldlen; 14257843Smckusick return (0); 14357843Smckusick } 14440206Smarc 14557843Smckusick /* 14657843Smckusick * Attributes stored in the kernel. 14757843Smckusick */ 14857843Smckusick char hostname[MAXHOSTNAMELEN]; 14957843Smckusick int hostnamelen; 15057843Smckusick long hostid; 15158415Smckusick int securelevel; 15257843Smckusick 15358415Smckusick /* 15458415Smckusick * kernel related system variables. 15558415Smckusick */ 15658415Smckusick kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 15757843Smckusick int *name; 15857843Smckusick u_int namelen; 15957843Smckusick void *oldp; 16058466Sbostic size_t *oldlenp; 16157843Smckusick void *newp; 16258466Sbostic size_t newlen; 16358415Smckusick struct proc *p; 16457843Smckusick { 16558415Smckusick int error, level; 16657843Smckusick extern char ostype[], osrelease[], version[]; 16757843Smckusick 16857843Smckusick /* all sysctl names at this level are terminal */ 16959312Smckusick if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) 17057843Smckusick return (ENOTDIR); /* overloaded */ 17157843Smckusick 17257843Smckusick switch (name[0]) { 17357843Smckusick case KERN_OSTYPE: 17457843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 17557843Smckusick case KERN_OSRELEASE: 17657843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 17757843Smckusick case KERN_OSREV: 17857843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 17957843Smckusick case KERN_VERSION: 18057843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, version)); 18157843Smckusick case KERN_POSIX1: 18257843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 18357843Smckusick case KERN_MAXPROC: 18457843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 18557843Smckusick case KERN_MAXFILES: 18657843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 18759314Smckusick case KERN_MAXVNODES: 18859314Smckusick return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 18957843Smckusick case KERN_ARGMAX: 19057843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 19157843Smckusick case KERN_HOSTNAME: 19259312Smckusick 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)); 21659312Smckusick #ifdef GPROF 21759312Smckusick case KERN_PROF: 21859312Smckusick return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 21959312Smckusick newp, newlen)); 22059312Smckusick #endif 22157843Smckusick default: 22257843Smckusick return (EOPNOTSUPP); 22352405Storek } 22457843Smckusick /* NOTREACHED */ 22557843Smckusick } 22657843Smckusick 22758415Smckusick /* 22858415Smckusick * hardware related system variables. 22958415Smckusick */ 23058415Smckusick hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 23157843Smckusick int *name; 23257843Smckusick u_int namelen; 23357843Smckusick void *oldp; 23458466Sbostic size_t *oldlenp; 23557843Smckusick void *newp; 23658466Sbostic size_t newlen; 23758415Smckusick struct proc *p; 23857843Smckusick { 23957843Smckusick extern char machine[], cpu_model[]; 24057843Smckusick 24157843Smckusick /* all sysctl names at this level are terminal */ 24257843Smckusick if (namelen != 1) 24357843Smckusick return (ENOTDIR); /* overloaded */ 24457843Smckusick 24557843Smckusick switch (name[0]) { 24657843Smckusick case HW_MACHINE: 24757843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 24857843Smckusick case HW_MODEL: 24957843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 25057843Smckusick case HW_NCPU: 25157843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 252*59618Smckusick case HW_BYTEORDER: 253*59618Smckusick return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 25457843Smckusick case HW_PHYSMEM: 25557843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 25657843Smckusick case HW_USERMEM: 25757843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 25857843Smckusick ctob(physmem - cnt.v_wire_count))); 25957843Smckusick case HW_PAGESIZE: 26057843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 26157843Smckusick default: 26257843Smckusick return (EOPNOTSUPP); 26357843Smckusick } 26457843Smckusick /* NOTREACHED */ 26557843Smckusick } 26657843Smckusick 26759161Smckusick #ifdef DEBUG 26857843Smckusick /* 26959161Smckusick * Debugging related system variables. 27059161Smckusick */ 27159161Smckusick struct ctldebug debug0, debug1, debug2, debug3, debug4; 27259161Smckusick struct ctldebug debug5, debug6, debug7, debug8, debug9; 27359161Smckusick struct ctldebug debug10, debug11, debug12, debug13, debug14; 27459161Smckusick struct ctldebug debug15, debug16, debug17, debug18, debug19; 27559161Smckusick static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 27659161Smckusick &debug0, &debug1, &debug2, &debug3, &debug4, 27759161Smckusick &debug5, &debug6, &debug7, &debug8, &debug9, 27859161Smckusick &debug10, &debug11, &debug12, &debug13, &debug14, 27959161Smckusick &debug15, &debug16, &debug17, &debug18, &debug19, 28059161Smckusick }; 28159161Smckusick int 28259161Smckusick debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 28359161Smckusick int *name; 28459161Smckusick u_int namelen; 28559161Smckusick void *oldp; 28659161Smckusick size_t *oldlenp; 28759161Smckusick void *newp; 28859161Smckusick size_t newlen; 28959161Smckusick struct proc *p; 29059161Smckusick { 29159161Smckusick struct ctldebug *cdp; 29259161Smckusick 29359161Smckusick /* all sysctl names at this level are name and field */ 29459161Smckusick if (namelen != 2) 29559161Smckusick return (ENOTDIR); /* overloaded */ 29659161Smckusick cdp = debugvars[name[0]]; 29759161Smckusick if (cdp->debugname == 0) 29859161Smckusick return (EOPNOTSUPP); 29959161Smckusick switch (name[1]) { 30059161Smckusick case CTL_DEBUG_NAME: 30159161Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 30259161Smckusick case CTL_DEBUG_VALUE: 30359161Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 30459161Smckusick default: 30559161Smckusick return (EOPNOTSUPP); 30659161Smckusick } 30759161Smckusick /* NOTREACHED */ 30859161Smckusick } 30959161Smckusick #endif /* DEBUG */ 31059161Smckusick 31159161Smckusick /* 31257843Smckusick * Validate parameters and get old / set new parameters 31357843Smckusick * for an integer-valued sysctl function. 31457843Smckusick */ 31557843Smckusick sysctl_int(oldp, oldlenp, newp, newlen, valp) 31657843Smckusick void *oldp; 31758466Sbostic size_t *oldlenp; 31857843Smckusick void *newp; 31958466Sbostic size_t newlen; 32057843Smckusick int *valp; 32157843Smckusick { 32257843Smckusick int error = 0; 32357843Smckusick 32457843Smckusick if (oldp && *oldlenp < sizeof(int)) 32557843Smckusick return (ENOMEM); 32657843Smckusick if (newp && newlen != sizeof(int)) 32757843Smckusick return (EINVAL); 32857843Smckusick *oldlenp = sizeof(int); 32957843Smckusick if (oldp) 33057843Smckusick error = copyout(valp, oldp, sizeof(int)); 33157843Smckusick if (error == 0 && newp) 33257843Smckusick error = copyin(newp, valp, sizeof(int)); 33343444Smckusick return (error); 33439963Smarc } 33539963Smarc 33657843Smckusick /* 33757843Smckusick * As above, but read-only. 33857843Smckusick */ 33957843Smckusick sysctl_rdint(oldp, oldlenp, newp, val) 34057843Smckusick void *oldp; 34158466Sbostic size_t *oldlenp; 34257843Smckusick void *newp; 34357843Smckusick int val; 34457843Smckusick { 34557843Smckusick int error = 0; 34657843Smckusick 34757843Smckusick if (oldp && *oldlenp < sizeof(int)) 34857843Smckusick return (ENOMEM); 34957843Smckusick if (newp) 35057843Smckusick return (EPERM); 35157843Smckusick *oldlenp = sizeof(int); 35257843Smckusick if (oldp) 35357843Smckusick error = copyout((caddr_t)&val, oldp, sizeof(int)); 35457843Smckusick return (error); 35557843Smckusick } 35657843Smckusick 35757843Smckusick /* 35857843Smckusick * Validate parameters and get old / set new parameters 35957843Smckusick * for a string-valued sysctl function. 36057843Smckusick */ 36157843Smckusick sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 36257843Smckusick void *oldp; 36358466Sbostic size_t *oldlenp; 36457843Smckusick void *newp; 36558466Sbostic size_t newlen; 36657843Smckusick char *str; 36757843Smckusick int maxlen; 36857843Smckusick { 36957843Smckusick int len, error = 0; 37057843Smckusick 37157843Smckusick len = strlen(str) + 1; 37257843Smckusick if (oldp && *oldlenp < len) 37357843Smckusick return (ENOMEM); 37457843Smckusick if (newp && newlen >= maxlen) 37557843Smckusick return (EINVAL); 37658128Sralph if (oldp) { 37758128Sralph *oldlenp = len; 37857843Smckusick error = copyout(str, oldp, len); 37958128Sralph } 38057843Smckusick if (error == 0 && newp) { 38157843Smckusick error = copyin(newp, str, newlen); 38257843Smckusick str[newlen] = 0; 38357843Smckusick } 38457843Smckusick return (error); 38557843Smckusick } 38657843Smckusick 38757843Smckusick /* 38857843Smckusick * As above, but read-only. 38957843Smckusick */ 39057843Smckusick sysctl_rdstring(oldp, oldlenp, newp, str) 39157843Smckusick void *oldp; 39258466Sbostic size_t *oldlenp; 39357843Smckusick void *newp; 39457843Smckusick char *str; 39557843Smckusick { 39657843Smckusick int len, error = 0; 39757843Smckusick 39857843Smckusick len = strlen(str) + 1; 39957843Smckusick if (oldp && *oldlenp < len) 40057843Smckusick return (ENOMEM); 40157843Smckusick if (newp) 40257843Smckusick return (EPERM); 40357843Smckusick *oldlenp = len; 40457843Smckusick if (oldp) 40557843Smckusick error = copyout(str, oldp, len); 40657843Smckusick return (error); 40757843Smckusick } 40857843Smckusick 40957843Smckusick /* 41059312Smckusick * Validate parameters and get old / set new parameters 41159312Smckusick * for a structure oriented sysctl function. 41259312Smckusick */ 41359312Smckusick sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 41459312Smckusick void *oldp; 41559312Smckusick size_t *oldlenp; 41659312Smckusick void *newp; 41759312Smckusick size_t newlen; 41859312Smckusick void *sp; 41959312Smckusick int len; 42059312Smckusick { 42159312Smckusick int error = 0; 42259312Smckusick 42359312Smckusick if (oldp && *oldlenp < len) 42459312Smckusick return (ENOMEM); 42559312Smckusick if (newp && newlen > len) 42659312Smckusick return (EINVAL); 42759312Smckusick if (oldp) { 42859312Smckusick *oldlenp = len; 42959312Smckusick error = copyout(sp, oldp, len); 43059312Smckusick } 43159312Smckusick if (error == 0 && newp) 43259312Smckusick error = copyin(newp, sp, len); 43359312Smckusick return (error); 43459312Smckusick } 43559312Smckusick 43659312Smckusick /* 43757843Smckusick * Validate parameters and get old parameters 43857843Smckusick * for a structure oriented sysctl function. 43957843Smckusick */ 44057843Smckusick sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 44157843Smckusick void *oldp; 44258466Sbostic size_t *oldlenp; 44358466Sbostic void *newp, *sp; 44457843Smckusick int len; 44557843Smckusick { 44657843Smckusick int error = 0; 44757843Smckusick 44857843Smckusick if (oldp && *oldlenp < len) 44957843Smckusick return (ENOMEM); 45057843Smckusick if (newp) 45157843Smckusick return (EPERM); 45257843Smckusick *oldlenp = len; 45357843Smckusick if (oldp) 45457843Smckusick error = copyout(sp, oldp, len); 45557843Smckusick return (error); 45657843Smckusick } 45757843Smckusick 45857843Smckusick /* 45957843Smckusick * Get file structures. 46057843Smckusick */ 46157843Smckusick sysctl_file(where, sizep) 46257843Smckusick char *where; 46358466Sbostic size_t *sizep; 46457843Smckusick { 46557843Smckusick int buflen, error; 46657843Smckusick struct file *fp; 46757843Smckusick char *start = where; 46857843Smckusick 46957843Smckusick buflen = *sizep; 47057843Smckusick if (where == NULL) { 47157843Smckusick /* 47257843Smckusick * overestimate by 10 files 47357843Smckusick */ 47457843Smckusick *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 47557843Smckusick return (0); 47657843Smckusick } 47757843Smckusick 47857843Smckusick /* 47957843Smckusick * first copyout filehead 48057843Smckusick */ 48157843Smckusick if (buflen < sizeof(filehead)) { 48257843Smckusick *sizep = 0; 48357843Smckusick return (0); 48457843Smckusick } 48557843Smckusick if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) 48657843Smckusick return (error); 48757843Smckusick buflen += sizeof(filehead); 48857843Smckusick where += sizeof(filehead); 48957843Smckusick 49057843Smckusick /* 49157843Smckusick * followed by an array of file structures 49257843Smckusick */ 49357843Smckusick for (fp = filehead; fp != NULL; fp = fp->f_filef) { 49457843Smckusick if (buflen < sizeof(struct file)) { 49557843Smckusick *sizep = where - start; 49657843Smckusick return (ENOMEM); 49757843Smckusick } 49857843Smckusick if (error = copyout((caddr_t)fp, where, sizeof (struct file))) 49957843Smckusick return (error); 50057843Smckusick buflen -= sizeof(struct file); 50157843Smckusick where += sizeof(struct file); 50257843Smckusick } 50357843Smckusick *sizep = where - start; 50457843Smckusick return (0); 50557843Smckusick } 50657843Smckusick 50759312Smckusick /* 50859312Smckusick * try over estimating by 5 procs 50939963Smarc */ 51057843Smckusick #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 51139963Smarc 51257843Smckusick sysctl_doproc(name, namelen, where, sizep) 51357843Smckusick int *name; 51458466Sbostic u_int namelen; 51539963Smarc char *where; 51658466Sbostic size_t *sizep; 51739963Smarc { 51839963Smarc register struct proc *p; 51943419Smarc register struct kinfo_proc *dp = (struct kinfo_proc *)where; 52057843Smckusick register int needed = 0; 52157843Smckusick int buflen = where != NULL ? *sizep : 0; 52239963Smarc int doingzomb; 52340067Smarc struct eproc eproc; 52439963Smarc int error = 0; 52539963Smarc 52657843Smckusick if (namelen != 2) 52757843Smckusick return (EINVAL); 52854755Storek p = (struct proc *)allproc; 52939963Smarc doingzomb = 0; 53039963Smarc again: 53139963Smarc for (; p != NULL; p = p->p_nxt) { 53253819Smckusick /* 53353819Smckusick * Skip embryonic processes. 53453819Smckusick */ 53553819Smckusick if (p->p_stat == SIDL) 53653819Smckusick continue; 53759312Smckusick /* 53839963Smarc * TODO - make more efficient (see notes below). 53959312Smckusick * do by session. 54039963Smarc */ 54157843Smckusick switch (name[0]) { 54239963Smarc 54357843Smckusick case KERN_PROC_PID: 54439963Smarc /* could do this with just a lookup */ 54557843Smckusick if (p->p_pid != (pid_t)name[1]) 54639963Smarc continue; 54739963Smarc break; 54839963Smarc 54957843Smckusick case KERN_PROC_PGRP: 55039963Smarc /* could do this by traversing pgrp */ 55157843Smckusick if (p->p_pgrp->pg_id != (pid_t)name[1]) 55239963Smarc continue; 55339963Smarc break; 55439963Smarc 55557843Smckusick case KERN_PROC_TTY: 55659312Smckusick if ((p->p_flag&SCTTY) == 0 || 55739963Smarc p->p_session->s_ttyp == NULL || 55857843Smckusick p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 55939963Smarc continue; 56039963Smarc break; 56139963Smarc 56257843Smckusick case KERN_PROC_UID: 56357843Smckusick if (p->p_ucred->cr_uid != (uid_t)name[1]) 56439963Smarc continue; 56539963Smarc break; 56639963Smarc 56757843Smckusick case KERN_PROC_RUID: 56857843Smckusick if (p->p_cred->p_ruid != (uid_t)name[1]) 56939963Smarc continue; 57039963Smarc break; 57139963Smarc } 57257843Smckusick if (buflen >= sizeof(struct kinfo_proc)) { 57348407Skarels fill_eproc(p, &eproc); 57459312Smckusick if (error = copyout((caddr_t)p, &dp->kp_proc, 57557843Smckusick sizeof(struct proc))) 57639963Smarc return (error); 57759312Smckusick if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 57857843Smckusick sizeof(eproc))) 57939963Smarc return (error); 58043419Smarc dp++; 58157843Smckusick buflen -= sizeof(struct kinfo_proc); 58239963Smarc } 58357843Smckusick needed += sizeof(struct kinfo_proc); 58439963Smarc } 58539963Smarc if (doingzomb == 0) { 58639963Smarc p = zombproc; 58739963Smarc doingzomb++; 58839963Smarc goto again; 58939963Smarc } 59057843Smckusick if (where != NULL) { 59157843Smckusick *sizep = (caddr_t)dp - where; 59257843Smckusick if (needed > *sizep) 59357843Smckusick return (ENOMEM); 59457843Smckusick } else { 59557843Smckusick needed += KERN_PROCSLOP; 59657843Smckusick *sizep = needed; 59757843Smckusick } 59839963Smarc return (0); 59939963Smarc } 60048407Skarels 60148407Skarels /* 60248407Skarels * Fill in an eproc structure for the specified process. 60348407Skarels */ 60448407Skarels void 60548407Skarels fill_eproc(p, ep) 60648407Skarels register struct proc *p; 60748407Skarels register struct eproc *ep; 60848407Skarels { 60948407Skarels register struct tty *tp; 61048407Skarels 61148407Skarels ep->e_paddr = p; 61248407Skarels ep->e_sess = p->p_pgrp->pg_session; 61348407Skarels ep->e_pcred = *p->p_cred; 61448407Skarels ep->e_ucred = *p->p_ucred; 61552405Storek if (p->p_stat == SIDL || p->p_stat == SZOMB) { 61652405Storek ep->e_vm.vm_rssize = 0; 61752405Storek ep->e_vm.vm_tsize = 0; 61852405Storek ep->e_vm.vm_dsize = 0; 61952405Storek ep->e_vm.vm_ssize = 0; 62052405Storek #ifndef sparc 62152405Storek /* ep->e_vm.vm_pmap = XXX; */ 62252405Storek #endif 62352405Storek } else { 62452405Storek register struct vmspace *vm = p->p_vmspace; 62552405Storek 62652405Storek ep->e_vm.vm_rssize = vm->vm_rssize; 62752405Storek ep->e_vm.vm_tsize = vm->vm_tsize; 62852405Storek ep->e_vm.vm_dsize = vm->vm_dsize; 62952405Storek ep->e_vm.vm_ssize = vm->vm_ssize; 63052405Storek #ifndef sparc 63152405Storek ep->e_vm.vm_pmap = vm->vm_pmap; 63252405Storek #endif 63352405Storek } 63449141Skarels if (p->p_pptr) 63549141Skarels ep->e_ppid = p->p_pptr->p_pid; 63649141Skarels else 63749141Skarels ep->e_ppid = 0; 63848407Skarels ep->e_pgid = p->p_pgrp->pg_id; 63948407Skarels ep->e_jobc = p->p_pgrp->pg_jobc; 64059312Smckusick if ((p->p_flag&SCTTY) && 64148407Skarels (tp = ep->e_sess->s_ttyp)) { 64248407Skarels ep->e_tdev = tp->t_dev; 64350022Skarels ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 64448407Skarels ep->e_tsess = tp->t_session; 64548407Skarels } else 64648407Skarels ep->e_tdev = NODEV; 64748407Skarels ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 64848407Skarels if (SESS_LEADER(p)) 64948407Skarels ep->e_flag |= EPROC_SLEADER; 65048407Skarels if (p->p_wmesg) 65148407Skarels strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 65248407Skarels ep->e_xsize = ep->e_xrssize = 0; 65348407Skarels ep->e_xccount = ep->e_xswrss = 0; 65448407Skarels } 65550149Smarc 65657843Smckusick #ifdef COMPAT_43 65757843Smckusick #include <sys/socket.h> 65857906Smckusick #define KINFO_PROC (0<<8) 65957906Smckusick #define KINFO_RT (1<<8) 66057906Smckusick #define KINFO_VNODE (2<<8) 66157906Smckusick #define KINFO_FILE (3<<8) 66257906Smckusick #define KINFO_METER (4<<8) 66357906Smckusick #define KINFO_LOADAVG (5<<8) 66457906Smckusick #define KINFO_CLOCKRATE (6<<8) 66557843Smckusick 66657843Smckusick struct getkerninfo_args { 66757843Smckusick int op; 66857843Smckusick char *where; 66957843Smckusick int *size; 67057843Smckusick int arg; 67157843Smckusick }; 67257843Smckusick 67358943Smckusick ogetkerninfo(p, uap, retval) 67457843Smckusick struct proc *p; 67557843Smckusick register struct getkerninfo_args *uap; 67657843Smckusick int *retval; 67750149Smarc { 67857843Smckusick int error, name[5]; 67957843Smckusick u_int size; 68050149Smarc 68158461Smckusick if (uap->size && 68258466Sbostic (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 68357843Smckusick return (error); 68450149Smarc 68557906Smckusick switch (uap->op & 0xff00) { 68650149Smarc 68757843Smckusick case KINFO_RT: 68857843Smckusick name[0] = PF_ROUTE; 68957843Smckusick name[1] = 0; 69057843Smckusick name[2] = (uap->op & 0xff0000) >> 16; 69157843Smckusick name[3] = uap->op & 0xff; 69257843Smckusick name[4] = uap->arg; 69358415Smckusick error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 69457843Smckusick break; 69557843Smckusick 69657843Smckusick case KINFO_VNODE: 69757843Smckusick name[0] = KERN_VNODE; 69858415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 69957843Smckusick break; 70057843Smckusick 70157843Smckusick case KINFO_PROC: 70257843Smckusick name[0] = KERN_PROC; 70357843Smckusick name[1] = uap->op & 0xff; 70457843Smckusick name[2] = uap->arg; 70558415Smckusick error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 70657843Smckusick break; 70757843Smckusick 70857843Smckusick case KINFO_FILE: 70957843Smckusick name[0] = KERN_FILE; 71058415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 71157843Smckusick break; 71257843Smckusick 71357843Smckusick case KINFO_METER: 71457843Smckusick name[0] = VM_METER; 71558415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 71657843Smckusick break; 71757843Smckusick 71857843Smckusick case KINFO_LOADAVG: 71957843Smckusick name[0] = VM_LOADAVG; 72058415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 72157843Smckusick break; 72257843Smckusick 72357843Smckusick case KINFO_CLOCKRATE: 72457843Smckusick name[0] = KERN_CLOCKRATE; 72558415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 72657843Smckusick break; 72757843Smckusick 72857843Smckusick default: 72958415Smckusick return (EOPNOTSUPP); 73050149Smarc } 73157843Smckusick if (error) 73257843Smckusick return (error); 73357843Smckusick *retval = size; 73458461Smckusick if (uap->size) 73558461Smckusick error = copyout((caddr_t)&size, (caddr_t)uap->size, 73658461Smckusick sizeof(size)); 73758461Smckusick return (error); 73850149Smarc } 73957843Smckusick #endif /* COMPAT_43 */ 740