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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
        !            23: /*-
        !            24:  * Copyright (c) 1982, 1986, 1989, 1993
        !            25:  *     The Regents of the University of California.  All rights reserved.
        !            26:  *
        !            27:  * This code is derived from software contributed to Berkeley by
        !            28:  * Mike Karels at Berkeley Software Design, Inc.
        !            29:  *
        !            30:  * Redistribution and use in source and binary forms, with or without
        !            31:  * modification, are permitted provided that the following conditions
        !            32:  * are met:
        !            33:  * 1. Redistributions of source code must retain the above copyright
        !            34:  *    notice, this list of conditions and the following disclaimer.
        !            35:  * 2. Redistributions in binary form must reproduce the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer in the
        !            37:  *    documentation and/or other materials provided with the distribution.
        !            38:  * 3. All advertising materials mentioning features or use of this software
        !            39:  *    must display the following acknowledgement:
        !            40:  *     This product includes software developed by the University of
        !            41:  *     California, Berkeley and its contributors.
        !            42:  * 4. Neither the name of the University nor the names of its contributors
        !            43:  *    may be used to endorse or promote products derived from this software
        !            44:  *    without specific prior written permission.
        !            45:  *
        !            46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            56:  * SUCH DAMAGE.
        !            57:  *
        !            58:  *     @(#)kern_sysctl.c       8.4 (Berkeley) 4/14/94
        !            59:  */
        !            60: 
        !            61: /*
        !            62:  * sysctl system call.
        !            63:  */
        !            64: 
        !            65: #include <sys/param.h>
        !            66: #include <sys/systm.h>
        !            67: #include <sys/kernel.h>
        !            68: #include <sys/malloc.h>
        !            69: #include <sys/proc.h>
        !            70: #include <sys/file.h>
        !            71: #include <sys/vnode.h>
        !            72: #include <sys/unistd.h>
        !            73: #include <sys/buf.h>
        !            74: #include <sys/ioctl.h>
        !            75: #include <sys/tty.h>
        !            76: #include <sys/disklabel.h>
        !            77: #include <sys/vm.h>
        !            78: #include <sys/sysctl.h>
        !            79: #include <mach/mach_types.h>
        !            80: #include <mach/vm_param.h>
        !            81: #include <kern/task.h>
        !            82: #include <vm/vm_kern.h>
        !            83: 
        !            84: extern vm_map_t bsd_pageable_map;
        !            85: 
        !            86: #include <sys/mount.h>
        !            87: #import <sys/kdebug.h>
        !            88: 
        !            89: #include <IOKit/IOPlatformExpert.h>
        !            90: 
        !            91: sysctlfn kern_sysctl;
        !            92: sysctlfn hw_sysctl;
        !            93: #ifdef DEBUG
        !            94: sysctlfn debug_sysctl;
        !            95: #endif
        !            96: extern sysctlfn vm_sysctl;
        !            97: extern sysctlfn vfs_sysctl;
        !            98: extern sysctlfn net_sysctl;
        !            99: extern sysctlfn cpu_sysctl;
        !           100: 
        !           101: 
        !           102: int
        !           103: userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t 
        !           104:                *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval);
        !           105: 
        !           106: 
        !           107: /*
        !           108:  * temporary location for vm_sysctl.  This should be machine independant
        !           109:  */
        !           110: vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           111:        int *name;
        !           112:        u_int namelen;
        !           113:        void *oldp;
        !           114:        size_t *oldlenp;
        !           115:        void *newp;
        !           116:        size_t newlen;
        !           117:        struct proc *p;
        !           118: {
        !           119:        int error, level, inthostid;
        !           120:        extern long avenrun[3], mach_factor[3];
        !           121:        struct loadavg loadinfo;
        !           122: 
        !           123:        //if (namelen != 1 && !(name[0] == VM_LOADAVG))
        !           124:                //return (ENOTDIR);             /* overloaded */
        !           125: 
        !           126:        switch (name[0]) {
        !           127:        case VM_LOADAVG:
        !           128:                loadinfo.ldavg[0] = avenrun[0];
        !           129:                loadinfo.ldavg[1] = avenrun[1];
        !           130:                loadinfo.ldavg[2] = avenrun[2];
        !           131:                loadinfo.fscale = LSCALE;
        !           132:                return (sysctl_struct(oldp, oldlenp, newp, newlen, &loadinfo, sizeof(struct loadavg)));
        !           133:        case VM_MACHFACTOR:
        !           134:                loadinfo.ldavg[0] = mach_factor[0];
        !           135:                loadinfo.ldavg[1] = mach_factor[1];
        !           136:                loadinfo.ldavg[2] = mach_factor[2];
        !           137:                loadinfo.fscale = LSCALE;
        !           138:                return (sysctl_struct(oldp, oldlenp, newp, newlen, &loadinfo, sizeof(struct loadavg)));
        !           139:        case VM_METER:
        !           140:                return (EOPNOTSUPP);
        !           141:        case VM_MAXID:
        !           142:                return (EOPNOTSUPP);
        !           143:        default:
        !           144:                return (EOPNOTSUPP);
        !           145:        }
        !           146:        /* NOTREACHED */
        !           147:        return (EOPNOTSUPP);
        !           148: }
        !           149: 
        !           150: /*
        !           151:  * Locking and stats
        !           152:  */
        !           153: static struct sysctl_lock {
        !           154:        int     sl_lock;
        !           155:        int     sl_want;
        !           156:        int     sl_locked;
        !           157: } memlock;
        !           158: 
        !           159: struct __sysctl_args {
        !           160:        int *name;
        !           161:        u_int namelen;
        !           162:        void *old;
        !           163:        size_t *oldlenp;
        !           164:        void *new;
        !           165:        size_t newlen;
        !           166: };
        !           167: int
        !           168: __sysctl(p, uap, retval)
        !           169:        struct proc *p;
        !           170:        register struct __sysctl_args *uap;
        !           171:        register_t *retval;
        !           172: {
        !           173:        int error, dolock = 1;
        !           174:        size_t savelen, oldlen = 0;
        !           175:        sysctlfn *fn;
        !           176:        int name[CTL_MAXNAME];
        !           177:        int i;
        !           178: 
        !           179:        if (uap->new != NULL &&
        !           180:            (error = suser(p->p_ucred, &p->p_acflag)))
        !           181:                return (error);
        !           182:        /*
        !           183:         * all top-level sysctl names are non-terminal
        !           184:         */
        !           185:        if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
        !           186:                return (EINVAL);
        !           187:        if (error =
        !           188:            copyin(uap->name, &name, uap->namelen * sizeof(int)))
        !           189:                return (error);
        !           190: 
        !           191:        switch (name[0]) {
        !           192:        case CTL_KERN:
        !           193:                fn = kern_sysctl;
        !           194:                if (name[2] != KERN_VNODE)      /* XXX */
        !           195:                        dolock = 0;
        !           196:                break;
        !           197:        case CTL_HW:
        !           198:                fn = hw_sysctl;
        !           199:                break;
        !           200:        case CTL_VM:
        !           201:                fn = vm_sysctl;
        !           202:                break;
        !           203:        case CTL_NET:
        !           204:                fn = net_sysctl;
        !           205:                break;
        !           206:        case CTL_VFS:
        !           207:                fn = vfs_sysctl;
        !           208:                break;
        !           209: #if FIXME  /* [ */
        !           210:        case CTL_MACHDEP:
        !           211:                fn = cpu_sysctl;
        !           212:                break;
        !           213: #endif  /* FIXME ] */
        !           214: #ifdef DEBUG
        !           215:        case CTL_DEBUG:
        !           216:                fn = debug_sysctl;
        !           217:                break;
        !           218: #endif
        !           219:        default:
        !           220:                fn = 0;
        !           221:        }
        !           222: 
        !           223:        if (uap->oldlenp &&
        !           224:            (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
        !           225:                return (error);
        !           226: 
        !           227:        if (uap->old != NULL) {
        !           228:                if (!useracc(uap->old, oldlen, B_WRITE))
        !           229:                        return (EFAULT);
        !           230:                while (memlock.sl_lock) {
        !           231:                        memlock.sl_want = 1;
        !           232:                        sleep((caddr_t)&memlock, PRIBIO+1);
        !           233:                        memlock.sl_locked++;
        !           234:                }
        !           235:                memlock.sl_lock = 1;
        !           236:                if (dolock)
        !           237:                        vslock(uap->old, oldlen);
        !           238:                savelen = oldlen;
        !           239:        }
        !           240: 
        !           241:        if (fn)
        !           242:            error = (*fn)(name + 1, uap->namelen - 1, uap->old,
        !           243:                          &oldlen, uap->new, uap->newlen, p);
        !           244:        else
        !           245:            error = 1;
        !           246: 
        !           247:        if (error)
        !           248:                error = userland_sysctl(p, name, uap->namelen,
        !           249:                                        uap->old, uap->oldlenp, 0,
        !           250:                                        uap->new, uap->newlen, &oldlen);
        !           251: 
        !           252:        if (uap->old != NULL) {
        !           253:                if (dolock)
        !           254:                        vsunlock(uap->old, savelen, B_WRITE);
        !           255:                memlock.sl_lock = 0;
        !           256:                if (memlock.sl_want) {
        !           257:                        memlock.sl_want = 0;
        !           258:                        wakeup((caddr_t)&memlock);
        !           259:                }
        !           260:        }
        !           261:        if ((error) && (error != ENOMEM))
        !           262:                return (error);
        !           263: 
        !           264:        if (uap->oldlenp) {
        !           265:                i = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
        !           266:                if (i) 
        !           267:                    return i;
        !           268:        }
        !           269: 
        !           270:        return (error);
        !           271: }
        !           272: 
        !           273: /*
        !           274:  * Attributes stored in the kernel.
        !           275:  */
        !           276: extern char hostname[MAXHOSTNAMELEN]; /* defined in bsd/kern/init_main.c */
        !           277: extern int hostnamelen;
        !           278: extern char domainname[MAXHOSTNAMELEN];
        !           279: extern int domainnamelen;
        !           280: extern long hostid;
        !           281: #ifdef INSECURE
        !           282: int securelevel = -1;
        !           283: #else
        !           284: int securelevel;
        !           285: #endif
        !           286: 
        !           287: int get_kernel_symfile( struct proc *p, char **symfile );
        !           288: 
        !           289: /*
        !           290:  * kernel related system variables.
        !           291:  */
        !           292: kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           293:        int *name;
        !           294:        u_int namelen;
        !           295:        void *oldp;
        !           296:        size_t *oldlenp;
        !           297:        void *newp;
        !           298:        size_t newlen;
        !           299:        struct proc *p;
        !           300: {
        !           301:        int error, level, inthostid;
        !           302:        unsigned int oldval=0;
        !           303:        extern char ostype[], osrelease[], version[];
        !           304: 
        !           305:        /* all sysctl names at this level are terminal */
        !           306:        if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 
        !           307:                || name[0] == KERN_KDEBUG
        !           308:                || name[0] == KERN_PROCARGS
        !           309:                 || name[0] == KERN_PCSAMPLES
        !           310:        ))
        !           311:                return (ENOTDIR);               /* overloaded */
        !           312: 
        !           313:        switch (name[0]) {
        !           314:        case KERN_OSTYPE:
        !           315:                return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
        !           316:        case KERN_OSRELEASE:
        !           317:                return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
        !           318:        case KERN_OSREV:
        !           319:                return (sysctl_rdint(oldp, oldlenp, newp, BSD));
        !           320:        case KERN_VERSION:
        !           321:                return (sysctl_rdstring(oldp, oldlenp, newp, version));
        !           322:        case KERN_MAXVNODES:
        !           323:                oldval = desiredvnodes;
        !           324:                error = sysctl_int(oldp, oldlenp, newp, 
        !           325:                                newlen, &desiredvnodes);
        !           326:                reset_vmobjectcache(oldval, desiredvnodes);
        !           327:                return(error);
        !           328:        case KERN_MAXPROC:
        !           329:                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
        !           330:        case KERN_MAXFILES:
        !           331:                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
        !           332:        case KERN_ARGMAX:
        !           333:                return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
        !           334:        case KERN_SECURELVL:
        !           335:                level = securelevel;
        !           336:                if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
        !           337:                    newp == NULL)
        !           338:                        return (error);
        !           339:                if (level < securelevel && p->p_pid != 1)
        !           340:                        return (EPERM);
        !           341:                securelevel = level;
        !           342:                return (0);
        !           343:        case KERN_HOSTNAME:
        !           344:                error = sysctl_string(oldp, oldlenp, newp, newlen,
        !           345:                    hostname, sizeof(hostname));
        !           346:                if (newp && !error)
        !           347:                        hostnamelen = newlen;
        !           348:                return (error);
        !           349:        case KERN_DOMAINNAME:
        !           350:                error = sysctl_string(oldp, oldlenp, newp, newlen,
        !           351:                    domainname, sizeof(domainname));
        !           352:                if (newp && !error)
        !           353:                        domainnamelen = newlen;
        !           354:                return (error);
        !           355:        case KERN_HOSTID:
        !           356:                inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
        !           357:                error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
        !           358:                hostid = inthostid;
        !           359:                return (error);
        !           360:        case KERN_CLOCKRATE:
        !           361:                return (sysctl_clockrate(oldp, oldlenp));
        !           362: #if FIXME  /* [ */
        !           363:        case KERN_BOOTTIME:
        !           364:                return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
        !           365:                    sizeof(struct timeval)));
        !           366: #endif  /* FIXME ] */
        !           367:        case KERN_VNODE:
        !           368:                return (sysctl_vnode(oldp, oldlenp));
        !           369:        case KERN_PROC:
        !           370:                return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
        !           371:        case KERN_FILE:
        !           372:                return (sysctl_file(oldp, oldlenp));
        !           373: #ifdef GPROF
        !           374:        case KERN_PROF:
        !           375:                return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
        !           376:                    newp, newlen));
        !           377: #endif
        !           378:        case KERN_POSIX1:
        !           379:                return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
        !           380:        case KERN_NGROUPS:
        !           381:                return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
        !           382:        case KERN_JOB_CONTROL:
        !           383:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
        !           384:        case KERN_SAVED_IDS:
        !           385: #ifdef _POSIX_SAVED_IDS
        !           386:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
        !           387: #else
        !           388:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
        !           389: #endif
        !           390: #if FIXME  /* [ */
        !           391:        case KERN_MAXPARTITIONS:
        !           392:                return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
        !           393: #endif  /* FIXME ] */
        !           394:        case KERN_KDEBUG:
        !           395:                return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
        !           396:        case KERN_PCSAMPLES:
        !           397:                return (pcsamples_control(name+1, namelen-1, oldp, oldlenp));
        !           398:        case KERN_PROCARGS:
        !           399:                /* new one as it does not use kinfo_proc */
        !           400:                return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp));
        !           401:         case KERN_SYMFILE:
        !           402:                 {
        !           403:                     char *str;
        !           404:                     error = get_kernel_symfile( p, &str );
        !           405:                     if ( error ) return error;
        !           406:                     return (sysctl_rdstring(oldp, oldlenp, newp, str));
        !           407:                 }    
        !           408:        default:
        !           409:                return (EOPNOTSUPP);
        !           410:        }
        !           411:        /* NOTREACHED */
        !           412: }
        !           413: 
        !           414: /*
        !           415:  * hardware related system variables.
        !           416:  */
        !           417: hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           418:        int *name;
        !           419:        u_int namelen;
        !           420:        void *oldp;
        !           421:        size_t *oldlenp;
        !           422:        void *newp;
        !           423:        size_t newlen;
        !           424:        struct proc *p;
        !           425: {
        !           426:        char dummy[65];
        !           427:        int  epochTemp;
        !           428:        extern int vm_page_wire_count;
        !           429: 
        !           430: 
        !           431:        /* all sysctl names at this level are terminal */
        !           432:        if (namelen != 1)
        !           433:                return (ENOTDIR);               /* overloaded */
        !           434: 
        !           435:        switch (name[0]) {
        !           436:        case HW_MACHINE:
        !           437:                if(!PEGetMachineName(dummy,64))
        !           438:                        return(EINVAL);
        !           439:                return (sysctl_rdstring(oldp, oldlenp, newp, dummy));
        !           440:        case HW_MODEL:
        !           441:                if(!PEGetModelName(dummy,64))
        !           442:                        return(EINVAL);
        !           443:                return (sysctl_rdstring(oldp, oldlenp, newp, dummy));
        !           444:        case HW_NCPU:
        !           445:                return (sysctl_rdint(oldp, oldlenp, newp, 1));  /* XXX */
        !           446:        case HW_BYTEORDER:
        !           447:                return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
        !           448:        case HW_PHYSMEM:
        !           449:                return (sysctl_rdint(oldp, oldlenp, newp, mem_size));
        !           450:        case HW_USERMEM:
        !           451:                return (sysctl_rdint(oldp, oldlenp, newp,
        !           452:                    (mem_size - vm_page_wire_count * page_size)));
        !           453:        case HW_PAGESIZE:
        !           454:                return (sysctl_rdint(oldp, oldlenp, newp, page_size));
        !           455:        case HW_EPOCH:
        !           456:                epochTemp = PEGetPlatformEpoch();
        !           457:                if (epochTemp == -1) return(EINVAL);
        !           458:                return (sysctl_rdint(oldp, oldlenp, newp, epochTemp));
        !           459:        default:
        !           460:                return (EOPNOTSUPP);
        !           461:        }
        !           462: }
        !           463: 
        !           464: #ifdef DEBUG
        !           465: /*
        !           466:  * Debugging related system variables.
        !           467:  */
        !           468: #if DIAGNOSTIC
        !           469: extern
        !           470: #endif /* DIAGNOSTIC */
        !           471: struct ctldebug debug0, debug1;
        !           472: struct ctldebug debug2, debug3, debug4;
        !           473: struct ctldebug debug5, debug6, debug7, debug8, debug9;
        !           474: struct ctldebug debug10, debug11, debug12, debug13, debug14;
        !           475: struct ctldebug debug15, debug16, debug17, debug18, debug19;
        !           476: static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
        !           477:        &debug0, &debug1, &debug2, &debug3, &debug4,
        !           478:        &debug5, &debug6, &debug7, &debug8, &debug9,
        !           479:        &debug10, &debug11, &debug12, &debug13, &debug14,
        !           480:        &debug15, &debug16, &debug17, &debug18, &debug19,
        !           481: };
        !           482: int
        !           483: debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
        !           484:        int *name;
        !           485:        u_int namelen;
        !           486:        void *oldp;
        !           487:        size_t *oldlenp;
        !           488:        void *newp;
        !           489:        size_t newlen;
        !           490:        struct proc *p;
        !           491: {
        !           492:        struct ctldebug *cdp;
        !           493: 
        !           494:        /* all sysctl names at this level are name and field */
        !           495:        if (namelen != 2)
        !           496:                return (ENOTDIR);               /* overloaded */
        !           497:        cdp = debugvars[name[0]];
        !           498:        if (cdp->debugname == 0)
        !           499:                return (EOPNOTSUPP);
        !           500:        switch (name[1]) {
        !           501:        case CTL_DEBUG_NAME:
        !           502:                return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
        !           503:        case CTL_DEBUG_VALUE:
        !           504:                return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
        !           505:        default:
        !           506:                return (EOPNOTSUPP);
        !           507:        }
        !           508:        /* NOTREACHED */
        !           509: }
        !           510: #endif /* DEBUG */
        !           511: 
        !           512: /*
        !           513:  * Validate parameters and get old / set new parameters
        !           514:  * for an integer-valued sysctl function.
        !           515:  */
        !           516: sysctl_int(oldp, oldlenp, newp, newlen, valp)
        !           517:        void *oldp;
        !           518:        size_t *oldlenp;
        !           519:        void *newp;
        !           520:        size_t newlen;
        !           521:        int *valp;
        !           522: {
        !           523:        int error = 0;
        !           524: 
        !           525:        if (oldp && *oldlenp < sizeof(int))
        !           526:                return (ENOMEM);
        !           527:        if (newp && newlen != sizeof(int))
        !           528:                return (EINVAL);
        !           529:        *oldlenp = sizeof(int);
        !           530:        if (oldp)
        !           531:                error = copyout(valp, oldp, sizeof(int));
        !           532:        if (error == 0 && newp)
        !           533:                error = copyin(newp, valp, sizeof(int));
        !           534:        return (error);
        !           535: }
        !           536: 
        !           537: /*
        !           538:  * As above, but read-only.
        !           539:  */
        !           540: sysctl_rdint(oldp, oldlenp, newp, val)
        !           541:        void *oldp;
        !           542:        size_t *oldlenp;
        !           543:        void *newp;
        !           544:        int val;
        !           545: {
        !           546:        int error = 0;
        !           547: 
        !           548:        if (oldp && *oldlenp < sizeof(int))
        !           549:                return (ENOMEM);
        !           550:        if (newp)
        !           551:                return (EPERM);
        !           552:        *oldlenp = sizeof(int);
        !           553:        if (oldp)
        !           554:                error = copyout((caddr_t)&val, oldp, sizeof(int));
        !           555:        return (error);
        !           556: }
        !           557: 
        !           558: /*
        !           559:  * Validate parameters and get old / set new parameters
        !           560:  * for a string-valued sysctl function.
        !           561:  */
        !           562: sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
        !           563:        void *oldp;
        !           564:        size_t *oldlenp;
        !           565:        void *newp;
        !           566:        size_t newlen;
        !           567:        char *str;
        !           568:        int maxlen;
        !           569: {
        !           570:        int len, error = 0;
        !           571: 
        !           572:        len = strlen(str) + 1;
        !           573:        if (oldp && *oldlenp < len)
        !           574:                return (ENOMEM);
        !           575:        if (newp && newlen >= maxlen)
        !           576:                return (EINVAL);
        !           577:        if (oldp) {
        !           578:                *oldlenp = len;
        !           579:                error = copyout(str, oldp, len);
        !           580:        }
        !           581:        if (error == 0 && newp) {
        !           582:                error = copyin(newp, str, newlen);
        !           583:                str[newlen] = 0;
        !           584:        }
        !           585:        return (error);
        !           586: }
        !           587: 
        !           588: /*
        !           589:  * As above, but read-only.
        !           590:  */
        !           591: sysctl_rdstring(oldp, oldlenp, newp, str)
        !           592:        void *oldp;
        !           593:        size_t *oldlenp;
        !           594:        void *newp;
        !           595:        char *str;
        !           596: {
        !           597:        int len, error = 0;
        !           598: 
        !           599:        len = strlen(str) + 1;
        !           600:        if (oldp && *oldlenp < len)
        !           601:                return (ENOMEM);
        !           602:        if (newp)
        !           603:                return (EPERM);
        !           604:        *oldlenp = len;
        !           605:        if (oldp)
        !           606:                error = copyout(str, oldp, len);
        !           607:        return (error);
        !           608: }
        !           609: 
        !           610: /*
        !           611:  * Validate parameters and get old / set new parameters
        !           612:  * for a structure oriented sysctl function.
        !           613:  */
        !           614: sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
        !           615:        void *oldp;
        !           616:        size_t *oldlenp;
        !           617:        void *newp;
        !           618:        size_t newlen;
        !           619:        void *sp;
        !           620:        int len;
        !           621: {
        !           622:        int error = 0;
        !           623: 
        !           624:        if (oldp && *oldlenp < len)
        !           625:                return (ENOMEM);
        !           626:        if (newp && newlen > len)
        !           627:                return (EINVAL);
        !           628:        if (oldp) {
        !           629:                *oldlenp = len;
        !           630:                error = copyout(sp, oldp, len);
        !           631:        }
        !           632:        if (error == 0 && newp)
        !           633:                error = copyin(newp, sp, len);
        !           634:        return (error);
        !           635: }
        !           636: 
        !           637: /*
        !           638:  * Validate parameters and get old parameters
        !           639:  * for a structure oriented sysctl function.
        !           640:  */
        !           641: sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
        !           642:        void *oldp;
        !           643:        size_t *oldlenp;
        !           644:        void *newp, *sp;
        !           645:        int len;
        !           646: {
        !           647:        int error = 0;
        !           648: 
        !           649:        if (oldp && *oldlenp < len)
        !           650:                return (ENOMEM);
        !           651:        if (newp)
        !           652:                return (EPERM);
        !           653:        *oldlenp = len;
        !           654:        if (oldp)
        !           655:                error = copyout(sp, oldp, len);
        !           656:        return (error);
        !           657: }
        !           658: 
        !           659: /*
        !           660:  * Get file structures.
        !           661:  */
        !           662: sysctl_file(where, sizep)
        !           663:        char *where;
        !           664:        size_t *sizep;
        !           665: {
        !           666:        int buflen, error;
        !           667:        struct file *fp;
        !           668:        char *start = where;
        !           669: 
        !           670:        buflen = *sizep;
        !           671:        if (where == NULL) {
        !           672:                /*
        !           673:                 * overestimate by 10 files
        !           674:                 */
        !           675:                *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
        !           676:                return (0);
        !           677:        }
        !           678: 
        !           679:        /*
        !           680:         * first copyout filehead
        !           681:         */
        !           682:        if (buflen < sizeof(filehead)) {
        !           683:                *sizep = 0;
        !           684:                return (0);
        !           685:        }
        !           686:        if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
        !           687:                return (error);
        !           688:        buflen -= sizeof(filehead);
        !           689:        where += sizeof(filehead);
        !           690: 
        !           691:        /*
        !           692:         * followed by an array of file structures
        !           693:         */
        !           694:        for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
        !           695:                if (buflen < sizeof(struct file)) {
        !           696:                        *sizep = where - start;
        !           697:                        return (ENOMEM);
        !           698:                }
        !           699:                if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
        !           700:                        return (error);
        !           701:                buflen -= sizeof(struct file);
        !           702:                where += sizeof(struct file);
        !           703:        }
        !           704:        *sizep = where - start;
        !           705:        return (0);
        !           706: }
        !           707: 
        !           708: /*
        !           709:  * try over estimating by 5 procs
        !           710:  */
        !           711: #define KERN_PROCSLOP  (5 * sizeof (struct kinfo_proc))
        !           712: 
        !           713: sysctl_doproc(name, namelen, where, sizep)
        !           714:        int *name;
        !           715:        u_int namelen;
        !           716:        char *where;
        !           717:        size_t *sizep;
        !           718: {
        !           719:        register struct proc *p;
        !           720:        register struct kinfo_proc *dp = (struct kinfo_proc *)where;
        !           721:        register int needed = 0;
        !           722:        int buflen = where != NULL ? *sizep : 0;
        !           723:        int doingzomb;
        !           724:        struct kinfo_proc kproc;
        !           725:        int error = 0;
        !           726: 
        !           727:        if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
        !           728:                return (EINVAL);
        !           729:        p = allproc.lh_first;
        !           730:        doingzomb = 0;
        !           731: again:
        !           732:        for (; p != 0; p = p->p_list.le_next) {
        !           733:                /*
        !           734:                 * Skip embryonic processes.
        !           735:                 */
        !           736:                if (p->p_stat == SIDL)
        !           737:                        continue;
        !           738:                /*
        !           739:                 * TODO - make more efficient (see notes below).
        !           740:                 * do by session.
        !           741:                 */
        !           742:                switch (name[0]) {
        !           743: 
        !           744:                case KERN_PROC_PID:
        !           745:                        /* could do this with just a lookup */
        !           746:                        if (p->p_pid != (pid_t)name[1])
        !           747:                                continue;
        !           748:                        break;
        !           749: 
        !           750:                case KERN_PROC_PGRP:
        !           751:                        /* could do this by traversing pgrp */
        !           752:                        if (p->p_pgrp->pg_id != (pid_t)name[1])
        !           753:                                continue;
        !           754:                        break;
        !           755: 
        !           756:                case KERN_PROC_TTY:
        !           757:                        if ((p->p_flag & P_CONTROLT) == 0 ||
        !           758:                            p->p_session->s_ttyp == NULL ||
        !           759:                            p->p_session->s_ttyp->t_dev != (dev_t)name[1])
        !           760:                                continue;
        !           761:                        break;
        !           762: 
        !           763:                case KERN_PROC_UID:
        !           764:                        if (p->p_ucred->cr_uid != (uid_t)name[1])
        !           765:                                continue;
        !           766:                        break;
        !           767: 
        !           768:                case KERN_PROC_RUID:
        !           769:                        if (p->p_cred->p_ruid != (uid_t)name[1])
        !           770:                                continue;
        !           771:                        break;
        !           772:                }
        !           773:                if (buflen >= sizeof(struct kinfo_proc)) {
        !           774:                        fill_proc(p, &kproc);
        !           775:                        if (error = copyout((caddr_t)&kproc, &dp->kp_proc,
        !           776:                            sizeof(struct kinfo_proc)))
        !           777:                                return (error);
        !           778:                        dp++;
        !           779:                        buflen -= sizeof(struct kinfo_proc);
        !           780:                }
        !           781:                needed += sizeof(struct kinfo_proc);
        !           782:        }
        !           783:        if (doingzomb == 0) {
        !           784:                p = zombproc.lh_first;
        !           785:                doingzomb++;
        !           786:                goto again;
        !           787:        }
        !           788:        if (where != NULL) {
        !           789:                *sizep = (caddr_t)dp - where;
        !           790:                if (needed > *sizep)
        !           791:                        return (ENOMEM);
        !           792:        } else {
        !           793:                needed += KERN_PROCSLOP;
        !           794:                *sizep = needed;
        !           795:        }
        !           796:        return (0);
        !           797: }
        !           798: 
        !           799: void
        !           800: fill_proc(p,kp)
        !           801:        register struct proc *p;
        !           802:        register struct kinfo_proc *kp;
        !           803: {
        !           804:        fill_externproc(p, &kp->kp_proc);
        !           805:        fill_eproc(p, &kp->kp_eproc);
        !           806: }
        !           807: /*
        !           808:  * Fill in an eproc structure for the specified process.
        !           809:  */
        !           810: void
        !           811: fill_eproc(p, ep)
        !           812:        register struct proc *p;
        !           813:        register struct eproc *ep;
        !           814: {
        !           815:        register struct tty *tp;
        !           816: 
        !           817:        ep->e_paddr = p;
        !           818:        ep->e_sess = p->p_pgrp->pg_session;
        !           819:        ep->e_pcred = *p->p_cred;
        !           820:        ep->e_ucred = *p->p_ucred;
        !           821:        if (p->p_stat == SIDL || p->p_stat == SZOMB) {
        !           822:                ep->e_vm.vm_rssize = 0;
        !           823:                ep->e_vm.vm_tsize = 0;
        !           824:                ep->e_vm.vm_dsize = 0;
        !           825:                ep->e_vm.vm_ssize = 0;
        !           826:                /* ep->e_vm.vm_pmap = XXX; */
        !           827:        } else {
        !           828: #if FIXME  /* [ */
        !           829:                register vm_map_t vm = ((task_t)p->task)->map;
        !           830: 
        !           831:                ep->e_vm.vm_rssize = pmap_resident_count(vm->pmap); /*XXX*/
        !           832: //             ep->e_vm.vm_tsize = vm->vm_tsize;
        !           833: //             ep->e_vm.vm_dsize = vm->vm_dsize;
        !           834: //             ep->e_vm.vm_ssize = vm->vm_ssize;
        !           835: #else  /* FIXME ][ */
        !           836:                ep->e_vm.vm_rssize = 0; /*XXX*/
        !           837: #endif  /* FIXME ] */
        !           838:        }
        !           839:        if (p->p_pptr)
        !           840:                ep->e_ppid = p->p_pptr->p_pid;
        !           841:        else
        !           842:                ep->e_ppid = 0;
        !           843:        ep->e_pgid = p->p_pgrp->pg_id;
        !           844:        ep->e_jobc = p->p_pgrp->pg_jobc;
        !           845:        if ((p->p_flag & P_CONTROLT) &&
        !           846:             (tp = ep->e_sess->s_ttyp)) {
        !           847:                ep->e_tdev = tp->t_dev;
        !           848:                ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
        !           849:                ep->e_tsess = tp->t_session;
        !           850:        } else
        !           851:                ep->e_tdev = NODEV;
        !           852:        ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
        !           853:        if (SESS_LEADER(p))
        !           854:                ep->e_flag |= EPROC_SLEADER;
        !           855:        if (p->p_wmesg)
        !           856:                strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
        !           857:        ep->e_xsize = ep->e_xrssize = 0;
        !           858:        ep->e_xccount = ep->e_xswrss = 0;
        !           859: }
        !           860: /*
        !           861:  * Fill in an eproc structure for the specified process.
        !           862:  */
        !           863: void
        !           864: fill_externproc(p, exp)
        !           865:        register struct proc *p;
        !           866:        register struct extern_proc *exp;
        !           867: {
        !           868:        exp->p_forw = exp->p_back = NULL;
        !           869:        exp->p_vmspace = NULL;
        !           870:        exp->p_sigacts = p->p_sigacts;
        !           871:        exp->p_flag  = p->p_flag;
        !           872:        exp->p_stat  = p->p_stat ;
        !           873:        exp->p_pid  = p->p_pid ;
        !           874:        exp->p_oppid  = p->p_oppid ;
        !           875:        exp->p_dupfd  = p->p_dupfd ;
        !           876:        /* Mach related  */
        !           877:        exp->user_stack  = p->user_stack ;
        !           878:        exp->exit_thread  = p->exit_thread ;
        !           879:        exp->p_debugger  = p->p_debugger ;
        !           880:        exp->sigwait  = p->sigwait ;
        !           881:        /* scheduling */
        !           882:        exp->p_estcpu  = p->p_estcpu ;
        !           883:        exp->p_cpticks  = p->p_cpticks ;
        !           884:        exp->p_pctcpu  = p->p_pctcpu ;
        !           885:        exp->p_wchan  = p->p_wchan ;
        !           886:        exp->p_wmesg  = p->p_wmesg ;
        !           887:        exp->p_swtime  = p->p_swtime ;
        !           888:        exp->p_slptime  = p->p_slptime ;
        !           889:        bcopy(&p->p_realtimer, &exp->p_realtimer,sizeof(struct itimerval));
        !           890:        bcopy(&p->p_rtime, &exp->p_rtime,sizeof(struct timeval));
        !           891:        exp->p_uticks  = p->p_uticks ;
        !           892:        exp->p_sticks  = p->p_sticks ;
        !           893:        exp->p_iticks  = p->p_iticks ;
        !           894:        exp->p_traceflag  = p->p_traceflag ;
        !           895:        exp->p_tracep  = p->p_tracep ;
        !           896:        exp->p_siglist  = p->p_siglist ;
        !           897:        exp->p_textvp  = p->p_textvp ;
        !           898:        exp->p_holdcnt = 0 ;
        !           899:        exp->p_sigmask  = p->p_sigmask ;
        !           900:        exp->p_sigignore  = p->p_sigignore ;
        !           901:        exp->p_sigcatch  = p->p_sigcatch ;
        !           902:        exp->p_priority  = p->p_priority ;
        !           903:        exp->p_usrpri  = p->p_usrpri ;
        !           904:        exp->p_nice  = p->p_nice ;
        !           905:        bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
        !           906:        exp->p_comm[MAXCOMLEN] = '\0';
        !           907:        exp->p_pgrp  = p->p_pgrp ;
        !           908:        exp->p_addr  = NULL;
        !           909:        exp->p_xstat  = p->p_xstat ;
        !           910:        exp->p_acflag  = p->p_acflag ;
        !           911:        exp->p_ru  = p->p_ru ;
        !           912: }
        !           913: 
        !           914: kdebug_ops(name, namelen, where, sizep, p)
        !           915: int *name;
        !           916: u_int namelen;
        !           917: char *where;
        !           918: size_t *sizep;
        !           919: struct proc *p;
        !           920: {
        !           921: int size=*sizep;
        !           922: int ret=0;
        !           923: extern int kdbg_control(int *name, u_int namelen, char * where,size_t * sizep);
        !           924: 
        !           925:        switch(name[0]) {
        !           926:        case KERN_KDEFLAGS:
        !           927:        case KERN_KDDFLAGS:
        !           928:        case KERN_KDENABLE:
        !           929:        case KERN_KDGETBUF:
        !           930:        case KERN_KDSETUP:
        !           931:        case KERN_KDREMOVE:
        !           932:        case KERN_KDSETREG:
        !           933:        case KERN_KDGETREG:
        !           934:        case KERN_KDREADTR:
        !           935:        case KERN_KDPIDTR:
        !           936:        case KERN_KDTHRMAP:
        !           937:        case KERN_KDPIDEX:
        !           938:                ret = kdbg_control(name, namelen, where, sizep);
        !           939:                break;
        !           940:        case KERN_KDSETRTCDEC:
        !           941:        case KERN_KDSETBUF:
        !           942:                if (ret = suser(p->p_ucred, &p->p_acflag))
        !           943:                    return(ret);
        !           944:                else
        !           945:                    ret = kdbg_control(name, namelen, where, sizep);
        !           946:                break;
        !           947:        default:
        !           948:                ret= EOPNOTSUPP;
        !           949:                break;
        !           950:        }
        !           951:        return(ret);
        !           952: }
        !           953: 
        !           954: /*
        !           955:  * try over estimating by 5 procs
        !           956:  */
        !           957: #define KERN_PROCSLOP  (5 * sizeof (struct kinfo_proc))
        !           958: 
        !           959: sysctl_procargs(name, namelen, where, sizep)
        !           960:        int *name;
        !           961:        u_int namelen;
        !           962:        char *where;
        !           963:        size_t *sizep;
        !           964: {
        !           965:        register struct proc *p;
        !           966:        register int needed = 0;
        !           967:        int buflen = where != NULL ? *sizep : 0;
        !           968:        int error = 0;
        !           969:        struct vm_map *proc_map;
        !           970:        struct task * task;
        !           971:        vm_map_copy_t   tmp;
        !           972:        vm_offset_t     arg_addr;
        !           973:        vm_size_t       arg_size;
        !           974:        caddr_t data;
        !           975:        unsigned size;
        !           976:        vm_offset_t     copy_start, copy_end;
        !           977:        vm_offset_t     dealloc_start;  /* area to remove from kernel map */
        !           978:        vm_offset_t     dealloc_end;
        !           979:        int             *ip;
        !           980:        kern_return_t ret;
        !           981:        int pid;
        !           982: 
        !           983: 
        !           984:        pid = name[0];
        !           985: 
        !           986:        p = pfind(pid);
        !           987:        if (p == NULL) {
        !           988:                return(EINVAL);
        !           989:        }
        !           990: 
        !           991:        if (p->task == NULL)
        !           992:                return(EINVAL);
        !           993:        
        !           994:        arg_size = buflen;
        !           995:        /*
        !           996:        *       Returns the top N bytes of the user stack, with
        !           997:        *       everything below the first argument character
        !           998:        *       zeroed for security reasons.
        !           999:        *       Odd data structure is for compatibility.
        !          1000:        */
        !          1001:        /*
        !          1002:         *      Lookup process by pid
        !          1003:         */
        !          1004:        /*
        !          1005:        *       Get map for process
        !          1006:        */
        !          1007:        proc_map = get_task_map((task_t)p->task);
        !          1008: 
        !          1009:        /*
        !          1010:         *      Copy the top N bytes of the stack.
        !          1011:         *      On all machines we have so far, the stack grows
        !          1012:         *      downwards.
        !          1013:         *
        !          1014:         *      If the user expects no more than N bytes of
        !          1015:         *      argument list, use that as a guess for the
        !          1016:         *      size.
        !          1017:         */
        !          1018: 
        !          1019:        if (buflen == 0) {
        !          1020:                return(EINVAL);
        !          1021:        }
        !          1022: 
        !          1023:        if (!p->user_stack)
        !          1024:                return(EINVAL);
        !          1025: 
        !          1026: #if    STACK_GROWTH_UP
        !          1027:        arg_addr = p->user_stack;
        !          1028: #else  STACK_GROWTH_UP
        !          1029:        arg_addr = p->user_stack - arg_size;
        !          1030: #endif /* STACK_GROWTH_UP */
        !          1031: 
        !          1032:        /*
        !          1033:         *      Before we can block (any VM code), make another
        !          1034:         *      reference to the map to keep it alive.
        !          1035:         */
        !          1036: 
        !          1037:        ret = kmem_alloc_pageable(bsd_pageable_map, &copy_start,
        !          1038:                                        round_page(arg_size));
        !          1039:        if (ret != KERN_SUCCESS) 
        !          1040:                return(ENOMEM);
        !          1041: 
        !          1042:        copy_end = round_page(copy_start + arg_size);
        !          1043: 
        !          1044:        /* vm_map_reference(proc_map); */
        !          1045: 
        !          1046:        if( vm_map_copyin(proc_map, trunc_page(arg_addr), round_page(arg_size), 
        !          1047:                        FALSE, &tmp) != KERN_SUCCESS) {
        !          1048:                        kmem_free(bsd_pageable_map, copy_start,
        !          1049:                                        round_page(arg_size));
        !          1050:                        /* vm_map_deallocate(proc_map); */
        !          1051:                        return (EIO);
        !          1052:        }
        !          1053:        if( vm_map_copy_overwrite(bsd_pageable_map, copy_start, 
        !          1054:                tmp, FALSE) != KERN_SUCCESS) {
        !          1055:                        kmem_free(bsd_pageable_map, copy_start,
        !          1056:                                        round_page(arg_size));
        !          1057:                        /* vm_map_deallocate(proc_map); */
        !          1058:                        return (EIO);
        !          1059:        }
        !          1060: 
        !          1061:        /*
        !          1062:        *       Now that we've done the copy, we can release
        !          1063:        *       the process' map.
        !          1064:        */
        !          1065:        /* vm_map_deallocate(proc_map); */
        !          1066:                        
        !          1067: #if    STACK_GROWTH_UP
        !          1068:        data = (caddr_t)copy_start;
        !          1069:        ip = (int *) ((*(int *)copy_start) - arg_addr + data);
        !          1070:        /*
        !          1071:         * sanity check ip since it comes from user-accessible
        !          1072:         * stack area
        !          1073:         */
        !          1074:        if (((vm_offset_t)ip > copy_end) ||
        !          1075:                        ((vm_offset_t)ip < copy_start))
        !          1076:                                ip = (int *)copy_end;
        !          1077:        /*
        !          1078:         * relocate so that end of string area is at end
        !          1079:         * of buffer.
        !          1080:         */
        !          1081:        size = (unsigned) ((int)ip - (int)copy_start);
        !          1082:        data = (caddr_t)(copy_end - size);
        !          1083:        bcopy(copy_start, data, size);
        !          1084:        /*
        !          1085:         * now find beginning of string area so we can
        !          1086:         * clear out data user should not see
        !          1087:         */
        !          1088:        ip = (int *)copy_end;   // start at new end
        !          1089:        ip -= 2; /*skip trailing 0 word and assume at least one
        !          1090:                  argument.  The last word of argN may be just
        !          1091:                  the trailing 0, in which case we'd stop
        !          1092:                  there */
        !          1093:        while (*--ip)
        !          1094:                if (ip == (int *)data)
        !          1095:                                break;                  
        !          1096:        bzero(copy_start,
        !          1097:                (unsigned) ((int)ip - (int)copy_start));
        !          1098:        /*
        !          1099:         * now prepare data/size for the copy's out of the
        !          1100:         * switch.  We copy the last arg_size bytes from
        !          1101:         * our data.
        !          1102:         */
        !          1103:        size = arg_size;
        !          1104:        data = (caddr_t)(copy_end - size);
        !          1105: #else  STACK_GROWTH_UP
        !          1106:        data = (caddr_t) (copy_end - arg_size);
        !          1107:        ip = (int *) copy_end;          
        !          1108:        size = arg_size;
        !          1109: 
        !          1110:        /*
        !          1111:         *      Now look down the stack for the bottom of the
        !          1112:         *      argument list.  Since this call is otherwise
        !          1113:         *      unprotected, we can't let the nosy user see
        !          1114:         *      anything else on the stack.
        !          1115:         *
        !          1116:         *      The arguments are pushed on the stack by
        !          1117:         *      execve() as:
        !          1118:         *
        !          1119:         *              .long   0
        !          1120:         *              arg 0   (null-terminated)
        !          1121:         *              arg 1
        !          1122:         *              ...
        !          1123:         *              arg N
        !          1124:         *              .long   0
        !          1125:         *
        !          1126:         */
        !          1127: 
        !          1128:        ip -= 2; /*skip trailing 0 word and assume at least one
        !          1129:                  argument.  The last word of argN may be just
        !          1130:                  the trailing 0, in which case we'd stop
        !          1131:                  there */
        !          1132:        while (*--ip)
        !          1133:                if (ip == (int *)data)
        !          1134:                        break;                  
        !          1135:        bzero(data, (unsigned) ((int)ip - (int)data));
        !          1136: #endif /* STACK_GROWTH_UP */
        !          1137: 
        !          1138:        dealloc_start = copy_start;
        !          1139:        dealloc_end = copy_end;
        !          1140: 
        !          1141: 
        !          1142:        size = MIN(size, buflen);
        !          1143:        error = copyout(data, where, size);
        !          1144: 
        !          1145:        if (dealloc_start != (vm_offset_t) 0) {
        !          1146:                kmem_free(bsd_pageable_map, dealloc_start,
        !          1147:                        dealloc_end - dealloc_start);
        !          1148:        }
        !          1149:        if (error) {
        !          1150:                return(error);
        !          1151:        }
        !          1152: 
        !          1153:        if (where != NULL)
        !          1154:                *sizep = size;
        !          1155:        return (0);
        !          1156: }

unix.superglobalmegacorp.com

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