Annotation of kernel/bsd/kern/kern_sysctl.c, revision 1.1.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.