📄 kern_sysctl.c
字号:
/*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Karels at Berkeley Software Design, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 *//* * sysctl system call. */#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/malloc.h>#include <sys/proc.h>#include <sys/file.h>#include <sys/vnode.h>#include <sys/unistd.h>#include <sys/buf.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <vm/vm.h>#include <sys/sysctl.h>sysctlfn kern_sysctl;sysctlfn hw_sysctl;#ifdef DEBUGsysctlfn debug_sysctl;#endifextern sysctlfn vm_sysctl;extern sysctlfn fs_sysctl;extern sysctlfn net_sysctl;extern sysctlfn cpu_sysctl;/* * Locking and stats */static struct sysctl_lock { int sl_lock; int sl_want; int sl_locked;} memlock;struct sysctl_args { int *name; u_int namelen; void *old; size_t *oldlenp; void *new; size_t newlen;};int__sysctl(p, uap, retval) struct proc *p; register struct sysctl_args *uap; int *retval;{ int error, dolock = 1; u_int savelen, oldlen = 0; sysctlfn *fn; int name[CTL_MAXNAME]; if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) return (error); /* * all top-level sysctl names are non-terminal */ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) return (EINVAL); if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) return (error); switch (name[0]) { case CTL_KERN: fn = kern_sysctl; if (name[2] != KERN_VNODE) /* XXX */ dolock = 0; break; case CTL_HW: fn = hw_sysctl; break; case CTL_VM: fn = vm_sysctl; break; case CTL_NET: fn = net_sysctl; break;#ifdef notyet case CTL_FS: fn = fs_sysctl; break;#endif case CTL_MACHDEP: fn = cpu_sysctl; break;#ifdef DEBUG case CTL_DEBUG: fn = debug_sysctl; break;#endif default: return (EOPNOTSUPP); } if (uap->oldlenp && (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) return (error); if (uap->old != NULL) { if (!useracc(uap->old, oldlen, B_WRITE)) return (EFAULT); while (memlock.sl_lock) { memlock.sl_want = 1; sleep((caddr_t)&memlock, PRIBIO+1); memlock.sl_locked++; } memlock.sl_lock = 1; if (dolock) vslock(uap->old, oldlen); savelen = oldlen; } error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, uap->new, uap->newlen, p); if (uap->old != NULL) { if (dolock) vsunlock(uap->old, savelen, B_WRITE); memlock.sl_lock = 0; if (memlock.sl_want) { memlock.sl_want = 0; wakeup((caddr_t)&memlock); } } if (error) return (error); if (uap->oldlenp) error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); *retval = oldlen; return (0);}/* * Attributes stored in the kernel. */char hostname[MAXHOSTNAMELEN];int hostnamelen;long hostid;int securelevel;/* * kernel related system variables. */kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; struct proc *p;{ int error, level, inthostid; extern char ostype[], osrelease[], version[]; /* all sysctl names at this level are terminal */ if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) return (ENOTDIR); /* overloaded */ switch (name[0]) { case KERN_OSTYPE: return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); case KERN_OSRELEASE: return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); case KERN_OSREV: return (sysctl_rdint(oldp, oldlenp, newp, BSD)); case KERN_VERSION: return (sysctl_rdstring(oldp, oldlenp, newp, version)); case KERN_MAXVNODES: return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); case KERN_MAXPROC: return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); case KERN_MAXFILES: return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); case KERN_ARGMAX: return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); case KERN_SECURELVL: level = securelevel; if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || newp == NULL) return (error); if (level < securelevel && p->p_pid != 1) return (EPERM); securelevel = level; return (0); case KERN_HOSTNAME: error = sysctl_string(oldp, oldlenp, newp, newlen, hostname, sizeof(hostname)); if (newp && !error) hostnamelen = newlen; return (error); case KERN_HOSTID: inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); hostid = inthostid; return (error); case KERN_CLOCKRATE: return (sysctl_clockrate(oldp, oldlenp)); case KERN_BOOTTIME: return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, sizeof(struct timeval))); case KERN_VNODE: return (sysctl_vnode(oldp, oldlenp)); case KERN_PROC: return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); case KERN_FILE: return (sysctl_file(oldp, oldlenp));#ifdef GPROF case KERN_PROF: return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, newp, newlen));#endif case KERN_POSIX1: return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); case KERN_NGROUPS: return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); case KERN_JOB_CONTROL: return (sysctl_rdint(oldp, oldlenp, newp, 1)); case KERN_SAVED_IDS:#ifdef _POSIX_SAVED_IDS return (sysctl_rdint(oldp, oldlenp, newp, 1));#else return (sysctl_rdint(oldp, oldlenp, newp, 0));#endif default: return (EOPNOTSUPP); } /* NOTREACHED */}/* * hardware related system variables. */hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; struct proc *p;{ extern char machine[], cpu_model[]; /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case HW_MACHINE: return (sysctl_rdstring(oldp, oldlenp, newp, machine)); case HW_MODEL: return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); case HW_NCPU: return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ case HW_BYTEORDER: return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); case HW_PHYSMEM: return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); case HW_USERMEM: return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem - cnt.v_wire_count))); case HW_PAGESIZE: return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); default: return (EOPNOTSUPP); } /* NOTREACHED */}#ifdef DEBUG/* * Debugging related system variables. */struct ctldebug debug0, debug1, debug2, debug3, debug4;struct ctldebug debug5, debug6, debug7, debug8, debug9;struct ctldebug debug10, debug11, debug12, debug13, debug14;struct ctldebug debug15, debug16, debug17, debug18, debug19;static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { &debug0, &debug1, &debug2, &debug3, &debug4, &debug5, &debug6, &debug7, &debug8, &debug9, &debug10, &debug11, &debug12, &debug13, &debug14, &debug15, &debug16, &debug17, &debug18, &debug19,};intdebug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; struct proc *p;{ struct ctldebug *cdp; /* all sysctl names at this level are name and field */ if (namelen != 2) return (ENOTDIR); /* overloaded */ cdp = debugvars[name[0]]; if (cdp->debugname == 0) return (EOPNOTSUPP); switch (name[1]) { case CTL_DEBUG_NAME: return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); case CTL_DEBUG_VALUE: return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); default: return (EOPNOTSUPP); } /* NOTREACHED */}#endif /* DEBUG *//* * Validate parameters and get old / set new parameters * for an integer-valued sysctl function. */sysctl_int(oldp, oldlenp, newp, newlen, valp) void *oldp; size_t *oldlenp; void *newp; size_t newlen; int *valp;{ int error = 0; if (oldp && *oldlenp < sizeof(int)) return (ENOMEM); if (newp && newlen != sizeof(int)) return (EINVAL); *oldlenp = sizeof(int); if (oldp) error = copyout(valp, oldp, sizeof(int)); if (error == 0 && newp) error = copyin(newp, valp, sizeof(int)); return (error);}/* * As above, but read-only. */sysctl_rdint(oldp, oldlenp, newp, val) void *oldp; size_t *oldlenp; void *newp; int val;{ int error = 0; if (oldp && *oldlenp < sizeof(int)) return (ENOMEM); if (newp) return (EPERM);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -