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*59314Smckusick * @(#)kern_sysctl.c 7.35 (Berkeley) 04/27/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> 22*59314Smckusick #include <sys/vnode.h> 2357843Smckusick #include <sys/sysctl.h> 2457843Smckusick #include <sys/unistd.h> 2557843Smckusick #include <sys/buf.h> 2656517Sbostic #include <sys/ioctl.h> 2756517Sbostic #include <sys/tty.h> 2839963Smarc 2956517Sbostic #include <vm/vm.h> 3048407Skarels 3156517Sbostic #include <sys/kinfo_proc.h> 3248407Skarels 3357843Smckusick sysctlfn kern_sysctl; 3457843Smckusick sysctlfn hw_sysctl; 3559161Smckusick #ifdef DEBUG 3659161Smckusick sysctlfn debug_sysctl; 3759161Smckusick #endif 3857843Smckusick extern sysctlfn vm_sysctl; 3957843Smckusick extern sysctlfn fs_sysctl; 4057843Smckusick extern sysctlfn net_sysctl; 4157843Smckusick extern sysctlfn cpu_sysctl; 4240068Smarc 4357843Smckusick /* 4457843Smckusick * Locking and stats 4557843Smckusick */ 4657843Smckusick static struct sysctl_lock { 4757843Smckusick int sl_lock; 4857843Smckusick int sl_want; 4957843Smckusick int sl_locked; 5057843Smckusick } memlock; 5157843Smckusick 5257843Smckusick struct sysctl_args { 5357843Smckusick int *name; 5457843Smckusick u_int namelen; 5557843Smckusick void *old; 5658466Sbostic size_t *oldlenp; 5757843Smckusick void *new; 5858466Sbostic size_t newlen; 5954923Storek }; 6057843Smckusick 6157843Smckusick sysctl(p, uap, retval) 6243444Smckusick struct proc *p; 6357843Smckusick register struct sysctl_args *uap; 6443444Smckusick int *retval; 6543444Smckusick { 6657843Smckusick int error, dolock = 1; 6757843Smckusick u_int savelen, oldlen = 0; 6857843Smckusick sysctlfn *fn; 6957843Smckusick int name[CTL_MAXNAME]; 7039963Smarc 7157843Smckusick if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 7257843Smckusick return (error); 7357843Smckusick /* 7457843Smckusick * all top-level sysctl names are non-terminal 7557843Smckusick */ 7657843Smckusick if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 7757843Smckusick return (EINVAL); 7857843Smckusick if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) 7957843Smckusick return (error); 8039963Smarc 8157843Smckusick switch (name[0]) { 8257843Smckusick case CTL_KERN: 8357843Smckusick fn = kern_sysctl; 8457843Smckusick if (name[2] != KERN_VNODE) /* XXX */ 8557843Smckusick dolock = 0; 8639963Smarc break; 8757843Smckusick case CTL_HW: 8857843Smckusick fn = hw_sysctl; 8940068Smarc break; 9057843Smckusick case CTL_VM: 9157843Smckusick fn = vm_sysctl; 9241181Smarc break; 9357843Smckusick case CTL_NET: 9457843Smckusick fn = net_sysctl; 9550149Smarc break; 9657843Smckusick #ifdef notyet 9757843Smckusick case CTL_FS: 9857843Smckusick fn = fs_sysctl; 9950909Smckusick break; 10057843Smckusick case CTL_MACHDEP: 10157843Smckusick fn = cpu_sysctl; 10252669Smckusick break; 10357843Smckusick #endif 10459161Smckusick #ifdef DEBUG 10559161Smckusick case CTL_DEBUG: 10659161Smckusick fn = debug_sysctl; 10759161Smckusick break; 10859161Smckusick #endif 10939963Smarc default: 11057843Smckusick return (EOPNOTSUPP); 11139963Smarc } 11257843Smckusick 11357843Smckusick if (uap->oldlenp && 11457843Smckusick (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 11557843Smckusick return (error); 11657843Smckusick if (uap->old != NULL) { 11757843Smckusick if (!useracc(uap->old, oldlen, B_WRITE)) 11857843Smckusick return (EFAULT); 11957843Smckusick while (memlock.sl_lock) { 12057843Smckusick memlock.sl_want = 1; 12157843Smckusick sleep((caddr_t)&memlock, PRIBIO+1); 12257843Smckusick memlock.sl_locked++; 12357843Smckusick } 12457843Smckusick memlock.sl_lock = 1; 12557843Smckusick if (dolock) 12657843Smckusick vslock(uap->old, oldlen); 12757843Smckusick savelen = oldlen; 12840813Smarc } 12957843Smckusick error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 13058415Smckusick uap->new, uap->newlen, p); 13157843Smckusick if (uap->old != NULL) { 13257843Smckusick if (dolock) 13357843Smckusick vsunlock(uap->old, savelen, B_WRITE); 13457843Smckusick memlock.sl_lock = 0; 13557843Smckusick if (memlock.sl_want) { 13657843Smckusick memlock.sl_want = 0; 13757843Smckusick wakeup((caddr_t)&memlock); 13857843Smckusick } 13940206Smarc } 14057843Smckusick if (error) 14157843Smckusick return (error); 14257843Smckusick if (uap->oldlenp) 14357843Smckusick error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 14457843Smckusick *retval = oldlen; 14557843Smckusick return (0); 14657843Smckusick } 14740206Smarc 14857843Smckusick /* 14957843Smckusick * Attributes stored in the kernel. 15057843Smckusick */ 15157843Smckusick char hostname[MAXHOSTNAMELEN]; 15257843Smckusick int hostnamelen; 15357843Smckusick long hostid; 15458415Smckusick int securelevel; 15557843Smckusick 15658415Smckusick /* 15758415Smckusick * kernel related system variables. 15858415Smckusick */ 15958415Smckusick kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 16057843Smckusick int *name; 16157843Smckusick u_int namelen; 16257843Smckusick void *oldp; 16358466Sbostic size_t *oldlenp; 16457843Smckusick void *newp; 16558466Sbostic size_t newlen; 16658415Smckusick struct proc *p; 16757843Smckusick { 16858415Smckusick int error, level; 16957843Smckusick extern char ostype[], osrelease[], version[]; 17057843Smckusick 17157843Smckusick /* all sysctl names at this level are terminal */ 17259312Smckusick if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) 17357843Smckusick return (ENOTDIR); /* overloaded */ 17457843Smckusick 17557843Smckusick switch (name[0]) { 17657843Smckusick case KERN_OSTYPE: 17757843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 17857843Smckusick case KERN_OSRELEASE: 17957843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 18057843Smckusick case KERN_OSREV: 18157843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 18257843Smckusick case KERN_VERSION: 18357843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, version)); 18457843Smckusick case KERN_POSIX1: 18557843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 18657843Smckusick case KERN_MAXPROC: 18757843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 18857843Smckusick case KERN_MAXFILES: 18957843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 190*59314Smckusick case KERN_MAXVNODES: 191*59314Smckusick return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 19257843Smckusick case KERN_ARGMAX: 19357843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 19457843Smckusick case KERN_HOSTNAME: 19559312Smckusick error = sysctl_string(oldp, oldlenp, newp, newlen, 19657843Smckusick hostname, sizeof(hostname)); 19757843Smckusick if (!error) 19857843Smckusick hostnamelen = newlen; 19957843Smckusick return (error); 20057843Smckusick case KERN_HOSTID: 20157843Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, &hostid)); 20258415Smckusick case KERN_SECURELVL: 20358415Smckusick level = securelevel; 20458415Smckusick if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 20558415Smckusick newp == NULL) 20658415Smckusick return (error); 20758415Smckusick if (level < securelevel && p->p_pid != 1) 20858415Smckusick return (EPERM); 20958415Smckusick securelevel = level; 21058415Smckusick return (0); 21157843Smckusick case KERN_CLOCKRATE: 21257843Smckusick return (sysctl_clockrate(oldp, oldlenp)); 21357843Smckusick case KERN_FILE: 21457843Smckusick return (sysctl_file(oldp, oldlenp)); 21557843Smckusick case KERN_VNODE: 21657843Smckusick return (sysctl_vnode(oldp, oldlenp)); 21757843Smckusick case KERN_PROC: 21857843Smckusick return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 21959312Smckusick #ifdef GPROF 22059312Smckusick case KERN_PROF: 22159312Smckusick return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 22259312Smckusick newp, newlen)); 22359312Smckusick #endif 22457843Smckusick default: 22557843Smckusick return (EOPNOTSUPP); 22652405Storek } 22757843Smckusick /* NOTREACHED */ 22857843Smckusick } 22957843Smckusick 23058415Smckusick /* 23158415Smckusick * hardware related system variables. 23258415Smckusick */ 23358415Smckusick hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 23457843Smckusick int *name; 23557843Smckusick u_int namelen; 23657843Smckusick void *oldp; 23758466Sbostic size_t *oldlenp; 23857843Smckusick void *newp; 23958466Sbostic size_t newlen; 24058415Smckusick struct proc *p; 24157843Smckusick { 24257843Smckusick extern char machine[], cpu_model[]; 24357843Smckusick 24457843Smckusick /* all sysctl names at this level are terminal */ 24557843Smckusick if (namelen != 1) 24657843Smckusick return (ENOTDIR); /* overloaded */ 24757843Smckusick 24857843Smckusick switch (name[0]) { 24957843Smckusick case HW_MACHINE: 25057843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 25157843Smckusick case HW_MODEL: 25257843Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 25357843Smckusick case HW_NCPU: 25457843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 25557843Smckusick case HW_CPUSPEED: 25657843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed)); 25757843Smckusick case HW_PHYSMEM: 25857843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 25957843Smckusick case HW_USERMEM: 26057843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, 26157843Smckusick ctob(physmem - cnt.v_wire_count))); 26257843Smckusick case HW_PAGESIZE: 26357843Smckusick return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 26457843Smckusick default: 26557843Smckusick return (EOPNOTSUPP); 26657843Smckusick } 26757843Smckusick /* NOTREACHED */ 26857843Smckusick } 26957843Smckusick 27059161Smckusick #ifdef DEBUG 27157843Smckusick /* 27259161Smckusick * Debugging related system variables. 27359161Smckusick */ 27459161Smckusick struct ctldebug debug0, debug1, debug2, debug3, debug4; 27559161Smckusick struct ctldebug debug5, debug6, debug7, debug8, debug9; 27659161Smckusick struct ctldebug debug10, debug11, debug12, debug13, debug14; 27759161Smckusick struct ctldebug debug15, debug16, debug17, debug18, debug19; 27859161Smckusick static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 27959161Smckusick &debug0, &debug1, &debug2, &debug3, &debug4, 28059161Smckusick &debug5, &debug6, &debug7, &debug8, &debug9, 28159161Smckusick &debug10, &debug11, &debug12, &debug13, &debug14, 28259161Smckusick &debug15, &debug16, &debug17, &debug18, &debug19, 28359161Smckusick }; 28459161Smckusick int 28559161Smckusick debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 28659161Smckusick int *name; 28759161Smckusick u_int namelen; 28859161Smckusick void *oldp; 28959161Smckusick size_t *oldlenp; 29059161Smckusick void *newp; 29159161Smckusick size_t newlen; 29259161Smckusick struct proc *p; 29359161Smckusick { 29459161Smckusick struct ctldebug *cdp; 29559161Smckusick 29659161Smckusick /* all sysctl names at this level are name and field */ 29759161Smckusick if (namelen != 2) 29859161Smckusick return (ENOTDIR); /* overloaded */ 29959161Smckusick cdp = debugvars[name[0]]; 30059161Smckusick if (cdp->debugname == 0) 30159161Smckusick return (EOPNOTSUPP); 30259161Smckusick switch (name[1]) { 30359161Smckusick case CTL_DEBUG_NAME: 30459161Smckusick return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 30559161Smckusick case CTL_DEBUG_VALUE: 30659161Smckusick return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 30759161Smckusick default: 30859161Smckusick return (EOPNOTSUPP); 30959161Smckusick } 31059161Smckusick /* NOTREACHED */ 31159161Smckusick } 31259161Smckusick #endif /* DEBUG */ 31359161Smckusick 31459161Smckusick /* 31557843Smckusick * Validate parameters and get old / set new parameters 31657843Smckusick * for an integer-valued sysctl function. 31757843Smckusick */ 31857843Smckusick sysctl_int(oldp, oldlenp, newp, newlen, valp) 31957843Smckusick void *oldp; 32058466Sbostic size_t *oldlenp; 32157843Smckusick void *newp; 32258466Sbostic size_t newlen; 32357843Smckusick int *valp; 32457843Smckusick { 32557843Smckusick int error = 0; 32657843Smckusick 32757843Smckusick if (oldp && *oldlenp < sizeof(int)) 32857843Smckusick return (ENOMEM); 32957843Smckusick if (newp && newlen != sizeof(int)) 33057843Smckusick return (EINVAL); 33157843Smckusick *oldlenp = sizeof(int); 33257843Smckusick if (oldp) 33357843Smckusick error = copyout(valp, oldp, sizeof(int)); 33457843Smckusick if (error == 0 && newp) 33557843Smckusick error = copyin(newp, valp, sizeof(int)); 33643444Smckusick return (error); 33739963Smarc } 33839963Smarc 33957843Smckusick /* 34057843Smckusick * As above, but read-only. 34157843Smckusick */ 34257843Smckusick sysctl_rdint(oldp, oldlenp, newp, val) 34357843Smckusick void *oldp; 34458466Sbostic size_t *oldlenp; 34557843Smckusick void *newp; 34657843Smckusick int val; 34757843Smckusick { 34857843Smckusick int error = 0; 34957843Smckusick 35057843Smckusick if (oldp && *oldlenp < sizeof(int)) 35157843Smckusick return (ENOMEM); 35257843Smckusick if (newp) 35357843Smckusick return (EPERM); 35457843Smckusick *oldlenp = sizeof(int); 35557843Smckusick if (oldp) 35657843Smckusick error = copyout((caddr_t)&val, oldp, sizeof(int)); 35757843Smckusick return (error); 35857843Smckusick } 35957843Smckusick 36057843Smckusick /* 36157843Smckusick * Validate parameters and get old / set new parameters 36257843Smckusick * for a string-valued sysctl function. 36357843Smckusick */ 36457843Smckusick sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 36557843Smckusick void *oldp; 36658466Sbostic size_t *oldlenp; 36757843Smckusick void *newp; 36858466Sbostic size_t newlen; 36957843Smckusick char *str; 37057843Smckusick int maxlen; 37157843Smckusick { 37257843Smckusick int len, error = 0; 37357843Smckusick 37457843Smckusick len = strlen(str) + 1; 37557843Smckusick if (oldp && *oldlenp < len) 37657843Smckusick return (ENOMEM); 37757843Smckusick if (newp && newlen >= maxlen) 37857843Smckusick return (EINVAL); 37958128Sralph if (oldp) { 38058128Sralph *oldlenp = len; 38157843Smckusick error = copyout(str, oldp, len); 38258128Sralph } 38357843Smckusick if (error == 0 && newp) { 38457843Smckusick error = copyin(newp, str, newlen); 38557843Smckusick str[newlen] = 0; 38657843Smckusick } 38757843Smckusick return (error); 38857843Smckusick } 38957843Smckusick 39057843Smckusick /* 39157843Smckusick * As above, but read-only. 39257843Smckusick */ 39357843Smckusick sysctl_rdstring(oldp, oldlenp, newp, str) 39457843Smckusick void *oldp; 39558466Sbostic size_t *oldlenp; 39657843Smckusick void *newp; 39757843Smckusick char *str; 39857843Smckusick { 39957843Smckusick int len, error = 0; 40057843Smckusick 40157843Smckusick len = strlen(str) + 1; 40257843Smckusick if (oldp && *oldlenp < len) 40357843Smckusick return (ENOMEM); 40457843Smckusick if (newp) 40557843Smckusick return (EPERM); 40657843Smckusick *oldlenp = len; 40757843Smckusick if (oldp) 40857843Smckusick error = copyout(str, oldp, len); 40957843Smckusick return (error); 41057843Smckusick } 41157843Smckusick 41257843Smckusick /* 41359312Smckusick * Validate parameters and get old / set new parameters 41459312Smckusick * for a structure oriented sysctl function. 41559312Smckusick */ 41659312Smckusick sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 41759312Smckusick void *oldp; 41859312Smckusick size_t *oldlenp; 41959312Smckusick void *newp; 42059312Smckusick size_t newlen; 42159312Smckusick void *sp; 42259312Smckusick int len; 42359312Smckusick { 42459312Smckusick int error = 0; 42559312Smckusick 42659312Smckusick if (oldp && *oldlenp < len) 42759312Smckusick return (ENOMEM); 42859312Smckusick if (newp && newlen > len) 42959312Smckusick return (EINVAL); 43059312Smckusick if (oldp) { 43159312Smckusick *oldlenp = len; 43259312Smckusick error = copyout(sp, oldp, len); 43359312Smckusick } 43459312Smckusick if (error == 0 && newp) 43559312Smckusick error = copyin(newp, sp, len); 43659312Smckusick return (error); 43759312Smckusick } 43859312Smckusick 43959312Smckusick /* 44057843Smckusick * Validate parameters and get old parameters 44157843Smckusick * for a structure oriented sysctl function. 44257843Smckusick */ 44357843Smckusick sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 44457843Smckusick void *oldp; 44558466Sbostic size_t *oldlenp; 44658466Sbostic void *newp, *sp; 44757843Smckusick int len; 44857843Smckusick { 44957843Smckusick int error = 0; 45057843Smckusick 45157843Smckusick if (oldp && *oldlenp < len) 45257843Smckusick return (ENOMEM); 45357843Smckusick if (newp) 45457843Smckusick return (EPERM); 45557843Smckusick *oldlenp = len; 45657843Smckusick if (oldp) 45757843Smckusick error = copyout(sp, oldp, len); 45857843Smckusick return (error); 45957843Smckusick } 46057843Smckusick 46157843Smckusick /* 46257843Smckusick * Get file structures. 46357843Smckusick */ 46457843Smckusick sysctl_file(where, sizep) 46557843Smckusick char *where; 46658466Sbostic size_t *sizep; 46757843Smckusick { 46857843Smckusick int buflen, error; 46957843Smckusick struct file *fp; 47057843Smckusick char *start = where; 47157843Smckusick 47257843Smckusick buflen = *sizep; 47357843Smckusick if (where == NULL) { 47457843Smckusick /* 47557843Smckusick * overestimate by 10 files 47657843Smckusick */ 47757843Smckusick *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 47857843Smckusick return (0); 47957843Smckusick } 48057843Smckusick 48157843Smckusick /* 48257843Smckusick * first copyout filehead 48357843Smckusick */ 48457843Smckusick if (buflen < sizeof(filehead)) { 48557843Smckusick *sizep = 0; 48657843Smckusick return (0); 48757843Smckusick } 48857843Smckusick if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) 48957843Smckusick return (error); 49057843Smckusick buflen += sizeof(filehead); 49157843Smckusick where += sizeof(filehead); 49257843Smckusick 49357843Smckusick /* 49457843Smckusick * followed by an array of file structures 49557843Smckusick */ 49657843Smckusick for (fp = filehead; fp != NULL; fp = fp->f_filef) { 49757843Smckusick if (buflen < sizeof(struct file)) { 49857843Smckusick *sizep = where - start; 49957843Smckusick return (ENOMEM); 50057843Smckusick } 50157843Smckusick if (error = copyout((caddr_t)fp, where, sizeof (struct file))) 50257843Smckusick return (error); 50357843Smckusick buflen -= sizeof(struct file); 50457843Smckusick where += sizeof(struct file); 50557843Smckusick } 50657843Smckusick *sizep = where - start; 50757843Smckusick return (0); 50857843Smckusick } 50957843Smckusick 51059312Smckusick /* 51159312Smckusick * try over estimating by 5 procs 51239963Smarc */ 51357843Smckusick #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 51439963Smarc 51557843Smckusick sysctl_doproc(name, namelen, where, sizep) 51657843Smckusick int *name; 51758466Sbostic u_int namelen; 51839963Smarc char *where; 51958466Sbostic size_t *sizep; 52039963Smarc { 52139963Smarc register struct proc *p; 52243419Smarc register struct kinfo_proc *dp = (struct kinfo_proc *)where; 52357843Smckusick register int needed = 0; 52457843Smckusick int buflen = where != NULL ? *sizep : 0; 52539963Smarc int doingzomb; 52640067Smarc struct eproc eproc; 52739963Smarc int error = 0; 52839963Smarc 52957843Smckusick if (namelen != 2) 53057843Smckusick return (EINVAL); 53154755Storek p = (struct proc *)allproc; 53239963Smarc doingzomb = 0; 53339963Smarc again: 53439963Smarc for (; p != NULL; p = p->p_nxt) { 53553819Smckusick /* 53653819Smckusick * Skip embryonic processes. 53753819Smckusick */ 53853819Smckusick if (p->p_stat == SIDL) 53953819Smckusick continue; 54059312Smckusick /* 54139963Smarc * TODO - make more efficient (see notes below). 54259312Smckusick * do by session. 54339963Smarc */ 54457843Smckusick switch (name[0]) { 54539963Smarc 54657843Smckusick case KERN_PROC_PID: 54739963Smarc /* could do this with just a lookup */ 54857843Smckusick if (p->p_pid != (pid_t)name[1]) 54939963Smarc continue; 55039963Smarc break; 55139963Smarc 55257843Smckusick case KERN_PROC_PGRP: 55339963Smarc /* could do this by traversing pgrp */ 55457843Smckusick if (p->p_pgrp->pg_id != (pid_t)name[1]) 55539963Smarc continue; 55639963Smarc break; 55739963Smarc 55857843Smckusick case KERN_PROC_TTY: 55959312Smckusick if ((p->p_flag&SCTTY) == 0 || 56039963Smarc p->p_session->s_ttyp == NULL || 56157843Smckusick p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 56239963Smarc continue; 56339963Smarc break; 56439963Smarc 56557843Smckusick case KERN_PROC_UID: 56657843Smckusick if (p->p_ucred->cr_uid != (uid_t)name[1]) 56739963Smarc continue; 56839963Smarc break; 56939963Smarc 57057843Smckusick case KERN_PROC_RUID: 57157843Smckusick if (p->p_cred->p_ruid != (uid_t)name[1]) 57239963Smarc continue; 57339963Smarc break; 57439963Smarc } 57557843Smckusick if (buflen >= sizeof(struct kinfo_proc)) { 57648407Skarels fill_eproc(p, &eproc); 57759312Smckusick if (error = copyout((caddr_t)p, &dp->kp_proc, 57857843Smckusick sizeof(struct proc))) 57939963Smarc return (error); 58059312Smckusick if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 58157843Smckusick sizeof(eproc))) 58239963Smarc return (error); 58343419Smarc dp++; 58457843Smckusick buflen -= sizeof(struct kinfo_proc); 58539963Smarc } 58657843Smckusick needed += sizeof(struct kinfo_proc); 58739963Smarc } 58839963Smarc if (doingzomb == 0) { 58939963Smarc p = zombproc; 59039963Smarc doingzomb++; 59139963Smarc goto again; 59239963Smarc } 59357843Smckusick if (where != NULL) { 59457843Smckusick *sizep = (caddr_t)dp - where; 59557843Smckusick if (needed > *sizep) 59657843Smckusick return (ENOMEM); 59757843Smckusick } else { 59857843Smckusick needed += KERN_PROCSLOP; 59957843Smckusick *sizep = needed; 60057843Smckusick } 60139963Smarc return (0); 60239963Smarc } 60348407Skarels 60448407Skarels /* 60548407Skarels * Fill in an eproc structure for the specified process. 60648407Skarels */ 60748407Skarels void 60848407Skarels fill_eproc(p, ep) 60948407Skarels register struct proc *p; 61048407Skarels register struct eproc *ep; 61148407Skarels { 61248407Skarels register struct tty *tp; 61348407Skarels 61448407Skarels ep->e_paddr = p; 61548407Skarels ep->e_sess = p->p_pgrp->pg_session; 61648407Skarels ep->e_pcred = *p->p_cred; 61748407Skarels ep->e_ucred = *p->p_ucred; 61852405Storek if (p->p_stat == SIDL || p->p_stat == SZOMB) { 61952405Storek ep->e_vm.vm_rssize = 0; 62052405Storek ep->e_vm.vm_tsize = 0; 62152405Storek ep->e_vm.vm_dsize = 0; 62252405Storek ep->e_vm.vm_ssize = 0; 62352405Storek #ifndef sparc 62452405Storek /* ep->e_vm.vm_pmap = XXX; */ 62552405Storek #endif 62652405Storek } else { 62752405Storek register struct vmspace *vm = p->p_vmspace; 62852405Storek 62952405Storek ep->e_vm.vm_rssize = vm->vm_rssize; 63052405Storek ep->e_vm.vm_tsize = vm->vm_tsize; 63152405Storek ep->e_vm.vm_dsize = vm->vm_dsize; 63252405Storek ep->e_vm.vm_ssize = vm->vm_ssize; 63352405Storek #ifndef sparc 63452405Storek ep->e_vm.vm_pmap = vm->vm_pmap; 63552405Storek #endif 63652405Storek } 63749141Skarels if (p->p_pptr) 63849141Skarels ep->e_ppid = p->p_pptr->p_pid; 63949141Skarels else 64049141Skarels ep->e_ppid = 0; 64148407Skarels ep->e_pgid = p->p_pgrp->pg_id; 64248407Skarels ep->e_jobc = p->p_pgrp->pg_jobc; 64359312Smckusick if ((p->p_flag&SCTTY) && 64448407Skarels (tp = ep->e_sess->s_ttyp)) { 64548407Skarels ep->e_tdev = tp->t_dev; 64650022Skarels ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 64748407Skarels ep->e_tsess = tp->t_session; 64848407Skarels } else 64948407Skarels ep->e_tdev = NODEV; 65048407Skarels ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 65148407Skarels if (SESS_LEADER(p)) 65248407Skarels ep->e_flag |= EPROC_SLEADER; 65348407Skarels if (p->p_wmesg) 65448407Skarels strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 65548407Skarels ep->e_xsize = ep->e_xrssize = 0; 65648407Skarels ep->e_xccount = ep->e_xswrss = 0; 65748407Skarels } 65850149Smarc 65957843Smckusick #ifdef COMPAT_43 66057843Smckusick #include <sys/socket.h> 66157906Smckusick #define KINFO_PROC (0<<8) 66257906Smckusick #define KINFO_RT (1<<8) 66357906Smckusick #define KINFO_VNODE (2<<8) 66457906Smckusick #define KINFO_FILE (3<<8) 66557906Smckusick #define KINFO_METER (4<<8) 66657906Smckusick #define KINFO_LOADAVG (5<<8) 66757906Smckusick #define KINFO_CLOCKRATE (6<<8) 66857843Smckusick 66957843Smckusick struct getkerninfo_args { 67057843Smckusick int op; 67157843Smckusick char *where; 67257843Smckusick int *size; 67357843Smckusick int arg; 67457843Smckusick }; 67557843Smckusick 67658943Smckusick ogetkerninfo(p, uap, retval) 67757843Smckusick struct proc *p; 67857843Smckusick register struct getkerninfo_args *uap; 67957843Smckusick int *retval; 68050149Smarc { 68157843Smckusick int error, name[5]; 68257843Smckusick u_int size; 68350149Smarc 68458461Smckusick if (uap->size && 68558466Sbostic (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 68657843Smckusick return (error); 68750149Smarc 68857906Smckusick switch (uap->op & 0xff00) { 68950149Smarc 69057843Smckusick case KINFO_RT: 69157843Smckusick name[0] = PF_ROUTE; 69257843Smckusick name[1] = 0; 69357843Smckusick name[2] = (uap->op & 0xff0000) >> 16; 69457843Smckusick name[3] = uap->op & 0xff; 69557843Smckusick name[4] = uap->arg; 69658415Smckusick error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 69757843Smckusick break; 69857843Smckusick 69957843Smckusick case KINFO_VNODE: 70057843Smckusick name[0] = KERN_VNODE; 70158415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 70257843Smckusick break; 70357843Smckusick 70457843Smckusick case KINFO_PROC: 70557843Smckusick name[0] = KERN_PROC; 70657843Smckusick name[1] = uap->op & 0xff; 70757843Smckusick name[2] = uap->arg; 70858415Smckusick error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 70957843Smckusick break; 71057843Smckusick 71157843Smckusick case KINFO_FILE: 71257843Smckusick name[0] = KERN_FILE; 71358415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 71457843Smckusick break; 71557843Smckusick 71657843Smckusick case KINFO_METER: 71757843Smckusick name[0] = VM_METER; 71858415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 71957843Smckusick break; 72057843Smckusick 72157843Smckusick case KINFO_LOADAVG: 72257843Smckusick name[0] = VM_LOADAVG; 72358415Smckusick error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 72457843Smckusick break; 72557843Smckusick 72657843Smckusick case KINFO_CLOCKRATE: 72757843Smckusick name[0] = KERN_CLOCKRATE; 72858415Smckusick error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 72957843Smckusick break; 73057843Smckusick 73157843Smckusick default: 73258415Smckusick return (EOPNOTSUPP); 73350149Smarc } 73457843Smckusick if (error) 73557843Smckusick return (error); 73657843Smckusick *retval = size; 73758461Smckusick if (uap->size) 73858461Smckusick error = copyout((caddr_t)&size, (caddr_t)uap->size, 73958461Smckusick sizeof(size)); 74058461Smckusick return (error); 74150149Smarc } 74257843Smckusick #endif /* COMPAT_43 */ 743