kern_sysctl.c revision 11863
11541Srgrimes/*- 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software contributed to Berkeley by 61541Srgrimes * Mike Karels at Berkeley Software Design, Inc. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 3. All advertising materials mentioning features or use of this software 171541Srgrimes * must display the following acknowledgement: 181541Srgrimes * This product includes software developed by the University of 191541Srgrimes * California, Berkeley and its contributors. 201541Srgrimes * 4. Neither the name of the University nor the names of its contributors 211541Srgrimes * may be used to endorse or promote products derived from this software 221541Srgrimes * without specific prior written permission. 231541Srgrimes * 241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341541Srgrimes * SUCH DAMAGE. 351541Srgrimes * 361541Srgrimes * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 3711863Sphk * $Id: kern_sysctl.c,v 1.28 1995/07/31 10:07:31 mpp Exp $ 381541Srgrimes */ 391541Srgrimes 401541Srgrimes/* 411541Srgrimes * sysctl system call. 421541Srgrimes */ 431541Srgrimes 441541Srgrimes#include <sys/param.h> 451541Srgrimes#include <sys/systm.h> 461541Srgrimes#include <sys/kernel.h> 471541Srgrimes#include <sys/malloc.h> 481541Srgrimes#include <sys/proc.h> 491541Srgrimes#include <sys/file.h> 501541Srgrimes#include <sys/vnode.h> 511541Srgrimes#include <sys/unistd.h> 521541Srgrimes#include <sys/buf.h> 531541Srgrimes#include <sys/ioctl.h> 541541Srgrimes#include <sys/tty.h> 558481Swollman#include <sys/conf.h> 561541Srgrimes#include <vm/vm.h> 571541Srgrimes#include <sys/sysctl.h> 581541Srgrimes 591541Srgrimes#ifdef DEBUG 604467Sbdestatic sysctlfn debug_sysctl; 611541Srgrimes#endif 621541Srgrimes 6311863Sphk/* BEGIN_MIB */ 6411863SphkSYSCTL_NODE(,CTL_KERN, kern, 0, "High kernel, proc, limits &c"); 6511863SphkSYSCTL_NODE(,CTL_VM, vm, 0, "Virtual memory"); 6611863SphkSYSCTL_NODE(,CTL_FS, fs, 0, "File system"); 6711863SphkSYSCTL_NODE(,CTL_NET, net, 0, "Network, (see socket.h)"); 6811863SphkSYSCTL_NODE(,CTL_DEBUG, debug, 0, "Debugging"); 6911863SphkSYSCTL_NODE(,CTL_HW, hw, 0, "hardware"); 7011863SphkSYSCTL_NODE(,CTL_MACHDEP, machdep,0, "machine dependent"); 7111863SphkSYSCTL_NODE(,CTL_USER, user, 0, "user-level"); 7211863Sphk 7311863SphkSYSCTL_STRING(_kern,KERN_OSTYPE, ostype, 7411863Sphk CTLFLAG_RD, ostype, 0, 0, ""); 7511863Sphk 7611863SphkSYSCTL_STRING(_kern,KERN_OSRELEASE, osrelease, 7711863Sphk CTLFLAG_RD, osrelease, 0, 0, ""); 7811863Sphk 7911863SphkSYSCTL_INT(_kern,KERN_OSREV, osrevision, 8011863Sphk CTLFLAG_RD, 0, BSD, 0, ""); 8111863Sphk 8211863SphkSYSCTL_STRING(_kern,KERN_VERSION, version, 8311863Sphk CTLFLAG_RD, version, 0, 0, ""); 8411863Sphk 8511863Sphkextern int osreldate; 8611863SphkSYSCTL_INT(_kern,KERN_OSRELDATE, osreldate, 8711863Sphk CTLFLAG_RD, &osreldate, 0, 0, ""); 8811863Sphk 8911863SphkSYSCTL_INT(_kern,KERN_MAXVNODES, maxvnodes, 9011863Sphk CTLFLAG_RD, &desiredvnodes, 0, 0, ""); 9111863Sphk 9211863SphkSYSCTL_INT(_kern,KERN_MAXPROC, maxproc, 9311863Sphk CTLFLAG_RD, &maxproc, 0, 0, ""); 9411863Sphk 9511863SphkSYSCTL_INT(_kern,KERN_MAXPROCPERUID,maxprocperuid, 9611863Sphk CTLFLAG_RD, &maxprocperuid, 0, 0, ""); 9711863Sphk 9811863SphkSYSCTL_INT(_kern,KERN_MAXFILESPERPROC, maxfilesperproc, 9911863Sphk CTLFLAG_RD, &maxfilesperproc, 0, 0, ""); 10011863Sphk 10111863SphkSYSCTL_INT(_kern,KERN_ARGMAX, argmax, 10211863Sphk CTLFLAG_RD, 0, ARG_MAX, 0, ""); 10311863Sphk 10411863SphkSYSCTL_INT(_kern,KERN_POSIX1, posix1version, 10511863Sphk CTLFLAG_RD, 0, _POSIX_VERSION, 0, ""); 10611863Sphk 10711863SphkSYSCTL_INT(_kern,KERN_NGROUPS, ngroups, 10811863Sphk CTLFLAG_RD, 0, NGROUPS_MAX, 0, ""); 10911863Sphk 11011863SphkSYSCTL_INT(_kern,KERN_JOB_CONTROL, job_control, 11111863Sphk CTLFLAG_RD, 0, 1, 0, ""); 11211863Sphk 11311863SphkSYSCTL_INT(_kern,KERN_MAXFILES, maxfiles, 11411863Sphk CTLFLAG_RW, &maxfiles, 0, 0, ""); 11511863Sphk 11611863Sphk#ifdef _POSIX_SAVED_IDS 11711863SphkSYSCTL_INT(_kern,KERN_SAVED_IDS, saved_ids, 11811863Sphk CTLFLAG_RD, 0, 1, 0, ""); 11911863Sphk#else 12011863SphkSYSCTL_INT(_kern,KERN_SAVED_IDS, saved_ids, 12111863Sphk CTLFLAG_RD, 0, 0, 0, ""); 12211863Sphk#endif 12311863Sphk 12411863Sphkchar kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 12511863Sphk 12611863SphkSYSCTL_STRING(_kern,KERN_BOOTFILE, bootfile, 12711863Sphk CTLFLAG_RW, kernelname, sizeof kernelname, 0, ""); 12811863Sphk 12911863SphkSYSCTL_STRUCT(_kern,KERN_BOOTTIME, boottime, 13011863Sphk CTLFLAG_RW, &boottime, timeval, 0, ""); 13111863Sphk 13211863SphkSYSCTL_STRING(_hw,HW_MACHINE, machine, 13311863Sphk CTLFLAG_RD, machine, 0, 0, ""); 13411863Sphk 13511863SphkSYSCTL_STRING(_hw,HW_MACHINE, model, 13611863Sphk CTLFLAG_RD, cpu_model, 0, 0, ""); 13711863Sphk 13811863SphkSYSCTL_INT(_hw,HW_NCPU, ncpu, 13911863Sphk CTLFLAG_RD, 0, 1, 0, ""); 14011863Sphk 14111863SphkSYSCTL_INT(_hw,HW_BYTEORDER, byteorder, 14211863Sphk CTLFLAG_RD, 0, BYTE_ORDER, 0, ""); 14311863Sphk 14411863SphkSYSCTL_INT(_hw,HW_PAGESIZE, pagesize, 14511863Sphk CTLFLAG_RD, 0, PAGE_SIZE, 0, ""); 14611863Sphk 14711863SphkSYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, 14811863Sphk CTLFLAG_RD, &hw_float, 0, 0, ""); 14911863Sphk 15011863Sphk/* END_MIB */ 15111863Sphk 15211863Sphkextern int vfs_update_wakeup; 15311863Sphkextern int vfs_update_interval; 15411863Sphkstatic int 15511863Sphksysctl_kern_updateinterval(oidp, when, error) 15611863Sphk struct sysctl_oid *oidp; 15711863Sphk int when; 15811863Sphk int error; 15911863Sphk{ 16011863Sphk if (when == CTLAFTER && !error) 16111863Sphk wakeup(&vfs_update_wakeup); 16211863Sphk return 0; 16311863Sphk} 16411863Sphk 16511863SphkSYSCTL_INT(_kern,KERN_UPDATEINTERVAL, update, 16611863Sphk CTLFLAG_RD, &vfs_update_interval, 0, sysctl_kern_updateinterval,""); 16711863Sphk 16811863Sphk 16911863Sphkstatic int 17011863Sphkdo_int(oidp, oldp, oldlenp, newp, newlen) 17111863Sphk struct sysctl_oid *oidp; 17211863Sphk void *oldp; 17311863Sphk size_t *oldlenp; 17411863Sphk void *newp; 17511863Sphk size_t newlen; 17611863Sphk{ 17711863Sphk int error = 0; 17811863Sphk 17911863Sphk /* If there isn't sufficient space to return */ 18011863Sphk if (oldp && *oldlenp < sizeof(int)) 18111863Sphk return (ENOMEM); 18211863Sphk 18311863Sphk /* If it is a constant, don't write */ 18411863Sphk if (newp && !oidp->oid_arg1) 18511863Sphk return (EPERM); 18611863Sphk 18711863Sphk /* If we get more than an int */ 18811863Sphk if (newp && newlen != sizeof(int)) 18911863Sphk return (EINVAL); 19011863Sphk 19111863Sphk *oldlenp = sizeof(int); 19211863Sphk if (oldp && oidp->oid_arg1 ) 19311863Sphk error = copyout(oidp->oid_arg1, oldp, sizeof(int)); 19411863Sphk else if (oldp) 19511863Sphk error = copyout(&oidp->oid_arg2, oldp, sizeof(int)); 19611863Sphk if (error == 0 && newp) 19711863Sphk error = copyin(newp, oidp->oid_arg1, sizeof(int)); 19811863Sphk return (error); 19911863Sphk} 20011863Sphk 20111863Sphkstatic int 20211863Sphkdo_string(oidp, oldp, oldlenp, newp, newlen) 20311863Sphk struct sysctl_oid *oidp; 20411863Sphk void *oldp; 20511863Sphk size_t *oldlenp; 20611863Sphk void *newp; 20711863Sphk size_t newlen; 20811863Sphk{ 20911863Sphk int len, error = 0, rval = 0; 21011863Sphk int maxlen = oidp->oid_arg2; 21111863Sphk char *str = (char *)(oidp->oid_arg1); 21211863Sphk 21311863Sphk len = strlen(str) + 1; 21411863Sphk 21511863Sphk if (oldp && *oldlenp < len) { 21611863Sphk len = *oldlenp; 21711863Sphk rval = ENOMEM; 21811863Sphk } 21911863Sphk 22011863Sphk if (newp && newlen >= maxlen) 22111863Sphk return (EINVAL); 22211863Sphk 22311863Sphk if (oldp) { 22411863Sphk *oldlenp = len; 22511863Sphk error = copyout(str, oldp, len); 22611863Sphk if (error) 22711863Sphk rval = error; 22811863Sphk } 22911863Sphk if ((error == 0 || error == ENOMEM) && newp) { 23011863Sphk error = copyin(newp, str, newlen); 23111863Sphk if (error) 23211863Sphk rval = error; 23311863Sphk str[newlen] = 0; 23411863Sphk } 23511863Sphk return (rval); 23611863Sphk} 23711863Sphk 23811863Sphkstatic int 23911863Sphkdo_opaque(oidp, oldp, oldlenp, newp, newlen) 24011863Sphk struct sysctl_oid *oidp; 24111863Sphk void *oldp; 24211863Sphk size_t *oldlenp; 24311863Sphk void *newp; 24411863Sphk size_t newlen; 24511863Sphk{ 24611863Sphk int error = 0, rval = 0; 24711863Sphk char *str = (char *)(oidp->oid_arg1); 24811863Sphk int len = oidp->oid_arg2; 24911863Sphk 25011863Sphk if (oldp && *oldlenp < len) { 25111863Sphk return (ENOMEM); 25211863Sphk } 25311863Sphk 25411863Sphk if (newp && newlen != len) 25511863Sphk return (EINVAL); 25611863Sphk 25711863Sphk if (oldp) { 25811863Sphk *oldlenp = len; 25911863Sphk error = copyout(str, oldp, len); 26011863Sphk if (error) 26111863Sphk rval = error; 26211863Sphk } 26311863Sphk if ((error == 0 || error == ENOMEM) && newp) { 26411863Sphk error = copyin(newp, str, len); 26511863Sphk if (error) 26611863Sphk rval = error; 26711863Sphk str[newlen] = 0; 26811863Sphk } 26911863Sphk return (rval); 27011863Sphk} 27111863Sphk 27211863Sphk 2731541Srgrimes/* 2741541Srgrimes * Locking and stats 2751541Srgrimes */ 2761541Srgrimesstatic struct sysctl_lock { 2771541Srgrimes int sl_lock; 2781541Srgrimes int sl_want; 2791541Srgrimes int sl_locked; 2801541Srgrimes} memlock; 2811541Srgrimes 2821541Srgrimesstruct sysctl_args { 2831541Srgrimes int *name; 2841541Srgrimes u_int namelen; 2851541Srgrimes void *old; 2861541Srgrimes size_t *oldlenp; 2871541Srgrimes void *new; 2881541Srgrimes size_t newlen; 2891541Srgrimes}; 2901541Srgrimes 29111863Sphkextern struct linker_set sysctl_; 29211863Sphk 2931541Srgrimesint 2941541Srgrimes__sysctl(p, uap, retval) 2951541Srgrimes struct proc *p; 2961541Srgrimes register struct sysctl_args *uap; 2971541Srgrimes int *retval; 2981541Srgrimes{ 29911863Sphk int error, dolock = 1, i; 3001549Srgrimes u_int savelen = 0, oldlen = 0; 3011541Srgrimes sysctlfn *fn; 3021541Srgrimes int name[CTL_MAXNAME]; 30311863Sphk struct linker_set *lsp; 30411863Sphk struct sysctl_oid **oidp; 3051541Srgrimes 3061541Srgrimes if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 3071541Srgrimes return (error); 30811863Sphk 3091541Srgrimes /* 3101541Srgrimes * all top-level sysctl names are non-terminal 3111541Srgrimes */ 31211863Sphk 3131541Srgrimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 3141541Srgrimes return (EINVAL); 31511863Sphk 3163308Sphk error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 3173308Sphk if (error) 3181541Srgrimes return (error); 3191541Srgrimes 32011863Sphk oidp = (struct sysctl_oid **) &sysctl_.ls_items[0]; 32111863Sphk 32211863Sphk for (i=0; *oidp && i < CTL_MAXNAME; oidp++) { 32311863Sphk if ((*oidp)->oid_arg1 == (void *) *oidp) 32411863Sphk continue; 32511863Sphk if ((*oidp)->oid_number != name[i]) 32611863Sphk continue; 32711863Sphk i++; 32811863Sphk if (((*oidp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 32911863Sphk if (i == uap->namelen) 33011863Sphk /* XXX fail when "old" goes away */ 33111863Sphk goto old; 33211863Sphk lsp = (struct linker_set*)(*oidp)->oid_arg1; 33311863Sphk oidp = (struct sysctl_oid **) &lsp->ls_items[0]; 33411863Sphk } else { 33511863Sphk if (i != uap->namelen) 33611863Sphk /* XXX fail when "old" goes away */ 33711863Sphk goto old; 33811863Sphk goto found; 33911863Sphk } 34011863Sphk } 34111863Sphk /* XXX fail when "old" goes away */ 34211863Sphk goto old; 34311863Sphkfound: 34411863Sphk#if 0 34511863Sphk printf("Found <%s> %x %p\n", 34611863Sphk (*oidp)->oid_name, (*oidp)->oid_kind, (*oidp)->oid_arg1); 34711863Sphk#endif 34811863Sphk 34911863Sphk if ((*oidp)->oid_handler) { 35011863Sphk i = ((*oidp)->oid_handler) (*oidp,CTLBEFORE,0); 35111863Sphk if (i) 35211863Sphk return i; 35311863Sphk } 35411863Sphk if ((*oidp)->oid_kind & CTLFLAG_NOLOCK) 35511863Sphk dolock = 0; 35611863Sphk 35711863Sphk if (uap->oldlenp && 35811863Sphk (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 35911863Sphk return (error); 36011863Sphk 36111863Sphk if (uap->old != NULL) { 36211863Sphk if (!useracc(uap->old, oldlen, B_WRITE)) 36311863Sphk return (EFAULT); 36411863Sphk while (memlock.sl_lock) { 36511863Sphk memlock.sl_want = 1; 36611863Sphk (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 36711863Sphk memlock.sl_locked++; 36811863Sphk } 36911863Sphk memlock.sl_lock = 1; 37011863Sphk if (dolock) 37111863Sphk vslock(uap->old, oldlen); 37211863Sphk savelen = oldlen; 37311863Sphk } 37411863Sphk 37511863Sphk /* If writing isn't allowed */ 37611863Sphk if (uap->new && !((*oidp)->oid_kind & CTLFLAG_WR)) 37711863Sphk return (EPERM); 37811863Sphk 37911863Sphk switch ((*oidp)->oid_kind & CTLTYPE) { 38011863Sphk case CTLTYPE_INT: 38111863Sphk error = do_int(*oidp, 38211863Sphk uap->old, &oldlen, 38311863Sphk uap->new, uap->newlen); 38411863Sphk break; 38511863Sphk case CTLTYPE_STRING: 38611863Sphk error = do_string(*oidp, 38711863Sphk uap->old, &oldlen, 38811863Sphk uap->new, uap->newlen); 38911863Sphk break; 39011863Sphk case CTLTYPE_OPAQUE: 39111863Sphk error = do_opaque(*oidp, 39211863Sphk uap->old, &oldlen, 39311863Sphk uap->new, uap->newlen); 39411863Sphk break; 39511863Sphk default: 39611863Sphk printf("sysctl not handled\n"); 39711863Sphk error = EINVAL; 39811863Sphk break; 39911863Sphk } 40011863Sphk 40111863Sphk if ((*oidp)->oid_handler) { 40211863Sphk i = ((*oidp)->oid_handler) (*oidp,CTLAFTER,error); 40311863Sphk if (i) 40411863Sphk error = i; 40511863Sphk } 40611863Sphk goto over_and_out; 40711863Sphk 40811863Sphk old: 4091541Srgrimes switch (name[0]) { 4101541Srgrimes case CTL_KERN: 4111541Srgrimes fn = kern_sysctl; 4122903Sache if (name[1] != KERN_VNODE) /* XXX */ 4131541Srgrimes dolock = 0; 4141541Srgrimes break; 4151541Srgrimes case CTL_HW: 4161541Srgrimes fn = hw_sysctl; 4171541Srgrimes break; 4181541Srgrimes case CTL_VM: 4191541Srgrimes fn = vm_sysctl; 4201541Srgrimes break; 4211541Srgrimes case CTL_NET: 4221541Srgrimes fn = net_sysctl; 4231541Srgrimes break; 4241541Srgrimes case CTL_FS: 4251541Srgrimes fn = fs_sysctl; 4261541Srgrimes break; 4271541Srgrimes case CTL_MACHDEP: 4281541Srgrimes fn = cpu_sysctl; 4291541Srgrimes break; 4301541Srgrimes#ifdef DEBUG 4311541Srgrimes case CTL_DEBUG: 4321541Srgrimes fn = debug_sysctl; 4331541Srgrimes break; 4341541Srgrimes#endif 4351541Srgrimes default: 4361541Srgrimes return (EOPNOTSUPP); 4371541Srgrimes } 4381541Srgrimes if (uap->oldlenp && 4391541Srgrimes (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 4401541Srgrimes return (error); 44111863Sphk 4421541Srgrimes if (uap->old != NULL) { 4431541Srgrimes if (!useracc(uap->old, oldlen, B_WRITE)) 4441541Srgrimes return (EFAULT); 4451541Srgrimes while (memlock.sl_lock) { 4461541Srgrimes memlock.sl_want = 1; 4473396Sdg (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 4481541Srgrimes memlock.sl_locked++; 4491541Srgrimes } 4501541Srgrimes memlock.sl_lock = 1; 4511541Srgrimes if (dolock) 4521541Srgrimes vslock(uap->old, oldlen); 4531541Srgrimes savelen = oldlen; 4541541Srgrimes } 45511863Sphk 45611863Sphk 4571541Srgrimes error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 4581541Srgrimes uap->new, uap->newlen, p); 45911863Sphk over_and_out: 4601541Srgrimes if (uap->old != NULL) { 4611541Srgrimes if (dolock) 4621541Srgrimes vsunlock(uap->old, savelen, B_WRITE); 4631541Srgrimes memlock.sl_lock = 0; 4641541Srgrimes if (memlock.sl_want) { 4651541Srgrimes memlock.sl_want = 0; 4661541Srgrimes wakeup((caddr_t)&memlock); 4671541Srgrimes } 4681541Srgrimes } 4691541Srgrimes if (error) 4701541Srgrimes return (error); 4711541Srgrimes if (uap->oldlenp) 4721541Srgrimes error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 4731541Srgrimes *retval = oldlen; 4741541Srgrimes return (0); 4751541Srgrimes} 4761541Srgrimes 4771541Srgrimes/* 4781541Srgrimes * Attributes stored in the kernel. 4791541Srgrimes */ 4801541Srgrimeschar hostname[MAXHOSTNAMELEN]; 4811541Srgrimesint hostnamelen; 4821925Swollmanchar domainname[MAXHOSTNAMELEN]; 4831925Swollmanint domainnamelen; 4841541Srgrimeslong hostid; 4851995Swollmanint securelevel = -1; 4861541Srgrimes 4871541Srgrimes/* 4881541Srgrimes * kernel related system variables. 4891541Srgrimes */ 4901549Srgrimesint 4911541Srgrimeskern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 4921541Srgrimes int *name; 4931541Srgrimes u_int namelen; 4941541Srgrimes void *oldp; 4951541Srgrimes size_t *oldlenp; 4961541Srgrimes void *newp; 4971541Srgrimes size_t newlen; 4981541Srgrimes struct proc *p; 4991541Srgrimes{ 5001541Srgrimes int error, level, inthostid; 5018481Swollman dev_t ndumpdev; 5021541Srgrimes 5031541Srgrimes /* all sysctl names at this level are terminal */ 5042858Swollman if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 5052858Swollman || name[0] == KERN_NTP_PLL)) 5061541Srgrimes return (ENOTDIR); /* overloaded */ 5071541Srgrimes 5081541Srgrimes switch (name[0]) { 50911863Sphk 5101541Srgrimes case KERN_SECURELVL: 5111541Srgrimes level = securelevel; 5121541Srgrimes if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 5131541Srgrimes newp == NULL) 5141541Srgrimes return (error); 5151541Srgrimes if (level < securelevel && p->p_pid != 1) 5161541Srgrimes return (EPERM); 5171541Srgrimes securelevel = level; 5181541Srgrimes return (0); 5191541Srgrimes case KERN_HOSTNAME: 5201541Srgrimes error = sysctl_string(oldp, oldlenp, newp, newlen, 5211541Srgrimes hostname, sizeof(hostname)); 5229816Smpp if (newp) 5239816Smpp if (error == 0 || error == ENOMEM) 5249816Smpp hostnamelen = newlen; 5251541Srgrimes return (error); 5261925Swollman case KERN_DOMAINNAME: 5271925Swollman error = sysctl_string(oldp, oldlenp, newp, newlen, 5281925Swollman domainname, sizeof(domainname)); 5299816Smpp if (newp) 5309816Smpp if (error == 0 || error == ENOMEM) 5319816Smpp domainnamelen = newlen; 5321925Swollman return (error); 5331541Srgrimes case KERN_HOSTID: 5341541Srgrimes inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 5351541Srgrimes error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 5361541Srgrimes hostid = inthostid; 5371541Srgrimes return (error); 5381541Srgrimes case KERN_CLOCKRATE: 5391541Srgrimes return (sysctl_clockrate(oldp, oldlenp)); 5401541Srgrimes case KERN_VNODE: 5411541Srgrimes return (sysctl_vnode(oldp, oldlenp)); 5421541Srgrimes case KERN_PROC: 5431541Srgrimes return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 5441541Srgrimes case KERN_FILE: 5451541Srgrimes return (sysctl_file(oldp, oldlenp)); 5461541Srgrimes#ifdef GPROF 5471541Srgrimes case KERN_PROF: 5481541Srgrimes return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 5491541Srgrimes newp, newlen)); 5501541Srgrimes#endif 5512858Swollman case KERN_NTP_PLL: 5522858Swollman return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp, 5532858Swollman newp, newlen, p)); 5548481Swollman case KERN_DUMPDEV: 5558481Swollman ndumpdev = dumpdev; 5568481Swollman error = sysctl_struct(oldp, oldlenp, newp, newlen, &ndumpdev, 5578481Swollman sizeof ndumpdev); 5588481Swollman if (!error && ndumpdev != dumpdev) { 5598481Swollman error = setdumpdev(ndumpdev); 5608481Swollman } 5618481Swollman return error; 5621541Srgrimes default: 5631541Srgrimes return (EOPNOTSUPP); 5641541Srgrimes } 5651541Srgrimes /* NOTREACHED */ 5661541Srgrimes} 5671541Srgrimes 5681541Srgrimes/* 5691541Srgrimes * hardware related system variables. 5701541Srgrimes */ 5711549Srgrimesint 5721541Srgrimeshw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 5731541Srgrimes int *name; 5741541Srgrimes u_int namelen; 5751541Srgrimes void *oldp; 5761541Srgrimes size_t *oldlenp; 5771541Srgrimes void *newp; 5781541Srgrimes size_t newlen; 5791541Srgrimes struct proc *p; 5801541Srgrimes{ 5813640Swollman /* almost all sysctl names at this level are terminal */ 5823640Swollman if (namelen != 1 && name[0] != HW_DEVCONF) 5831541Srgrimes return (ENOTDIR); /* overloaded */ 5841541Srgrimes 5851541Srgrimes switch (name[0]) { 5861541Srgrimes case HW_PHYSMEM: 5871541Srgrimes return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 5881541Srgrimes case HW_USERMEM: 5891541Srgrimes return (sysctl_rdint(oldp, oldlenp, newp, 5901541Srgrimes ctob(physmem - cnt.v_wire_count))); 5913640Swollman case HW_DEVCONF: 5923640Swollman return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp, 5933640Swollman newp, newlen, p)); 5941541Srgrimes default: 5951541Srgrimes return (EOPNOTSUPP); 5961541Srgrimes } 5971541Srgrimes /* NOTREACHED */ 5981541Srgrimes} 5991541Srgrimes 6001541Srgrimes#ifdef DEBUG 6011541Srgrimes/* 6021541Srgrimes * Debugging related system variables. 6031541Srgrimes */ 6041541Srgrimesstruct ctldebug debug0, debug1, debug2, debug3, debug4; 6051541Srgrimesstruct ctldebug debug5, debug6, debug7, debug8, debug9; 6061541Srgrimesstruct ctldebug debug10, debug11, debug12, debug13, debug14; 6071541Srgrimesstruct ctldebug debug15, debug16, debug17, debug18, debug19; 6081541Srgrimesstatic struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 6091541Srgrimes &debug0, &debug1, &debug2, &debug3, &debug4, 6101541Srgrimes &debug5, &debug6, &debug7, &debug8, &debug9, 6111541Srgrimes &debug10, &debug11, &debug12, &debug13, &debug14, 6121541Srgrimes &debug15, &debug16, &debug17, &debug18, &debug19, 6131541Srgrimes}; 6144467Sbdestatic int 6151541Srgrimesdebug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 6161541Srgrimes int *name; 6171541Srgrimes u_int namelen; 6181541Srgrimes void *oldp; 6191541Srgrimes size_t *oldlenp; 6201541Srgrimes void *newp; 6211541Srgrimes size_t newlen; 6221541Srgrimes struct proc *p; 6231541Srgrimes{ 6241541Srgrimes struct ctldebug *cdp; 6251541Srgrimes 6261541Srgrimes /* all sysctl names at this level are name and field */ 6271541Srgrimes if (namelen != 2) 6281541Srgrimes return (ENOTDIR); /* overloaded */ 6291541Srgrimes cdp = debugvars[name[0]]; 6301541Srgrimes if (cdp->debugname == 0) 6311541Srgrimes return (EOPNOTSUPP); 6321541Srgrimes switch (name[1]) { 6331541Srgrimes case CTL_DEBUG_NAME: 6341541Srgrimes return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 6351541Srgrimes case CTL_DEBUG_VALUE: 6361541Srgrimes return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 6371541Srgrimes default: 6381541Srgrimes return (EOPNOTSUPP); 6391541Srgrimes } 6401541Srgrimes /* NOTREACHED */ 6411541Srgrimes} 6421541Srgrimes#endif /* DEBUG */ 6431541Srgrimes 6441541Srgrimes/* 6451541Srgrimes * Validate parameters and get old / set new parameters 6461541Srgrimes * for an integer-valued sysctl function. 6471541Srgrimes */ 6481549Srgrimesint 6491541Srgrimessysctl_int(oldp, oldlenp, newp, newlen, valp) 6501541Srgrimes void *oldp; 6511541Srgrimes size_t *oldlenp; 6521541Srgrimes void *newp; 6531541Srgrimes size_t newlen; 6541541Srgrimes int *valp; 6551541Srgrimes{ 6561541Srgrimes int error = 0; 6571541Srgrimes 6581541Srgrimes if (oldp && *oldlenp < sizeof(int)) 6591541Srgrimes return (ENOMEM); 6601541Srgrimes if (newp && newlen != sizeof(int)) 6611541Srgrimes return (EINVAL); 6621541Srgrimes *oldlenp = sizeof(int); 6631541Srgrimes if (oldp) 6641541Srgrimes error = copyout(valp, oldp, sizeof(int)); 6651541Srgrimes if (error == 0 && newp) 6661541Srgrimes error = copyin(newp, valp, sizeof(int)); 6671541Srgrimes return (error); 6681541Srgrimes} 6691541Srgrimes 6701541Srgrimes/* 6711541Srgrimes * As above, but read-only. 6721541Srgrimes */ 6731549Srgrimesint 6741541Srgrimessysctl_rdint(oldp, oldlenp, newp, val) 6751541Srgrimes void *oldp; 6761541Srgrimes size_t *oldlenp; 6771541Srgrimes void *newp; 6781541Srgrimes int val; 6791541Srgrimes{ 6801541Srgrimes int error = 0; 6811541Srgrimes 6821541Srgrimes if (oldp && *oldlenp < sizeof(int)) 6831541Srgrimes return (ENOMEM); 6841541Srgrimes if (newp) 6851541Srgrimes return (EPERM); 6861541Srgrimes *oldlenp = sizeof(int); 6871541Srgrimes if (oldp) 6881541Srgrimes error = copyout((caddr_t)&val, oldp, sizeof(int)); 6891541Srgrimes return (error); 6901541Srgrimes} 6911541Srgrimes 6921541Srgrimes/* 6931541Srgrimes * Validate parameters and get old / set new parameters 6941541Srgrimes * for a string-valued sysctl function. 6951541Srgrimes */ 6961549Srgrimesint 6971541Srgrimessysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 6981541Srgrimes void *oldp; 6991541Srgrimes size_t *oldlenp; 7001541Srgrimes void *newp; 7011541Srgrimes size_t newlen; 7021541Srgrimes char *str; 7031541Srgrimes int maxlen; 7041541Srgrimes{ 7059816Smpp int len, error = 0, rval = 0; 7061541Srgrimes 7071541Srgrimes len = strlen(str) + 1; 7089816Smpp if (oldp && *oldlenp < len) { 7095150Sguido len = *oldlenp; 7109816Smpp rval = ENOMEM; 7119816Smpp } 7121541Srgrimes if (newp && newlen >= maxlen) 7131541Srgrimes return (EINVAL); 7141541Srgrimes if (oldp) { 7151541Srgrimes *oldlenp = len; 7161541Srgrimes error = copyout(str, oldp, len); 7179816Smpp if (error) 7189816Smpp rval = error; 7191541Srgrimes } 7209816Smpp if ((error == 0 || error == ENOMEM) && newp) { 7211541Srgrimes error = copyin(newp, str, newlen); 7229816Smpp if (error) 7239816Smpp rval = error; 7241541Srgrimes str[newlen] = 0; 7251541Srgrimes } 7269816Smpp return (rval); 7271541Srgrimes} 7281541Srgrimes 7291541Srgrimes/* 7301541Srgrimes * As above, but read-only. 7311541Srgrimes */ 7321549Srgrimesint 7331541Srgrimessysctl_rdstring(oldp, oldlenp, newp, str) 7341541Srgrimes void *oldp; 7351541Srgrimes size_t *oldlenp; 7361541Srgrimes void *newp; 7371541Srgrimes char *str; 7381541Srgrimes{ 7399816Smpp int len, error = 0, rval = 0; 7401541Srgrimes 7411541Srgrimes len = strlen(str) + 1; 7429816Smpp if (oldp && *oldlenp < len) { 7439816Smpp len = *oldlenp; 7449816Smpp rval = ENOMEM; 7459816Smpp } 7461541Srgrimes if (newp) 7471541Srgrimes return (EPERM); 7481541Srgrimes *oldlenp = len; 7491541Srgrimes if (oldp) 7501541Srgrimes error = copyout(str, oldp, len); 7519816Smpp if (error) 7529816Smpp rval = error; 7539816Smpp return (rval); 7541541Srgrimes} 7551541Srgrimes 7561541Srgrimes/* 7571541Srgrimes * Validate parameters and get old / set new parameters 7581541Srgrimes * for a structure oriented sysctl function. 7591541Srgrimes */ 7601549Srgrimesint 7611541Srgrimessysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 7621541Srgrimes void *oldp; 7631541Srgrimes size_t *oldlenp; 7641541Srgrimes void *newp; 7651541Srgrimes size_t newlen; 7661541Srgrimes void *sp; 7671541Srgrimes int len; 7681541Srgrimes{ 7691541Srgrimes int error = 0; 7701541Srgrimes 7711541Srgrimes if (oldp && *oldlenp < len) 7721541Srgrimes return (ENOMEM); 7731541Srgrimes if (newp && newlen > len) 7741541Srgrimes return (EINVAL); 7751541Srgrimes if (oldp) { 7761541Srgrimes *oldlenp = len; 7771541Srgrimes error = copyout(sp, oldp, len); 7781541Srgrimes } 7791541Srgrimes if (error == 0 && newp) 7801541Srgrimes error = copyin(newp, sp, len); 7811541Srgrimes return (error); 7821541Srgrimes} 7831541Srgrimes 7841541Srgrimes/* 7851541Srgrimes * Validate parameters and get old parameters 7861541Srgrimes * for a structure oriented sysctl function. 7871541Srgrimes */ 7881549Srgrimesint 7891541Srgrimessysctl_rdstruct(oldp, oldlenp, newp, sp, len) 7901541Srgrimes void *oldp; 7911541Srgrimes size_t *oldlenp; 7921541Srgrimes void *newp, *sp; 7931541Srgrimes int len; 7941541Srgrimes{ 7951541Srgrimes int error = 0; 7961541Srgrimes 7971541Srgrimes if (oldp && *oldlenp < len) 7981541Srgrimes return (ENOMEM); 7991541Srgrimes if (newp) 8001541Srgrimes return (EPERM); 8011541Srgrimes *oldlenp = len; 8021541Srgrimes if (oldp) 8031541Srgrimes error = copyout(sp, oldp, len); 8041541Srgrimes return (error); 8051541Srgrimes} 8061541Srgrimes 8071541Srgrimes/* 8081541Srgrimes * Get file structures. 8091541Srgrimes */ 8101549Srgrimesint 8111541Srgrimessysctl_file(where, sizep) 8121541Srgrimes char *where; 8131541Srgrimes size_t *sizep; 8141541Srgrimes{ 8151541Srgrimes int buflen, error; 8161541Srgrimes struct file *fp; 8171541Srgrimes char *start = where; 8181541Srgrimes 8191541Srgrimes buflen = *sizep; 8201541Srgrimes if (where == NULL) { 8211541Srgrimes /* 8221541Srgrimes * overestimate by 10 files 8231541Srgrimes */ 8241541Srgrimes *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 8251541Srgrimes return (0); 8261541Srgrimes } 8271541Srgrimes 8281541Srgrimes /* 8291541Srgrimes * first copyout filehead 8301541Srgrimes */ 8311541Srgrimes if (buflen < sizeof(filehead)) { 8321541Srgrimes *sizep = 0; 8331541Srgrimes return (0); 8341541Srgrimes } 8353308Sphk error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 8363308Sphk if (error) 8371541Srgrimes return (error); 8381541Srgrimes buflen -= sizeof(filehead); 8391541Srgrimes where += sizeof(filehead); 8401541Srgrimes 8411541Srgrimes /* 8421541Srgrimes * followed by an array of file structures 8431541Srgrimes */ 8441541Srgrimes for (fp = filehead; fp != NULL; fp = fp->f_filef) { 8451541Srgrimes if (buflen < sizeof(struct file)) { 8461541Srgrimes *sizep = where - start; 8471541Srgrimes return (ENOMEM); 8481541Srgrimes } 8493308Sphk error = copyout((caddr_t)fp, where, sizeof (struct file)); 8503308Sphk if (error) 8511541Srgrimes return (error); 8521541Srgrimes buflen -= sizeof(struct file); 8531541Srgrimes where += sizeof(struct file); 8541541Srgrimes } 8551541Srgrimes *sizep = where - start; 8561541Srgrimes return (0); 8571541Srgrimes} 8581541Srgrimes 8591541Srgrimes/* 8601541Srgrimes * try over estimating by 5 procs 8611541Srgrimes */ 8621541Srgrimes#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 8631541Srgrimes 8641549Srgrimesint 8651541Srgrimessysctl_doproc(name, namelen, where, sizep) 8661541Srgrimes int *name; 8671541Srgrimes u_int namelen; 8681541Srgrimes char *where; 8691541Srgrimes size_t *sizep; 8701541Srgrimes{ 8711541Srgrimes register struct proc *p; 8721541Srgrimes register struct kinfo_proc *dp = (struct kinfo_proc *)where; 8731541Srgrimes register int needed = 0; 8741541Srgrimes int buflen = where != NULL ? *sizep : 0; 8751541Srgrimes int doingzomb; 8761541Srgrimes struct eproc eproc; 8771541Srgrimes int error = 0; 8781541Srgrimes 8791541Srgrimes if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 8801541Srgrimes return (EINVAL); 8811541Srgrimes p = (struct proc *)allproc; 8821541Srgrimes doingzomb = 0; 8831541Srgrimesagain: 8841541Srgrimes for (; p != NULL; p = p->p_next) { 8851541Srgrimes /* 8861541Srgrimes * Skip embryonic processes. 8871541Srgrimes */ 8881541Srgrimes if (p->p_stat == SIDL) 8891541Srgrimes continue; 8901541Srgrimes /* 8911541Srgrimes * TODO - make more efficient (see notes below). 8921541Srgrimes * do by session. 8931541Srgrimes */ 8941541Srgrimes switch (name[0]) { 8951541Srgrimes 8961541Srgrimes case KERN_PROC_PID: 8971541Srgrimes /* could do this with just a lookup */ 8981541Srgrimes if (p->p_pid != (pid_t)name[1]) 8991541Srgrimes continue; 9001541Srgrimes break; 9011541Srgrimes 9021541Srgrimes case KERN_PROC_PGRP: 9031541Srgrimes /* could do this by traversing pgrp */ 9045260Sdg if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 9051541Srgrimes continue; 9061541Srgrimes break; 9071541Srgrimes 9081541Srgrimes case KERN_PROC_TTY: 9091541Srgrimes if ((p->p_flag & P_CONTROLT) == 0 || 9105260Sdg p->p_session == NULL || 9111541Srgrimes p->p_session->s_ttyp == NULL || 9121541Srgrimes p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 9131541Srgrimes continue; 9141541Srgrimes break; 9151541Srgrimes 9161541Srgrimes case KERN_PROC_UID: 9175260Sdg if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 9181541Srgrimes continue; 9191541Srgrimes break; 9201541Srgrimes 9211541Srgrimes case KERN_PROC_RUID: 9225260Sdg if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 9231541Srgrimes continue; 9241541Srgrimes break; 9251541Srgrimes } 9261541Srgrimes if (buflen >= sizeof(struct kinfo_proc)) { 9271541Srgrimes fill_eproc(p, &eproc); 9288876Srgrimes error = copyout((caddr_t)p, &dp->kp_proc, 9293308Sphk sizeof(struct proc)); 9303308Sphk if (error) 9311541Srgrimes return (error); 9323308Sphk error = copyout((caddr_t)&eproc, &dp->kp_eproc, 9333308Sphk sizeof(eproc)); 9343308Sphk if (error) 9351541Srgrimes return (error); 9361541Srgrimes dp++; 9371541Srgrimes buflen -= sizeof(struct kinfo_proc); 9381541Srgrimes } 9391541Srgrimes needed += sizeof(struct kinfo_proc); 9401541Srgrimes } 9411541Srgrimes if (doingzomb == 0) { 9421541Srgrimes p = zombproc; 9431541Srgrimes doingzomb++; 9441541Srgrimes goto again; 9451541Srgrimes } 9461541Srgrimes if (where != NULL) { 9471541Srgrimes *sizep = (caddr_t)dp - where; 9481541Srgrimes if (needed > *sizep) 9491541Srgrimes return (ENOMEM); 9501541Srgrimes } else { 9511541Srgrimes needed += KERN_PROCSLOP; 9521541Srgrimes *sizep = needed; 9531541Srgrimes } 9541541Srgrimes return (0); 9551541Srgrimes} 9561541Srgrimes 9571541Srgrimes/* 9581541Srgrimes * Fill in an eproc structure for the specified process. 9591541Srgrimes */ 9601541Srgrimesvoid 9611541Srgrimesfill_eproc(p, ep) 9621541Srgrimes register struct proc *p; 9631541Srgrimes register struct eproc *ep; 9641541Srgrimes{ 9651541Srgrimes register struct tty *tp; 9661541Srgrimes 9675260Sdg bzero(ep, sizeof(*ep)); 9685260Sdg 9691541Srgrimes ep->e_paddr = p; 9709747Sdg if (p->p_cred) { 9715260Sdg ep->e_pcred = *p->p_cred; 9729747Sdg if (p->p_ucred) 9739747Sdg ep->e_ucred = *p->p_ucred; 9749747Sdg } 9759747Sdg if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) { 9761541Srgrimes register struct vmspace *vm = p->p_vmspace; 9771541Srgrimes 9781541Srgrimes#ifdef pmap_resident_count 9791541Srgrimes ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 9801541Srgrimes#else 9811541Srgrimes ep->e_vm.vm_rssize = vm->vm_rssize; 9821541Srgrimes#endif 9831541Srgrimes ep->e_vm.vm_tsize = vm->vm_tsize; 9841541Srgrimes ep->e_vm.vm_dsize = vm->vm_dsize; 9851541Srgrimes ep->e_vm.vm_ssize = vm->vm_ssize; 9861541Srgrimes#ifndef sparc 9871541Srgrimes ep->e_vm.vm_pmap = vm->vm_pmap; 9881541Srgrimes#endif 9891541Srgrimes } 9901541Srgrimes if (p->p_pptr) 9911541Srgrimes ep->e_ppid = p->p_pptr->p_pid; 9925260Sdg if (p->p_pgrp) { 9935260Sdg ep->e_sess = p->p_pgrp->pg_session; 9945260Sdg ep->e_pgid = p->p_pgrp->pg_id; 9955260Sdg ep->e_jobc = p->p_pgrp->pg_jobc; 9965260Sdg } 9971541Srgrimes if ((p->p_flag & P_CONTROLT) && 9985260Sdg (ep->e_sess != NULL) && 9995260Sdg ((tp = ep->e_sess->s_ttyp) != NULL)) { 10001541Srgrimes ep->e_tdev = tp->t_dev; 10011541Srgrimes ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 10021541Srgrimes ep->e_tsess = tp->t_session; 10031541Srgrimes } else 10041541Srgrimes ep->e_tdev = NODEV; 10058876Srgrimes if (ep->e_sess && ep->e_sess->s_ttyvp) 10065260Sdg ep->e_flag = EPROC_CTTY; 10071541Srgrimes if (SESS_LEADER(p)) 10081541Srgrimes ep->e_flag |= EPROC_SLEADER; 10095260Sdg if (p->p_wmesg) { 10101541Srgrimes strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 10115260Sdg ep->e_wmesg[WMESGLEN] = 0; 10125260Sdg } 10131541Srgrimes} 10141541Srgrimes 10151541Srgrimes#ifdef COMPAT_43 10161541Srgrimes#include <sys/socket.h> 10171541Srgrimes#define KINFO_PROC (0<<8) 10181541Srgrimes#define KINFO_RT (1<<8) 10191541Srgrimes#define KINFO_VNODE (2<<8) 10201541Srgrimes#define KINFO_FILE (3<<8) 10211541Srgrimes#define KINFO_METER (4<<8) 10221541Srgrimes#define KINFO_LOADAVG (5<<8) 10231541Srgrimes#define KINFO_CLOCKRATE (6<<8) 10241541Srgrimes 10259455Speter/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 10269455Speter#define KINFO_BSDI_SYSINFO (101<<8) 10279455Speter 10289455Speter/* 10299455Speter * XXX this is bloat, but I hope it's better here than on the potentially 10309455Speter * limited kernel stack... -Peter 10319455Speter */ 10329455Speter 10339455Speterstruct { 10349455Speter int bsdi_machine; /* "i386" on BSD/386 */ 10359455Speter/* ^^^ this is an offset to the string, relative to the struct start */ 10369455Speter char *pad0; 10379455Speter long pad1; 10389455Speter long pad2; 10399455Speter long pad3; 10409455Speter u_long pad4; 10419455Speter u_long pad5; 10429455Speter u_long pad6; 10439455Speter 10449455Speter int bsdi_ostype; /* "BSD/386" on BSD/386 */ 10459455Speter int bsdi_osrelease; /* "1.1" on BSD/386 */ 10469455Speter long pad7; 10479455Speter long pad8; 10489455Speter char *pad9; 10499455Speter 10509455Speter long pad10; 10519455Speter long pad11; 10529455Speter int pad12; 10539455Speter long pad13; 10549455Speter quad_t pad14; 10559455Speter long pad15; 10569455Speter 10579455Speter struct timeval pad16; 10589455Speter /* we dont set this, because BSDI's uname used gethostname() instead */ 10599455Speter int bsdi_hostname; /* hostname on BSD/386 */ 10609455Speter 10619455Speter /* the actual string data is appended here */ 10629455Speter 10639455Speter} bsdi_si; 10649455Speter/* 10659455Speter * this data is appended to the end of the bsdi_si structure during copyout. 10669455Speter * The "char *" offsets are relative to the base of the bsdi_si struct. 10679455Speter * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 10689455Speter * should not exceed the length of the buffer here... (or else!! :-) 10699455Speter */ 10709455Speterchar bsdi_strings[80]; /* It had better be less than this! */ 10719455Speter 10721541Srgrimesstruct getkerninfo_args { 10731541Srgrimes int op; 10741541Srgrimes char *where; 10751541Srgrimes int *size; 10761541Srgrimes int arg; 10771541Srgrimes}; 10781541Srgrimes 10791549Srgrimesint 10801541Srgrimesogetkerninfo(p, uap, retval) 10811541Srgrimes struct proc *p; 10821541Srgrimes register struct getkerninfo_args *uap; 10831541Srgrimes int *retval; 10841541Srgrimes{ 10851541Srgrimes int error, name[5]; 10861541Srgrimes u_int size; 10871541Srgrimes 10881541Srgrimes if (uap->size && 10891541Srgrimes (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 10901541Srgrimes return (error); 10911541Srgrimes 10921541Srgrimes switch (uap->op & 0xff00) { 10931541Srgrimes 10941541Srgrimes case KINFO_RT: 10951541Srgrimes name[0] = PF_ROUTE; 10961541Srgrimes name[1] = 0; 10971541Srgrimes name[2] = (uap->op & 0xff0000) >> 16; 10981541Srgrimes name[3] = uap->op & 0xff; 10991541Srgrimes name[4] = uap->arg; 11001541Srgrimes error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 11011541Srgrimes break; 11021541Srgrimes 11031541Srgrimes case KINFO_VNODE: 11041541Srgrimes name[0] = KERN_VNODE; 11051541Srgrimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 11061541Srgrimes break; 11071541Srgrimes 11081541Srgrimes case KINFO_PROC: 11091541Srgrimes name[0] = KERN_PROC; 11101541Srgrimes name[1] = uap->op & 0xff; 11111541Srgrimes name[2] = uap->arg; 11121541Srgrimes error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 11131541Srgrimes break; 11141541Srgrimes 11151541Srgrimes case KINFO_FILE: 11161541Srgrimes name[0] = KERN_FILE; 11171541Srgrimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 11181541Srgrimes break; 11191541Srgrimes 11201541Srgrimes case KINFO_METER: 11211541Srgrimes name[0] = VM_METER; 11221541Srgrimes error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 11231541Srgrimes break; 11241541Srgrimes 11251541Srgrimes case KINFO_LOADAVG: 11261541Srgrimes name[0] = VM_LOADAVG; 11271541Srgrimes error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 11281541Srgrimes break; 11291541Srgrimes 11301541Srgrimes case KINFO_CLOCKRATE: 11311541Srgrimes name[0] = KERN_CLOCKRATE; 11321541Srgrimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 11331541Srgrimes break; 11341541Srgrimes 11359455Speter case KINFO_BSDI_SYSINFO: { 11369455Speter /* 11379455Speter * this is pretty crude, but it's just enough for uname() 11389455Speter * from BSDI's 1.x libc to work. 11399455Speter * 11409455Speter * In particular, it doesn't return the same results when 11419455Speter * the supplied buffer is too small. BSDI's version apparently 11429455Speter * will return the amount copied, and set the *size to how 11439455Speter * much was needed. The emulation framework here isn't capable 11449455Speter * of that, so we just set both to the amount copied. 11459455Speter * BSDI's 2.x product apparently fails with ENOMEM in this 11469455Speter * scenario. 11479455Speter */ 11489455Speter 11499455Speter u_int needed; 11509455Speter u_int left; 11519455Speter char *s; 11529455Speter 11539455Speter bzero((char *)&bsdi_si, sizeof(bsdi_si)); 11549455Speter bzero(bsdi_strings, sizeof(bsdi_strings)); 11559455Speter 11569455Speter s = bsdi_strings; 11579455Speter 11589455Speter bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 11599455Speter strcpy(s, ostype); 11609455Speter s += strlen(s) + 1; 11619455Speter 11629455Speter bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 11639455Speter strcpy(s, osrelease); 11649455Speter s += strlen(s) + 1; 11659455Speter 11669455Speter bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 11679455Speter strcpy(s, machine); 11689455Speter s += strlen(s) + 1; 11699455Speter 11709455Speter needed = sizeof(bsdi_si) + (s - bsdi_strings); 11719455Speter 11729455Speter if (uap->where == NULL) { 11739455Speter /* process is asking how much buffer to supply.. */ 11749455Speter size = needed; 11759455Speter error = 0; 11769455Speter break; 11779455Speter } 11789455Speter 11799455Speter 11809455Speter /* if too much buffer supplied, trim it down */ 11819455Speter if (size > needed) 11829455Speter size = needed; 11839455Speter 11849455Speter /* how much of the buffer is remaining */ 11859455Speter left = size; 11869455Speter 11879455Speter if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 11889455Speter break; 11899455Speter 11909455Speter /* is there any point in continuing? */ 11919455Speter if (left > sizeof(bsdi_si)) { 11929455Speter left -= sizeof(bsdi_si); 11939455Speter error = copyout(&bsdi_strings, 11949455Speter uap->where + sizeof(bsdi_si), left); 11959455Speter } 11969455Speter break; 11979455Speter } 11989455Speter 11991541Srgrimes default: 12001541Srgrimes return (EOPNOTSUPP); 12011541Srgrimes } 12021541Srgrimes if (error) 12031541Srgrimes return (error); 12041541Srgrimes *retval = size; 12051541Srgrimes if (uap->size) 12061541Srgrimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 12071541Srgrimes sizeof(size)); 12081541Srgrimes return (error); 12091541Srgrimes} 12101541Srgrimes#endif /* COMPAT_43 */ 1211