Annotation of kernel/bsd/kern/kern_sysctl.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
        !            26: /*-
        !            27:  * Copyright (c) 1982, 1986, 1989, 1993
        !            28:  *     The Regents of the University of California.  All rights reserved.
        !            29:  *
        !            30:  * This code is derived from software contributed to Berkeley by
        !            31:  * Mike Karels at Berkeley Software Design, Inc.
        !            32:  *
        !            33:  * Redistribution and use in source and binary forms, with or without
        !            34:  * modification, are permitted provided that the following conditions
        !            35:  * are met:
        !            36:  * 1. Redistributions of source code must retain the above copyright
        !            37:  *    notice, this list of conditions and the following disclaimer.
        !            38:  * 2. Redistributions in binary form must reproduce the above copyright
        !            39:  *    notice, this list of conditions and the following disclaimer in the
        !            40:  *    documentation and/or other materials provided with the distribution.
        !            41:  * 3. All advertising materials mentioning features or use of this software
        !            42:  *    must display the following acknowledgement:
        !            43:  *     This product includes software developed by the University of
        !            44:  *     California, Berkeley and its contributors.
        !            45:  * 4. Neither the name of the University nor the names of its contributors
        !            46:  *    may be used to endorse or promote products derived from this software
        !            47:  *    without specific prior written permission.
        !            48:  *
        !            49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            59:  * SUCH DAMAGE.
        !            60:  *
        !            61:  *     @(#)kern_sysctl.c       8.4 (Berkeley) 4/14/94
        !            62:  */
        !            63: 
        !            64: /*
        !            65:  * sysctl system call.
        !            66:  */
        !            67: 
        !            68: #include <sys/param.h>
        !            69: #include <sys/systm.h>
        !            70: #include <sys/kernel.h>
        !            71: #include <sys/malloc.h>
        !            72: #include <sys/proc.h>
        !            73: #include <sys/file.h>
        !            74: #include <sys/vnode.h>
        !            75: #include <sys/unistd.h>
        !            76: #include <sys/buf.h>
        !            77: #include <sys/ioctl.h>
        !            78: #include <sys/tty.h>
        !            79: #include <sys/disklabel.h>
        !            80: #include <sys/vm.h>
        !            81: #include <sys/sysctl.h>
        !            82: 
        !            83: #include <sys/mount.h>
        !            84: #include <kdebug.h>
        !            85: #if KDEBUG
        !            86: #import <kern/kdebug.h>
        !            87: #endif
        !            88: 
        !            89: #ifdef __ppc__
        !            90: #include <machdep/ppc/powermac.h>
        !            91: #endif
        !            92: 
        !            93: sysctlfn kern_sysctl;
        !            94: sysctlfn hw_sysctl;
        !            95: #ifdef DEBUG
        !            96: sysctlfn debug_sysctl;
        !            97: #endif
        !            98: extern sysctlfn vm_sysctl;
        !            99: extern sysctlfn vfs_sysctl;
        !           100: extern sysctlfn net_sysctl;
        !           101: extern sysctlfn cpu_sysctl;
        !           102: 
        !           103: /*
        !           104:  * temporary location for vm_sysctl.  This should be machine independant
        !           105:  */
        !           106: vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           107:        int *name;
        !           108:        u_int namelen;
        !           109:        void *oldp;
        !           110:        size_t *oldlenp;
        !           111:        void *newp;
        !           112:        size_t newlen;
        !           113:        struct proc *p;
        !           114: {
        !           115:        int error, level, inthostid;
        !           116:        extern long avenrun[3], mach_factor[3];
        !           117:        struct loadavg loadinfo;
        !           118: 
        !           119:        //if (namelen != 1 && !(name[0] == VM_LOADAVG))
        !           120:                //return (ENOTDIR);             /* overloaded */
        !           121: 
        !           122:        switch (name[0]) {
        !           123:        case VM_LOADAVG:
        !           124:                loadinfo.ldavg[0] = avenrun[0];
        !           125:                loadinfo.ldavg[1] = avenrun[1];
        !           126:                loadinfo.ldavg[2] = avenrun[2];
        !           127:                loadinfo.fscale = LSCALE;
        !           128:                return (sysctl_struct(oldp, oldlenp, newp, newlen, &loadinfo, sizeof(struct loadavg)));
        !           129:        case VM_MACHFACTOR:
        !           130:                loadinfo.ldavg[0] = mach_factor[0];
        !           131:                loadinfo.ldavg[1] = mach_factor[1];
        !           132:                loadinfo.ldavg[2] = mach_factor[2];
        !           133:                loadinfo.fscale = LSCALE;
        !           134:                return (sysctl_struct(oldp, oldlenp, newp, newlen, &loadinfo, sizeof(struct loadavg)));
        !           135:        case VM_METER:
        !           136:                return (EOPNOTSUPP);
        !           137:        case VM_MAXID:
        !           138:                return (EOPNOTSUPP);
        !           139:        default:
        !           140:                return (EOPNOTSUPP);
        !           141:        }
        !           142:        /* NOTREACHED */
        !           143:        return (EOPNOTSUPP);
        !           144: }
        !           145: 
        !           146: /*
        !           147:  * Locking and stats
        !           148:  */
        !           149: static struct sysctl_lock {
        !           150:        int     sl_lock;
        !           151:        int     sl_want;
        !           152:        int     sl_locked;
        !           153: } memlock;
        !           154: 
        !           155: struct __sysctl_args {
        !           156:        int *name;
        !           157:        u_int namelen;
        !           158:        void *old;
        !           159:        size_t *oldlenp;
        !           160:        void *new;
        !           161:        size_t newlen;
        !           162: };
        !           163: int
        !           164: __sysctl(p, uap, retval)
        !           165:        struct proc *p;
        !           166:        register struct __sysctl_args *uap;
        !           167:        register_t *retval;
        !           168: {
        !           169:        int error, dolock = 1;
        !           170:        size_t savelen, oldlen = 0;
        !           171:        sysctlfn *fn;
        !           172:        int name[CTL_MAXNAME];
        !           173: 
        !           174:        if (uap->new != NULL &&
        !           175:            (error = suser(p->p_ucred, &p->p_acflag)))
        !           176:                return (error);
        !           177:        /*
        !           178:         * all top-level sysctl names are non-terminal
        !           179:         */
        !           180:        if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
        !           181:                return (EINVAL);
        !           182:        if (error =
        !           183:            copyin(uap->name, &name, uap->namelen * sizeof(int)))
        !           184:                return (error);
        !           185: 
        !           186:        switch (name[0]) {
        !           187:        case CTL_KERN:
        !           188:                fn = kern_sysctl;
        !           189:                if (name[2] != KERN_VNODE)      /* XXX */
        !           190:                        dolock = 0;
        !           191:                break;
        !           192:        case CTL_HW:
        !           193:                fn = hw_sysctl;
        !           194:                break;
        !           195:        case CTL_VM:
        !           196:                fn = vm_sysctl;
        !           197:                break;
        !           198:        case CTL_NET:
        !           199:                fn = net_sysctl;
        !           200:                break;
        !           201:        case CTL_VFS:
        !           202:                fn = vfs_sysctl;
        !           203:                break;
        !           204:        case CTL_MACHDEP:
        !           205:                fn = cpu_sysctl;
        !           206:                break;
        !           207: #ifdef DEBUG
        !           208:        case CTL_DEBUG:
        !           209:                fn = debug_sysctl;
        !           210:                break;
        !           211: #endif
        !           212:        default:
        !           213:                return (EOPNOTSUPP);
        !           214:        }
        !           215: 
        !           216:        if (uap->oldlenp &&
        !           217:            (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
        !           218:                return (error);
        !           219:        if (uap->old != NULL) {
        !           220:                if (!useracc(uap->old, oldlen, B_WRITE))
        !           221:                        return (EFAULT);
        !           222:                while (memlock.sl_lock) {
        !           223:                        memlock.sl_want = 1;
        !           224:                        sleep((caddr_t)&memlock, PRIBIO+1);
        !           225:                        memlock.sl_locked++;
        !           226:                }
        !           227:                memlock.sl_lock = 1;
        !           228:                if (dolock)
        !           229:                        vslock(uap->old, oldlen);
        !           230:                savelen = oldlen;
        !           231:        }
        !           232:        error = (*fn)(name + 1, uap->namelen - 1, uap->old,
        !           233:            &oldlen, uap->new, uap->newlen, p);
        !           234:        if (uap->old != NULL) {
        !           235:                if (dolock)
        !           236:                        vsunlock(uap->old, savelen, B_WRITE);
        !           237:                memlock.sl_lock = 0;
        !           238:                if (memlock.sl_want) {
        !           239:                        memlock.sl_want = 0;
        !           240:                        wakeup((caddr_t)&memlock);
        !           241:                }
        !           242:        }
        !           243:        if (error)
        !           244:                return (error);
        !           245:        if (uap->oldlenp)
        !           246:                error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
        !           247:        *retval = oldlen;
        !           248:        return (0);
        !           249: }
        !           250: 
        !           251: /*
        !           252:  * Attributes stored in the kernel.
        !           253:  */
        !           254: extern char hostname[MAXHOSTNAMELEN]; /* defined in bsd/kern/init_main.c */
        !           255: extern int hostnamelen;
        !           256: extern char domainname[MAXHOSTNAMELEN];
        !           257: extern int domainnamelen;
        !           258: extern long hostid;
        !           259: #ifdef INSECURE
        !           260: int securelevel = -1;
        !           261: #else
        !           262: int securelevel;
        !           263: #endif
        !           264: 
        !           265: /*
        !           266:  * kernel related system variables.
        !           267:  */
        !           268: kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           269:        int *name;
        !           270:        u_int namelen;
        !           271:        void *oldp;
        !           272:        size_t *oldlenp;
        !           273:        void *newp;
        !           274:        size_t newlen;
        !           275:        struct proc *p;
        !           276: {
        !           277:        int error, level, inthostid;
        !           278:        unsigned int oldval=0;
        !           279:        extern char ostype[], osrelease[], version[];
        !           280: 
        !           281:        /* all sysctl names at this level are terminal */
        !           282:        if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 
        !           283: #if KDEBUG
        !           284:                || name[0] == KERN_KDEBUG
        !           285: #endif
        !           286:        ))
        !           287:                return (ENOTDIR);               /* overloaded */
        !           288: 
        !           289:        switch (name[0]) {
        !           290:        case KERN_OSTYPE:
        !           291:                return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
        !           292:        case KERN_OSRELEASE:
        !           293:                return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
        !           294:        case KERN_OSREV:
        !           295:                return (sysctl_rdint(oldp, oldlenp, newp, BSD));
        !           296:        case KERN_VERSION:
        !           297:                return (sysctl_rdstring(oldp, oldlenp, newp, version));
        !           298:        case KERN_MAXVNODES:
        !           299:                oldval = desiredvnodes;
        !           300:                error = sysctl_int(oldp, oldlenp, newp, 
        !           301:                                newlen, &desiredvnodes);
        !           302:                reset_vmobjectcache(oldval, desiredvnodes);
        !           303:                return(error);
        !           304:        case KERN_MAXPROC:
        !           305:                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
        !           306:        case KERN_MAXFILES:
        !           307:                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
        !           308:        case KERN_ARGMAX:
        !           309:                return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
        !           310:        case KERN_SECURELVL:
        !           311:                level = securelevel;
        !           312:                if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
        !           313:                    newp == NULL)
        !           314:                        return (error);
        !           315:                if (level < securelevel && p->p_pid != 1)
        !           316:                        return (EPERM);
        !           317:                securelevel = level;
        !           318:                return (0);
        !           319:        case KERN_HOSTNAME:
        !           320:                error = sysctl_string(oldp, oldlenp, newp, newlen,
        !           321:                    hostname, sizeof(hostname));
        !           322:                if (newp && !error)
        !           323:                        hostnamelen = newlen;
        !           324:                return (error);
        !           325:        case KERN_DOMAINNAME:
        !           326:                error = sysctl_string(oldp, oldlenp, newp, newlen,
        !           327:                    domainname, sizeof(domainname));
        !           328:                if (newp && !error)
        !           329:                        domainnamelen = newlen;
        !           330:                return (error);
        !           331:        case KERN_HOSTID:
        !           332:                inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
        !           333:                error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
        !           334:                hostid = inthostid;
        !           335:                return (error);
        !           336:        case KERN_CLOCKRATE:
        !           337:                return (sysctl_clockrate(oldp, oldlenp));
        !           338:        case KERN_BOOTTIME:
        !           339:                return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
        !           340:                    sizeof(struct timeval)));
        !           341:        case KERN_VNODE:
        !           342:                return (sysctl_vnode(oldp, oldlenp));
        !           343:        case KERN_PROC:
        !           344:                return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
        !           345:        case KERN_FILE:
        !           346:                return (sysctl_file(oldp, oldlenp));
        !           347: #ifdef GPROF
        !           348:        case KERN_PROF:
        !           349:                return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
        !           350:                    newp, newlen));
        !           351: #endif
        !           352:        case KERN_POSIX1:
        !           353:                return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
        !           354:        case KERN_NGROUPS:
        !           355:                return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
        !           356:        case KERN_JOB_CONTROL:
        !           357:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
        !           358:        case KERN_SAVED_IDS:
        !           359: #ifdef _POSIX_SAVED_IDS
        !           360:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
        !           361: #else
        !           362:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
        !           363: #endif
        !           364:        case KERN_MAXPARTITIONS:
        !           365:                return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
        !           366: #if KDEBUG
        !           367:        case KERN_KDEBUG:
        !           368:                return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp));
        !           369: #endif /* KDEBUG */
        !           370:        default:
        !           371:                return (EOPNOTSUPP);
        !           372:        }
        !           373:        /* NOTREACHED */
        !           374: }
        !           375: 
        !           376: /*
        !           377:  * hardware related system variables.
        !           378:  */
        !           379: hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           380:        int *name;
        !           381:        u_int namelen;
        !           382:        void *oldp;
        !           383:        size_t *oldlenp;
        !           384:        void *newp;
        !           385:        size_t newlen;
        !           386:        struct proc *p;
        !           387: {
        !           388:        extern char machine[], cpu_model[];
        !           389: 
        !           390:        /* all sysctl names at this level are terminal */
        !           391:        if (namelen != 1)
        !           392:                return (ENOTDIR);               /* overloaded */
        !           393: 
        !           394:        switch (name[0]) {
        !           395:        case HW_MACHINE:
        !           396:                return (sysctl_rdstring(oldp, oldlenp, newp, machine));
        !           397:        case HW_MODEL:
        !           398:                return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
        !           399:        case HW_NCPU:
        !           400:                return (sysctl_rdint(oldp, oldlenp, newp, 1));  /* XXX */
        !           401:        case HW_BYTEORDER:
        !           402:                return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
        !           403:        case HW_PHYSMEM:
        !           404:                return (sysctl_rdint(oldp, oldlenp, newp, mem_size));
        !           405:        case HW_USERMEM:
        !           406:                return (sysctl_rdint(oldp, oldlenp, newp,
        !           407:                    (mem_size - vm_page_wire_count * PAGE_SIZE)));
        !           408:        case HW_PAGESIZE:
        !           409:                return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
        !           410: #ifdef __ppc__
        !           411:        case HW_NEWWORLD:
        !           412:                return (sysctl_rdint(oldp, oldlenp, newp, IsYosemite()));
        !           413: #endif
        !           414:        default:
        !           415:                return (EOPNOTSUPP);
        !           416:        }
        !           417:        /* NOTREACHED */
        !           418: }
        !           419: 
        !           420: #ifdef DEBUG
        !           421: /*
        !           422:  * Debugging related system variables.
        !           423:  */
        !           424: #if DIAGNOSTIC
        !           425: extern
        !           426: #endif /* DIAGNOSTIC */
        !           427: struct ctldebug debug0, debug1;
        !           428: extern struct ctldebug debug2;  /* dev/ppc/drvCuda needs var to debug ADB */
        !           429: struct ctldebug debug3, debug4;
        !           430: struct ctldebug debug5, debug6, debug7, debug8, debug9;
        !           431: struct ctldebug debug10, debug11, debug12, debug13, debug14;
        !           432: struct ctldebug debug15, debug16, debug17, debug18, debug19;
        !           433: static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
        !           434:        &debug0, &debug1, &debug2, &debug3, &debug4,
        !           435:        &debug5, &debug6, &debug7, &debug8, &debug9,
        !           436:        &debug10, &debug11, &debug12, &debug13, &debug14,
        !           437:        &debug15, &debug16, &debug17, &debug18, &debug19,
        !           438: };
        !           439: int
        !           440: debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           441:        int *name;
        !           442:        u_int namelen;
        !           443:        void *oldp;
        !           444:        size_t *oldlenp;
        !           445:        void *newp;
        !           446:        size_t newlen;
        !           447:        struct proc *p;
        !           448: {
        !           449:        struct ctldebug *cdp;
        !           450: 
        !           451:        /* all sysctl names at this level are name and field */
        !           452:        if (namelen != 2)
        !           453:                return (ENOTDIR);               /* overloaded */
        !           454:        cdp = debugvars[name[0]];
        !           455:        if (cdp->debugname == 0)
        !           456:                return (EOPNOTSUPP);
        !           457:        switch (name[1]) {
        !           458:        case CTL_DEBUG_NAME:
        !           459:                return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
        !           460:        case CTL_DEBUG_VALUE:
        !           461:                return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
        !           462:        default:
        !           463:                return (EOPNOTSUPP);
        !           464:        }
        !           465:        /* NOTREACHED */
        !           466: }
        !           467: #endif /* DEBUG */
        !           468: 
        !           469: /*
        !           470:  * Validate parameters and get old / set new parameters
        !           471:  * for an integer-valued sysctl function.
        !           472:  */
        !           473: sysctl_int(oldp, oldlenp, newp, newlen, valp)
        !           474:        void *oldp;
        !           475:        size_t *oldlenp;
        !           476:        void *newp;
        !           477:        size_t newlen;
        !           478:        int *valp;
        !           479: {
        !           480:        int error = 0;
        !           481: 
        !           482:        if (oldp && *oldlenp < sizeof(int))
        !           483:                return (ENOMEM);
        !           484:        if (newp && newlen != sizeof(int))
        !           485:                return (EINVAL);
        !           486:        *oldlenp = sizeof(int);
        !           487:        if (oldp)
        !           488:                error = copyout(valp, oldp, sizeof(int));
        !           489:        if (error == 0 && newp)
        !           490:                error = copyin(newp, valp, sizeof(int));
        !           491:        return (error);
        !           492: }
        !           493: 
        !           494: /*
        !           495:  * As above, but read-only.
        !           496:  */
        !           497: sysctl_rdint(oldp, oldlenp, newp, val)
        !           498:        void *oldp;
        !           499:        size_t *oldlenp;
        !           500:        void *newp;
        !           501:        int val;
        !           502: {
        !           503:        int error = 0;
        !           504: 
        !           505:        if (oldp && *oldlenp < sizeof(int))
        !           506:                return (ENOMEM);
        !           507:        if (newp)
        !           508:                return (EPERM);
        !           509:        *oldlenp = sizeof(int);
        !           510:        if (oldp)
        !           511:                error = copyout((caddr_t)&val, oldp, sizeof(int));
        !           512:        return (error);
        !           513: }
        !           514: 
        !           515: /*
        !           516:  * Validate parameters and get old / set new parameters
        !           517:  * for a string-valued sysctl function.
        !           518:  */
        !           519: sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
        !           520:        void *oldp;
        !           521:        size_t *oldlenp;
        !           522:        void *newp;
        !           523:        size_t newlen;
        !           524:        char *str;
        !           525:        int maxlen;
        !           526: {
        !           527:        int len, error = 0;
        !           528: 
        !           529:        len = strlen(str) + 1;
        !           530:        if (oldp && *oldlenp < len)
        !           531:                return (ENOMEM);
        !           532:        if (newp && newlen >= maxlen)
        !           533:                return (EINVAL);
        !           534:        if (oldp) {
        !           535:                *oldlenp = len;
        !           536:                error = copyout(str, oldp, len);
        !           537:        }
        !           538:        if (error == 0 && newp) {
        !           539:                error = copyin(newp, str, newlen);
        !           540:                str[newlen] = 0;
        !           541:        }
        !           542:        return (error);
        !           543: }
        !           544: 
        !           545: /*
        !           546:  * As above, but read-only.
        !           547:  */
        !           548: sysctl_rdstring(oldp, oldlenp, newp, str)
        !           549:        void *oldp;
        !           550:        size_t *oldlenp;
        !           551:        void *newp;
        !           552:        char *str;
        !           553: {
        !           554:        int len, error = 0;
        !           555: 
        !           556:        len = strlen(str) + 1;
        !           557:        if (oldp && *oldlenp < len)
        !           558:                return (ENOMEM);
        !           559:        if (newp)
        !           560:                return (EPERM);
        !           561:        *oldlenp = len;
        !           562:        if (oldp)
        !           563:                error = copyout(str, oldp, len);
        !           564:        return (error);
        !           565: }
        !           566: 
        !           567: /*
        !           568:  * Validate parameters and get old / set new parameters
        !           569:  * for a structure oriented sysctl function.
        !           570:  */
        !           571: sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
        !           572:        void *oldp;
        !           573:        size_t *oldlenp;
        !           574:        void *newp;
        !           575:        size_t newlen;
        !           576:        void *sp;
        !           577:        int len;
        !           578: {
        !           579:        int error = 0;
        !           580: 
        !           581:        if (oldp && *oldlenp < len)
        !           582:                return (ENOMEM);
        !           583:        if (newp && newlen > len)
        !           584:                return (EINVAL);
        !           585:        if (oldp) {
        !           586:                *oldlenp = len;
        !           587:                error = copyout(sp, oldp, len);
        !           588:        }
        !           589:        if (error == 0 && newp)
        !           590:                error = copyin(newp, sp, len);
        !           591:        return (error);
        !           592: }
        !           593: 
        !           594: /*
        !           595:  * Validate parameters and get old parameters
        !           596:  * for a structure oriented sysctl function.
        !           597:  */
        !           598: sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
        !           599:        void *oldp;
        !           600:        size_t *oldlenp;
        !           601:        void *newp, *sp;
        !           602:        int len;
        !           603: {
        !           604:        int error = 0;
        !           605: 
        !           606:        if (oldp && *oldlenp < len)
        !           607:                return (ENOMEM);
        !           608:        if (newp)
        !           609:                return (EPERM);
        !           610:        *oldlenp = len;
        !           611:        if (oldp)
        !           612:                error = copyout(sp, oldp, len);
        !           613:        return (error);
        !           614: }
        !           615: 
        !           616: /*
        !           617:  * Get file structures.
        !           618:  */
        !           619: sysctl_file(where, sizep)
        !           620:        char *where;
        !           621:        size_t *sizep;
        !           622: {
        !           623:        int buflen, error;
        !           624:        struct file *fp;
        !           625:        char *start = where;
        !           626: 
        !           627:        buflen = *sizep;
        !           628:        if (where == NULL) {
        !           629:                /*
        !           630:                 * overestimate by 10 files
        !           631:                 */
        !           632:                *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
        !           633:                return (0);
        !           634:        }
        !           635: 
        !           636:        /*
        !           637:         * first copyout filehead
        !           638:         */
        !           639:        if (buflen < sizeof(filehead)) {
        !           640:                *sizep = 0;
        !           641:                return (0);
        !           642:        }
        !           643:        if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
        !           644:                return (error);
        !           645:        buflen -= sizeof(filehead);
        !           646:        where += sizeof(filehead);
        !           647: 
        !           648:        /*
        !           649:         * followed by an array of file structures
        !           650:         */
        !           651:        for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
        !           652:                if (buflen < sizeof(struct file)) {
        !           653:                        *sizep = where - start;
        !           654:                        return (ENOMEM);
        !           655:                }
        !           656:                if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
        !           657:                        return (error);
        !           658:                buflen -= sizeof(struct file);
        !           659:                where += sizeof(struct file);
        !           660:        }
        !           661:        *sizep = where - start;
        !           662:        return (0);
        !           663: }
        !           664: 
        !           665: /*
        !           666:  * try over estimating by 5 procs
        !           667:  */
        !           668: #define KERN_PROCSLOP  (5 * sizeof (struct kinfo_proc))
        !           669: 
        !           670: sysctl_doproc(name, namelen, where, sizep)
        !           671:        int *name;
        !           672:        u_int namelen;
        !           673:        char *where;
        !           674:        size_t *sizep;
        !           675: {
        !           676:        register struct proc *p;
        !           677:        register struct kinfo_proc *dp = (struct kinfo_proc *)where;
        !           678:        register int needed = 0;
        !           679:        int buflen = where != NULL ? *sizep : 0;
        !           680:        int doingzomb;
        !           681:        struct kinfo_proc kproc;
        !           682:        int error = 0;
        !           683: 
        !           684:        if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
        !           685:                return (EINVAL);
        !           686:        p = allproc.lh_first;
        !           687:        doingzomb = 0;
        !           688: again:
        !           689:        for (; p != 0; p = p->p_list.le_next) {
        !           690:                /*
        !           691:                 * Skip embryonic processes.
        !           692:                 */
        !           693:                if (p->p_stat == SIDL)
        !           694:                        continue;
        !           695:                /*
        !           696:                 * TODO - make more efficient (see notes below).
        !           697:                 * do by session.
        !           698:                 */
        !           699:                switch (name[0]) {
        !           700: 
        !           701:                case KERN_PROC_PID:
        !           702:                        /* could do this with just a lookup */
        !           703:                        if (p->p_pid != (pid_t)name[1])
        !           704:                                continue;
        !           705:                        break;
        !           706: 
        !           707:                case KERN_PROC_PGRP:
        !           708:                        /* could do this by traversing pgrp */
        !           709:                        if (p->p_pgrp->pg_id != (pid_t)name[1])
        !           710:                                continue;
        !           711:                        break;
        !           712: 
        !           713:                case KERN_PROC_TTY:
        !           714:                        if ((p->p_flag & P_CONTROLT) == 0 ||
        !           715:                            p->p_session->s_ttyp == NULL ||
        !           716:                            p->p_session->s_ttyp->t_dev != (dev_t)name[1])
        !           717:                                continue;
        !           718:                        break;
        !           719: 
        !           720:                case KERN_PROC_UID:
        !           721:                        if (p->p_ucred->cr_uid != (uid_t)name[1])
        !           722:                                continue;
        !           723:                        break;
        !           724: 
        !           725:                case KERN_PROC_RUID:
        !           726:                        if (p->p_cred->p_ruid != (uid_t)name[1])
        !           727:                                continue;
        !           728:                        break;
        !           729:                }
        !           730:                if (buflen >= sizeof(struct kinfo_proc)) {
        !           731:                        fill_proc(p, &kproc);
        !           732:                        if (error = copyout((caddr_t)&kproc, &dp->kp_proc,
        !           733:                            sizeof(struct kinfo_proc)))
        !           734:                                return (error);
        !           735:                        dp++;
        !           736:                        buflen -= sizeof(struct kinfo_proc);
        !           737:                }
        !           738:                needed += sizeof(struct kinfo_proc);
        !           739:        }
        !           740:        if (doingzomb == 0) {
        !           741:                p = zombproc.lh_first;
        !           742:                doingzomb++;
        !           743:                goto again;
        !           744:        }
        !           745:        if (where != NULL) {
        !           746:                *sizep = (caddr_t)dp - where;
        !           747:                if (needed > *sizep)
        !           748:                        return (ENOMEM);
        !           749:        } else {
        !           750:                needed += KERN_PROCSLOP;
        !           751:                *sizep = needed;
        !           752:        }
        !           753:        return (0);
        !           754: }
        !           755: 
        !           756: void
        !           757: fill_proc(p,kp)
        !           758:        register struct proc *p;
        !           759:        register struct kinfo_proc *kp;
        !           760: {
        !           761:        fill_externproc(p, &kp->kp_proc);
        !           762:        fill_eproc(p, &kp->kp_eproc);
        !           763: }
        !           764: /*
        !           765:  * Fill in an eproc structure for the specified process.
        !           766:  */
        !           767: void
        !           768: fill_eproc(p, ep)
        !           769:        register struct proc *p;
        !           770:        register struct eproc *ep;
        !           771: {
        !           772:        register struct tty *tp;
        !           773: 
        !           774:        ep->e_paddr = p;
        !           775:        ep->e_sess = p->p_pgrp->pg_session;
        !           776:        ep->e_pcred = *p->p_cred;
        !           777:        ep->e_ucred = *p->p_ucred;
        !           778:        if (p->p_stat == SIDL || p->p_stat == SZOMB) {
        !           779:                ep->e_vm.vm_rssize = 0;
        !           780:                ep->e_vm.vm_tsize = 0;
        !           781:                ep->e_vm.vm_dsize = 0;
        !           782:                ep->e_vm.vm_ssize = 0;
        !           783:                /* ep->e_vm.vm_pmap = XXX; */
        !           784:        } else {
        !           785:                register vm_map_t vm = ((task_t)p->task)->map;
        !           786: 
        !           787:                ep->e_vm.vm_rssize = pmap_resident_count(vm->pmap); /*XXX*/
        !           788: //             ep->e_vm.vm_tsize = vm->vm_tsize;
        !           789: //             ep->e_vm.vm_dsize = vm->vm_dsize;
        !           790: //             ep->e_vm.vm_ssize = vm->vm_ssize;
        !           791:        }
        !           792:        if (p->p_pptr)
        !           793:                ep->e_ppid = p->p_pptr->p_pid;
        !           794:        else
        !           795:                ep->e_ppid = 0;
        !           796:        ep->e_pgid = p->p_pgrp->pg_id;
        !           797:        ep->e_jobc = p->p_pgrp->pg_jobc;
        !           798:        if ((p->p_flag & P_CONTROLT) &&
        !           799:             (tp = ep->e_sess->s_ttyp)) {
        !           800:                ep->e_tdev = tp->t_dev;
        !           801:                ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
        !           802:                ep->e_tsess = tp->t_session;
        !           803:        } else
        !           804:                ep->e_tdev = NODEV;
        !           805:        ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
        !           806:        if (SESS_LEADER(p))
        !           807:                ep->e_flag |= EPROC_SLEADER;
        !           808:        if (p->p_wmesg)
        !           809:                strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
        !           810:        ep->e_xsize = ep->e_xrssize = 0;
        !           811:        ep->e_xccount = ep->e_xswrss = 0;
        !           812: }
        !           813: /*
        !           814:  * Fill in an eproc structure for the specified process.
        !           815:  */
        !           816: void
        !           817: fill_externproc(p, exp)
        !           818:        register struct proc *p;
        !           819:        register struct extern_proc *exp;
        !           820: {
        !           821:        exp->p_forw = exp->p_back = NULL;
        !           822:        exp->p_vmspace = NULL;
        !           823:        exp->p_sigacts = p->p_sigacts;
        !           824:        exp->p_flag  = p->p_flag;
        !           825:        exp->p_stat  = p->p_stat ;
        !           826:        exp->p_pid  = p->p_pid ;
        !           827:        exp->p_oppid  = p->p_oppid ;
        !           828:        exp->p_dupfd  = p->p_dupfd ;
        !           829:        /* Mach related  */
        !           830:        exp->user_stack  = p->user_stack ;
        !           831:        exp->exit_thread  = p->exit_thread ;
        !           832:        exp->p_debugger  = p->p_debugger ;
        !           833:        exp->sigwait  = p->sigwait ;
        !           834:        /* scheduling */
        !           835:        exp->p_estcpu  = p->p_estcpu ;
        !           836:        exp->p_cpticks  = p->p_cpticks ;
        !           837:        exp->p_pctcpu  = p->p_pctcpu ;
        !           838:        exp->p_wchan  = p->p_wchan ;
        !           839:        exp->p_wmesg  = p->p_wmesg ;
        !           840:        exp->p_swtime  = p->p_swtime ;
        !           841:        exp->p_slptime  = p->p_slptime ;
        !           842:        bcopy(&p->p_realtimer, &exp->p_realtimer,sizeof(struct itimerval));
        !           843:        bcopy(&p->p_rtime, &exp->p_rtime,sizeof(struct timeval));
        !           844:        exp->p_uticks  = p->p_uticks ;
        !           845:        exp->p_sticks  = p->p_sticks ;
        !           846:        exp->p_iticks  = p->p_iticks ;
        !           847:        exp->p_traceflag  = p->p_traceflag ;
        !           848:        exp->p_tracep  = p->p_tracep ;
        !           849:        exp->p_siglist  = p->p_siglist ;
        !           850:        exp->p_textvp  = p->p_textvp ;
        !           851:        exp->p_holdcnt = 0 ;
        !           852:        exp->p_sigmask  = p->p_sigmask ;
        !           853:        exp->p_sigignore  = p->p_sigignore ;
        !           854:        exp->p_sigcatch  = p->p_sigcatch ;
        !           855:        exp->p_priority  = p->p_priority ;
        !           856:        exp->p_usrpri  = p->p_usrpri ;
        !           857:        exp->p_nice  = p->p_nice ;
        !           858:        bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
        !           859:        exp->p_comm[MAXCOMLEN] = '\0';
        !           860:        exp->p_pgrp  = p->p_pgrp ;
        !           861:        exp->p_addr  = NULL;
        !           862:        exp->p_xstat  = p->p_xstat ;
        !           863:        exp->p_acflag  = p->p_acflag ;
        !           864:        exp->p_ru  = p->p_ru ;
        !           865: }
        !           866: 
        !           867: #if KDEBUG
        !           868: kdebug_ops(name, namelen, where, sizep)
        !           869: int *name;
        !           870: u_int namelen;
        !           871: char *where;
        !           872: size_t *sizep;
        !           873: {
        !           874: int size=*sizep;
        !           875: int ret=0;
        !           876: extern int kdbg_control(int *name, u_int namelen, char * where,size_t * sizep);
        !           877: 
        !           878:        switch(name[0]) {
        !           879:        case KERN_KDEFLAGS:
        !           880:        case KERN_KDDFLAGS:
        !           881:        case KERN_KDENABLE:
        !           882:        case KERN_KDSETBUF:
        !           883:        case KERN_KDGETBUF:
        !           884:        case KERN_KDSETUP:
        !           885:        case KERN_KDREMOVE:
        !           886:        case KERN_KDSETREG:
        !           887:        case KERN_KDGETREG:
        !           888:        case KERN_KDREADTR:
        !           889:                ret = kdbg_control(name, namelen, where, sizep);
        !           890:                break;
        !           891:        default:
        !           892:                ret= EOPNOTSUPP;
        !           893:                break;
        !           894:        }
        !           895:        return(ret);
        !           896: }
        !           897: #endif /* KDEBUG */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.