[BACK]Return to kern_sysctl.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_sysctl.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: kern_sysctl.c,v 1.155 2007/08/09 04:12:12 cnst Exp $  */
                      2: /*     $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $     */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1982, 1986, 1989, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * Mike Karels at Berkeley Software Design, Inc.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  *
                     35:  *     @(#)kern_sysctl.c       8.4 (Berkeley) 4/14/94
                     36:  */
                     37:
                     38: /*
                     39:  * sysctl system call.
                     40:  */
                     41:
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/malloc.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/resourcevar.h>
                     48: #include <sys/file.h>
                     49: #include <sys/vnode.h>
                     50: #include <sys/unistd.h>
                     51: #include <sys/buf.h>
                     52: #include <sys/ioctl.h>
                     53: #include <sys/tty.h>
                     54: #include <sys/disklabel.h>
                     55: #include <sys/disk.h>
                     56: #include <uvm/uvm_extern.h>
                     57: #include <sys/sysctl.h>
                     58: #include <sys/msgbuf.h>
                     59: #include <sys/dkstat.h>
                     60: #include <sys/vmmeter.h>
                     61: #include <sys/namei.h>
                     62: #include <sys/exec.h>
                     63: #include <sys/mbuf.h>
                     64: #include <sys/sensors.h>
                     65: #ifdef __HAVE_TIMECOUNTER
                     66: #include <sys/timetc.h>
                     67: #endif
                     68: #include <sys/evcount.h>
                     69:
                     70: #include <sys/mount.h>
                     71: #include <sys/syscallargs.h>
                     72: #include <dev/rndvar.h>
                     73:
                     74: #ifdef DDB
                     75: #include <ddb/db_var.h>
                     76: #endif
                     77:
                     78: #ifdef SYSVMSG
                     79: #include <sys/msg.h>
                     80: #endif
                     81: #ifdef SYSVSEM
                     82: #include <sys/sem.h>
                     83: #endif
                     84: #ifdef SYSVSHM
                     85: #include <sys/shm.h>
                     86: #endif
                     87:
                     88: #define        PTRTOINT64(_x)  ((u_int64_t)(u_long)(_x))
                     89:
                     90: extern struct forkstat forkstat;
                     91: extern struct nchstats nchstats;
                     92: extern int nselcoll, fscale;
                     93: extern struct disklist_head disklist;
                     94: extern fixpt_t ccpu;
                     95: extern  long numvnodes;
                     96:
                     97: extern void nmbclust_update(void);
                     98:
                     99: int sysctl_diskinit(int, struct proc *);
                    100: int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
                    101: int sysctl_intrcnt(int *, u_int, void *, size_t *);
                    102: int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
                    103: int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t);
                    104: int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t);
                    105:
                    106: int (*cpu_cpuspeed)(int *);
                    107: void (*cpu_setperf)(int);
                    108: int perflevel = 100;
                    109:
                    110: /*
                    111:  * Lock to avoid too many processes vslocking a large amount of memory
                    112:  * at the same time.
                    113:  */
                    114: struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk");
                    115: struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk");
                    116:
                    117: int
                    118: sys___sysctl(struct proc *p, void *v, register_t *retval)
                    119: {
                    120:        struct sys___sysctl_args /* {
                    121:                syscallarg(int *) name;
                    122:                syscallarg(u_int) namelen;
                    123:                syscallarg(void *) old;
                    124:                syscallarg(size_t *) oldlenp;
                    125:                syscallarg(void *) new;
                    126:                syscallarg(size_t) newlen;
                    127:        } */ *uap = v;
                    128:        int error, dolock = 1;
                    129:        size_t savelen = 0, oldlen = 0;
                    130:        sysctlfn *fn;
                    131:        int name[CTL_MAXNAME];
                    132:
                    133:        if (SCARG(uap, new) != NULL &&
                    134:            (error = suser(p, 0)))
                    135:                return (error);
                    136:        /*
                    137:         * all top-level sysctl names are non-terminal
                    138:         */
                    139:        if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
                    140:                return (EINVAL);
                    141:        error = copyin(SCARG(uap, name), name,
                    142:                       SCARG(uap, namelen) * sizeof(int));
                    143:        if (error)
                    144:                return (error);
                    145:
                    146:        switch (name[0]) {
                    147:        case CTL_KERN:
                    148:                fn = kern_sysctl;
                    149:                if (name[1] == KERN_VNODE)      /* XXX */
                    150:                        dolock = 0;
                    151:                break;
                    152:        case CTL_HW:
                    153:                fn = hw_sysctl;
                    154:                break;
                    155:        case CTL_VM:
                    156:                fn = uvm_sysctl;
                    157:                break;
                    158:        case CTL_NET:
                    159:                fn = net_sysctl;
                    160:                break;
                    161:        case CTL_FS:
                    162:                fn = fs_sysctl;
                    163:                break;
                    164:        case CTL_VFS:
                    165:                fn = vfs_sysctl;
                    166:                break;
                    167:        case CTL_MACHDEP:
                    168:                fn = cpu_sysctl;
                    169:                break;
                    170: #ifdef DEBUG
                    171:        case CTL_DEBUG:
                    172:                fn = debug_sysctl;
                    173:                break;
                    174: #endif
                    175: #ifdef DDB
                    176:        case CTL_DDB:
                    177:                fn = ddb_sysctl;
                    178:                break;
                    179: #endif
                    180:        default:
                    181:                return (EOPNOTSUPP);
                    182:        }
                    183:
                    184:        if (SCARG(uap, oldlenp) &&
                    185:            (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
                    186:                return (error);
                    187:        if (SCARG(uap, old) != NULL) {
                    188:                if ((error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR)) != 0)
                    189:                        return (error);
                    190:                if (dolock) {
                    191:                        if (atop(oldlen) > uvmexp.wiredmax - uvmexp.wired) {
                    192:                                rw_exit_write(&sysctl_lock);
                    193:                                return (ENOMEM);
                    194:                        }
                    195:                        error = uvm_vslock(p, SCARG(uap, old), oldlen,
                    196:                            VM_PROT_READ|VM_PROT_WRITE);
                    197:                        if (error) {
                    198:                                rw_exit_write(&sysctl_lock);
                    199:                                return (error);
                    200:                        }
                    201:                }
                    202:                savelen = oldlen;
                    203:        }
                    204:        error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
                    205:            &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
                    206:        if (SCARG(uap, old) != NULL) {
                    207:                if (dolock)
                    208:                        uvm_vsunlock(p, SCARG(uap, old), savelen);
                    209:                rw_exit_write(&sysctl_lock);
                    210:        }
                    211:        if (error)
                    212:                return (error);
                    213:        if (SCARG(uap, oldlenp))
                    214:                error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
                    215:        return (error);
                    216: }
                    217:
                    218: /*
                    219:  * Attributes stored in the kernel.
                    220:  */
                    221: char hostname[MAXHOSTNAMELEN];
                    222: int hostnamelen;
                    223: char domainname[MAXHOSTNAMELEN];
                    224: int domainnamelen;
                    225: long hostid;
                    226: char *disknames = NULL;
                    227: struct diskstats *diskstats = NULL;
                    228: #ifdef INSECURE
                    229: int securelevel = -1;
                    230: #else
                    231: int securelevel;
                    232: #endif
                    233:
                    234: /*
                    235:  * kernel related system variables.
                    236:  */
                    237: int
                    238: kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                    239:     size_t newlen, struct proc *p)
                    240: {
                    241:        int error, level, inthostid, stackgap;
                    242:        extern int somaxconn, sominconn;
                    243:        extern int usermount, nosuidcoredump;
                    244:        extern long cp_time[CPUSTATES];
                    245:        extern int stackgap_random;
                    246: #ifdef CRYPTO
                    247:        extern int usercrypto;
                    248:        extern int userasymcrypto;
                    249:        extern int cryptodevallowsoft;
                    250: #endif
                    251:        extern int maxlocksperuid;
                    252:
                    253:        /* all sysctl names at this level are terminal except a ton of them */
                    254:        if (namelen != 1) {
                    255:                switch (name[0]) {
                    256:                case KERN_PROC:
                    257:                case KERN_PROC2:
                    258:                case KERN_PROF:
                    259:                case KERN_MALLOCSTATS:
                    260:                case KERN_TTY:
                    261:                case KERN_POOL:
                    262:                case KERN_PROC_ARGS:
                    263:                case KERN_SYSVIPC_INFO:
                    264:                case KERN_SEMINFO:
                    265:                case KERN_SHMINFO:
                    266:                case KERN_INTRCNT:
                    267:                case KERN_WATCHDOG:
                    268:                case KERN_EMUL:
                    269:                case KERN_EVCOUNT:
                    270: #ifdef __HAVE_TIMECOUNTER
                    271:                case KERN_TIMECOUNTER:
                    272: #endif
                    273:                case KERN_CPTIME2:
                    274:                        break;
                    275:                default:
                    276:                        return (ENOTDIR);       /* overloaded */
                    277:                }
                    278:        }
                    279:
                    280:        switch (name[0]) {
                    281:        case KERN_OSTYPE:
                    282:                return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
                    283:        case KERN_OSRELEASE:
                    284:                return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
                    285:        case KERN_OSREV:
                    286:                return (sysctl_rdint(oldp, oldlenp, newp, OpenBSD));
                    287:        case KERN_OSVERSION:
                    288:                return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
                    289:        case KERN_VERSION:
                    290:                return (sysctl_rdstring(oldp, oldlenp, newp, version));
                    291:        case KERN_MAXVNODES:
                    292:                return(sysctl_int(oldp, oldlenp, newp, newlen, &maxvnodes));
                    293:        case KERN_MAXPROC:
                    294:                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
                    295:        case KERN_MAXFILES:
                    296:                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
                    297:        case KERN_NFILES:
                    298:                return (sysctl_rdint(oldp, oldlenp, newp, nfiles));
                    299:        case KERN_TTYCOUNT:
                    300:                return (sysctl_rdint(oldp, oldlenp, newp, tty_count));
                    301:        case KERN_NUMVNODES:
                    302:                return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
                    303:        case KERN_ARGMAX:
                    304:                return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
                    305:        case KERN_NSELCOLL:
                    306:                return (sysctl_rdint(oldp, oldlenp, newp, nselcoll));
                    307:        case KERN_SECURELVL:
                    308:                level = securelevel;
                    309:                if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
                    310:                    newp == NULL)
                    311:                        return (error);
                    312:                if ((securelevel > 0 || level < -1) &&
                    313:                    level < securelevel && p->p_pid != 1)
                    314:                        return (EPERM);
                    315:                securelevel = level;
                    316:                return (0);
                    317:        case KERN_HOSTNAME:
                    318:                error = sysctl_tstring(oldp, oldlenp, newp, newlen,
                    319:                    hostname, sizeof(hostname));
                    320:                if (newp && !error)
                    321:                        hostnamelen = newlen;
                    322:                return (error);
                    323:        case KERN_DOMAINNAME:
                    324:                error = sysctl_tstring(oldp, oldlenp, newp, newlen,
                    325:                    domainname, sizeof(domainname));
                    326:                if (newp && !error)
                    327:                        domainnamelen = newlen;
                    328:                return (error);
                    329:        case KERN_HOSTID:
                    330:                inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
                    331:                error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
                    332:                hostid = inthostid;
                    333:                return (error);
                    334:        case KERN_CLOCKRATE:
                    335:                return (sysctl_clockrate(oldp, oldlenp));
                    336:        case KERN_BOOTTIME:
                    337:                return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
                    338:                    sizeof(struct timeval)));
                    339:        case KERN_VNODE:
                    340:                return (sysctl_vnode(oldp, oldlenp, p));
                    341: #ifndef SMALL_KERNEL
                    342:        case KERN_PROC:
                    343:        case KERN_PROC2:
                    344:                return (sysctl_doproc(name, namelen, oldp, oldlenp));
                    345:        case KERN_PROC_ARGS:
                    346:                return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
                    347:                     p));
                    348: #endif
                    349:        case KERN_FILE:
                    350:                return (sysctl_file(oldp, oldlenp));
                    351:        case KERN_MBSTAT:
                    352:                return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat,
                    353:                    sizeof(mbstat)));
                    354: #ifdef GPROF
                    355:        case KERN_PROF:
                    356:                return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
                    357:                    newp, newlen));
                    358: #endif
                    359:        case KERN_POSIX1:
                    360:                return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
                    361:        case KERN_NGROUPS:
                    362:                return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
                    363:        case KERN_JOB_CONTROL:
                    364:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
                    365:        case KERN_SAVED_IDS:
                    366: #ifdef _POSIX_SAVED_IDS
                    367:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
                    368: #else
                    369:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
                    370: #endif
                    371:        case KERN_MAXPARTITIONS:
                    372:                return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
                    373:        case KERN_RAWPARTITION:
                    374:                return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
                    375:        case KERN_SOMAXCONN:
                    376:                return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn));
                    377:        case KERN_SOMINCONN:
                    378:                return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn));
                    379:        case KERN_USERMOUNT:
                    380:                return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount));
                    381:        case KERN_RND:
                    382:                return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats,
                    383:                    sizeof(rndstats)));
                    384:        case KERN_ARND: {
                    385:                char buf[256];
                    386:
                    387:                if (*oldlenp > sizeof(buf))
                    388:                        *oldlenp = sizeof(buf);
                    389:                if (oldp) {
                    390:                        arc4random_bytes(buf, *oldlenp);
                    391:                        if ((error = copyout(buf, oldp, *oldlenp)))
                    392:                                return (error);
                    393:                }
                    394:                return (0);
                    395:        }
                    396:        case KERN_NOSUIDCOREDUMP:
                    397:                return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump));
                    398:        case KERN_FSYNC:
                    399:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
                    400:        case KERN_SYSVMSG:
                    401: #ifdef SYSVMSG
                    402:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
                    403: #else
                    404:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
                    405: #endif
                    406:        case KERN_SYSVSEM:
                    407: #ifdef SYSVSEM
                    408:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
                    409: #else
                    410:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
                    411: #endif
                    412:        case KERN_SYSVSHM:
                    413: #ifdef SYSVSHM
                    414:                return (sysctl_rdint(oldp, oldlenp, newp, 1));
                    415: #else
                    416:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
                    417: #endif
                    418:        case KERN_MSGBUFSIZE:
                    419:                /*
                    420:                 * deal with cases where the message buffer has
                    421:                 * become corrupted.
                    422:                 */
                    423:                if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
                    424:                        return (ENXIO);
                    425:                return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
                    426:        case KERN_MSGBUF:
                    427:                /* see note above */
                    428:                if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
                    429:                        return (ENXIO);
                    430:                return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp,
                    431:                    msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
                    432:        case KERN_MALLOCSTATS:
                    433:                return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp,
                    434:                    newp, newlen, p));
                    435:        case KERN_CPTIME:
                    436:        {
                    437:                CPU_INFO_ITERATOR cii;
                    438:                struct cpu_info *ci;
                    439:                int i;
                    440:
                    441:                bzero(cp_time, sizeof(cp_time));
                    442:
                    443:                CPU_INFO_FOREACH(cii, ci) {
                    444:                        for (i = 0; i < CPUSTATES; i++)
                    445:                                cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
                    446:                }
                    447:
                    448:                return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
                    449:                    sizeof(cp_time)));
                    450:        }
                    451:        case KERN_NCHSTATS:
                    452:                return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
                    453:                    sizeof(struct nchstats)));
                    454:        case KERN_FORKSTAT:
                    455:                return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
                    456:                    sizeof(struct forkstat)));
                    457:        case KERN_TTY:
                    458:                return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp,
                    459:                    newp, newlen));
                    460:        case KERN_FSCALE:
                    461:                return (sysctl_rdint(oldp, oldlenp, newp, fscale));
                    462:        case KERN_CCPU:
                    463:                return (sysctl_rdint(oldp, oldlenp, newp, ccpu));
                    464:        case KERN_NPROCS:
                    465:                return (sysctl_rdint(oldp, oldlenp, newp, nprocs));
                    466:        case KERN_POOL:
                    467:                return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp));
                    468:        case KERN_STACKGAPRANDOM:
                    469:                stackgap = stackgap_random;
                    470:                error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap);
                    471:                if (error)
                    472:                        return (error);
                    473:                /*
                    474:                 * Safety harness.
                    475:                 */
                    476:                if ((stackgap < ALIGNBYTES && stackgap != 0) ||
                    477:                    !powerof2(stackgap) || stackgap >= MAXSSIZ)
                    478:                        return (EINVAL);
                    479:                stackgap_random = stackgap;
                    480:                return (0);
                    481: #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
                    482:        case KERN_SYSVIPC_INFO:
                    483:                return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp));
                    484: #endif
                    485: #ifdef CRYPTO
                    486:        case KERN_USERCRYPTO:
                    487:                return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto));
                    488:        case KERN_USERASYMCRYPTO:
                    489:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                    490:                            &userasymcrypto));
                    491:        case KERN_CRYPTODEVALLOWSOFT:
                    492:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                    493:                            &cryptodevallowsoft));
                    494: #endif
                    495:        case KERN_SPLASSERT:
                    496:                return (sysctl_int(oldp, oldlenp, newp, newlen,
                    497:                    &splassert_ctl));
                    498: #ifdef SYSVSEM
                    499:        case KERN_SEMINFO:
                    500:                return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp,
                    501:                    newp, newlen));
                    502: #endif
                    503: #ifdef SYSVSHM
                    504:        case KERN_SHMINFO:
                    505:                return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp,
                    506:                    newp, newlen));
                    507: #endif
                    508: #ifndef SMALL_KERNEL
                    509:        case KERN_INTRCNT:
                    510:                return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp));
                    511:        case KERN_WATCHDOG:
                    512:                return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
                    513:                    newp, newlen));
                    514:        case KERN_EMUL:
                    515:                return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp,
                    516:                    newp, newlen));
                    517: #endif
                    518:        case KERN_MAXCLUSTERS:
                    519:                error = sysctl_int(oldp, oldlenp, newp, newlen, &nmbclust);
                    520:                if (!error)
                    521:                        nmbclust_update();
                    522:                return (error);
                    523: #ifndef SMALL_KERNEL
                    524:        case KERN_EVCOUNT:
                    525:                return (evcount_sysctl(name + 1, namelen - 1, oldp, oldlenp,
                    526:                    newp, newlen));
                    527: #endif
                    528: #ifdef __HAVE_TIMECOUNTER
                    529:        case KERN_TIMECOUNTER:
                    530:                return (sysctl_tc(name + 1, namelen - 1, oldp, oldlenp,
                    531:                    newp, newlen));
                    532: #endif
                    533:        case KERN_MAXLOCKSPERUID:
                    534:                return (sysctl_int(oldp, oldlenp, newp, newlen, &maxlocksperuid));
                    535:        case KERN_CPTIME2:
                    536:                return (sysctl_cptime2(name + 1, namelen -1, oldp, oldlenp,
                    537:                    newp, newlen));
                    538:        default:
                    539:                return (EOPNOTSUPP);
                    540:        }
                    541:        /* NOTREACHED */
                    542: }
                    543:
                    544: /*
                    545:  * hardware related system variables.
                    546:  */
                    547: char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver;
                    548:
                    549: int
                    550: hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                    551:     size_t newlen, struct proc *p)
                    552: {
                    553:        extern char machine[], cpu_model[];
                    554:        int err, cpuspeed;
                    555:
                    556:        /* all sysctl names at this level except sensors are terminal */
                    557:        if (name[0] != HW_SENSORS && namelen != 1)
                    558:                return (ENOTDIR);               /* overloaded */
                    559:
                    560:        switch (name[0]) {
                    561:        case HW_MACHINE:
                    562:                return (sysctl_rdstring(oldp, oldlenp, newp, machine));
                    563:        case HW_MODEL:
                    564:                return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
                    565:        case HW_NCPU:
                    566:                return (sysctl_rdint(oldp, oldlenp, newp, ncpus));
                    567:        case HW_BYTEORDER:
                    568:                return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
                    569:        case HW_PHYSMEM:
                    570:                return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
                    571:        case HW_USERMEM:
                    572:                return (sysctl_rdint(oldp, oldlenp, newp,
                    573:                    ctob(physmem - uvmexp.wired)));
                    574:        case HW_PAGESIZE:
                    575:                return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
                    576:        case HW_DISKNAMES:
                    577:                err = sysctl_diskinit(0, p);
                    578:                if (err)
                    579:                        return err;
                    580:                if (disknames)
                    581:                        return (sysctl_rdstring(oldp, oldlenp, newp,
                    582:                            disknames));
                    583:                else
                    584:                        return (sysctl_rdstring(oldp, oldlenp, newp, ""));
                    585:        case HW_DISKSTATS:
                    586:                err = sysctl_diskinit(1, p);
                    587:                if (err)
                    588:                        return err;
                    589:                return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
                    590:                    disk_count * sizeof(struct diskstats)));
                    591:        case HW_DISKCOUNT:
                    592:                return (sysctl_rdint(oldp, oldlenp, newp, disk_count));
                    593: #ifndef        SMALL_KERNEL
                    594:        case HW_SENSORS:
                    595:                return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
                    596:                    newp, newlen));
                    597: #endif
                    598:        case HW_CPUSPEED:
                    599:                if (!cpu_cpuspeed)
                    600:                        return (EOPNOTSUPP);
                    601:                err = cpu_cpuspeed(&cpuspeed);
                    602:                if (err)
                    603:                        return err;
                    604:                return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
                    605:        case HW_SETPERF:
                    606:                if (!cpu_setperf)
                    607:                        return (EOPNOTSUPP);
                    608:                err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel);
                    609:                if (err)
                    610:                        return err;
                    611:                if (perflevel > 100)
                    612:                        perflevel = 100;
                    613:                if (perflevel < 0)
                    614:                        perflevel = 0;
                    615:                if (newp)
                    616:                        cpu_setperf(perflevel);
                    617:                return (0);
                    618:        case HW_VENDOR:
                    619:                if (hw_vendor)
                    620:                        return (sysctl_rdstring(oldp, oldlenp, newp,
                    621:                            hw_vendor));
                    622:                else
                    623:                        return (EOPNOTSUPP);
                    624:        case HW_PRODUCT:
                    625:                if (hw_prod)
                    626:                        return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod));
                    627:                else
                    628:                        return (EOPNOTSUPP);
                    629:        case HW_VERSION:
                    630:                if (hw_ver)
                    631:                        return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver));
                    632:                else
                    633:                        return (EOPNOTSUPP);
                    634:        case HW_SERIALNO:
                    635:                if (hw_serial)
                    636:                        return (sysctl_rdstring(oldp, oldlenp, newp,
                    637:                            hw_serial));
                    638:                else
                    639:                        return (EOPNOTSUPP);
                    640:        case HW_UUID:
                    641:                if (hw_uuid)
                    642:                        return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid));
                    643:                else
                    644:                        return (EOPNOTSUPP);
                    645:        default:
                    646:                return (EOPNOTSUPP);
                    647:        }
                    648:        /* NOTREACHED */
                    649: }
                    650:
                    651: #ifdef DEBUG
                    652: /*
                    653:  * Debugging related system variables.
                    654:  */
                    655: extern struct ctldebug debug0, debug1;
                    656: struct ctldebug debug2, debug3, debug4;
                    657: struct ctldebug debug5, debug6, debug7, debug8, debug9;
                    658: struct ctldebug debug10, debug11, debug12, debug13, debug14;
                    659: struct ctldebug debug15, debug16, debug17, debug18, debug19;
                    660: static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
                    661:        &debug0, &debug1, &debug2, &debug3, &debug4,
                    662:        &debug5, &debug6, &debug7, &debug8, &debug9,
                    663:        &debug10, &debug11, &debug12, &debug13, &debug14,
                    664:        &debug15, &debug16, &debug17, &debug18, &debug19,
                    665: };
                    666: int
                    667: debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                    668:     size_t newlen, struct proc *p)
                    669: {
                    670:        struct ctldebug *cdp;
                    671:
                    672:        /* all sysctl names at this level are name and field */
                    673:        if (namelen != 2)
                    674:                return (ENOTDIR);               /* overloaded */
                    675:        cdp = debugvars[name[0]];
                    676:        if (cdp->debugname == 0)
                    677:                return (EOPNOTSUPP);
                    678:        switch (name[1]) {
                    679:        case CTL_DEBUG_NAME:
                    680:                return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
                    681:        case CTL_DEBUG_VALUE:
                    682:                return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
                    683:        default:
                    684:                return (EOPNOTSUPP);
                    685:        }
                    686:        /* NOTREACHED */
                    687: }
                    688: #endif /* DEBUG */
                    689:
                    690: /*
                    691:  * Reads, or writes that lower the value
                    692:  */
                    693: int
                    694: sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp)
                    695: {
                    696:        unsigned int oval = *valp, val = *valp;
                    697:        int error;
                    698:
                    699:        if (newp == NULL)
                    700:                return (sysctl_rdint(oldp, oldlenp, newp, *valp));
                    701:
                    702:        if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val)))
                    703:                return (error);
                    704:        if (val > oval)
                    705:                return (EPERM);         /* do not allow raising */
                    706:        *(unsigned int *)valp = val;
                    707:        return (0);
                    708: }
                    709:
                    710: /*
                    711:  * Validate parameters and get old / set new parameters
                    712:  * for an integer-valued sysctl function.
                    713:  */
                    714: int
                    715: sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp)
                    716: {
                    717:        int error = 0;
                    718:
                    719:        if (oldp && *oldlenp < sizeof(int))
                    720:                return (ENOMEM);
                    721:        if (newp && newlen != sizeof(int))
                    722:                return (EINVAL);
                    723:        *oldlenp = sizeof(int);
                    724:        if (oldp)
                    725:                error = copyout(valp, oldp, sizeof(int));
                    726:        if (error == 0 && newp)
                    727:                error = copyin(newp, valp, sizeof(int));
                    728:        return (error);
                    729: }
                    730:
                    731: /*
                    732:  * As above, but read-only.
                    733:  */
                    734: int
                    735: sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val)
                    736: {
                    737:        int error = 0;
                    738:
                    739:        if (oldp && *oldlenp < sizeof(int))
                    740:                return (ENOMEM);
                    741:        if (newp)
                    742:                return (EPERM);
                    743:        *oldlenp = sizeof(int);
                    744:        if (oldp)
                    745:                error = copyout((caddr_t)&val, oldp, sizeof(int));
                    746:        return (error);
                    747: }
                    748:
                    749: /*
                    750:  * Array of integer values.
                    751:  */
                    752: int
                    753: sysctl_int_arr(int **valpp, int *name, u_int namelen, void *oldp,
                    754:     size_t *oldlenp, void *newp, size_t newlen)
                    755: {
                    756:        if (namelen > 1)
                    757:                return (ENOTDIR);
                    758:        if (name[0] < 0 || valpp[name[0]] == NULL)
                    759:                return (EOPNOTSUPP);
                    760:        return (sysctl_int(oldp, oldlenp, newp, newlen, valpp[name[0]]));
                    761: }
                    762:
                    763: /*
                    764:  * Validate parameters and get old / set new parameters
                    765:  * for an integer-valued sysctl function.
                    766:  */
                    767: int
                    768: sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
                    769:     int64_t *valp)
                    770: {
                    771:        int error = 0;
                    772:
                    773:        if (oldp && *oldlenp < sizeof(int64_t))
                    774:                return (ENOMEM);
                    775:        if (newp && newlen != sizeof(int64_t))
                    776:                return (EINVAL);
                    777:        *oldlenp = sizeof(int64_t);
                    778:        if (oldp)
                    779:                error = copyout(valp, oldp, sizeof(int64_t));
                    780:        if (error == 0 && newp)
                    781:                error = copyin(newp, valp, sizeof(int64_t));
                    782:        return (error);
                    783: }
                    784:
                    785: /*
                    786:  * As above, but read-only.
                    787:  */
                    788: int
                    789: sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val)
                    790: {
                    791:        int error = 0;
                    792:
                    793:        if (oldp && *oldlenp < sizeof(int64_t))
                    794:                return (ENOMEM);
                    795:        if (newp)
                    796:                return (EPERM);
                    797:        *oldlenp = sizeof(int64_t);
                    798:        if (oldp)
                    799:                error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
                    800:        return (error);
                    801: }
                    802:
                    803: /*
                    804:  * Validate parameters and get old / set new parameters
                    805:  * for a string-valued sysctl function.
                    806:  */
                    807: int
                    808: sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str,
                    809:     int maxlen)
                    810: {
                    811:        return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
                    812: }
                    813:
                    814: int
                    815: sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
                    816:     char *str, int maxlen)
                    817: {
                    818:        return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
                    819: }
                    820:
                    821: int
                    822: sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
                    823:     char *str, int maxlen, int trunc)
                    824: {
                    825:        int len, error = 0;
                    826:        char c;
                    827:
                    828:        len = strlen(str) + 1;
                    829:        if (oldp && *oldlenp < len) {
                    830:                if (trunc == 0 || *oldlenp == 0)
                    831:                        return (ENOMEM);
                    832:        }
                    833:        if (newp && newlen >= maxlen)
                    834:                return (EINVAL);
                    835:        if (oldp) {
                    836:                if (trunc && *oldlenp < len) {
                    837:                        /* save & zap NUL terminator while copying */
                    838:                        c = str[*oldlenp-1];
                    839:                        str[*oldlenp-1] = '\0';
                    840:                        error = copyout(str, oldp, *oldlenp);
                    841:                        str[*oldlenp-1] = c;
                    842:                } else {
                    843:                        *oldlenp = len;
                    844:                        error = copyout(str, oldp, len);
                    845:                }
                    846:        }
                    847:        if (error == 0 && newp) {
                    848:                error = copyin(newp, str, newlen);
                    849:                str[newlen] = 0;
                    850:        }
                    851:        return (error);
                    852: }
                    853:
                    854: /*
                    855:  * As above, but read-only.
                    856:  */
                    857: int
                    858: sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str)
                    859: {
                    860:        int len, error = 0;
                    861:
                    862:        len = strlen(str) + 1;
                    863:        if (oldp && *oldlenp < len)
                    864:                return (ENOMEM);
                    865:        if (newp)
                    866:                return (EPERM);
                    867:        *oldlenp = len;
                    868:        if (oldp)
                    869:                error = copyout(str, oldp, len);
                    870:        return (error);
                    871: }
                    872:
                    873: /*
                    874:  * Validate parameters and get old / set new parameters
                    875:  * for a structure oriented sysctl function.
                    876:  */
                    877: int
                    878: sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp,
                    879:     int len)
                    880: {
                    881:        int error = 0;
                    882:
                    883:        if (oldp && *oldlenp < len)
                    884:                return (ENOMEM);
                    885:        if (newp && newlen > len)
                    886:                return (EINVAL);
                    887:        if (oldp) {
                    888:                *oldlenp = len;
                    889:                error = copyout(sp, oldp, len);
                    890:        }
                    891:        if (error == 0 && newp)
                    892:                error = copyin(newp, sp, len);
                    893:        return (error);
                    894: }
                    895:
                    896: /*
                    897:  * Validate parameters and get old parameters
                    898:  * for a structure oriented sysctl function.
                    899:  */
                    900: int
                    901: sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp,
                    902:     int len)
                    903: {
                    904:        int error = 0;
                    905:
                    906:        if (oldp && *oldlenp < len)
                    907:                return (ENOMEM);
                    908:        if (newp)
                    909:                return (EPERM);
                    910:        *oldlenp = len;
                    911:        if (oldp)
                    912:                error = copyout(sp, oldp, len);
                    913:        return (error);
                    914: }
                    915:
                    916: /*
                    917:  * Get file structures.
                    918:  */
                    919: int
                    920: sysctl_file(char *where, size_t *sizep)
                    921: {
                    922:        int buflen, error;
                    923:        struct file *fp;
                    924:        char *start = where;
                    925:
                    926:        buflen = *sizep;
                    927:        if (where == NULL) {
                    928:                /*
                    929:                 * overestimate by 10 files
                    930:                 */
                    931:                *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
                    932:                return (0);
                    933:        }
                    934:
                    935:        /*
                    936:         * first copyout filehead
                    937:         */
                    938:        if (buflen < sizeof(filehead)) {
                    939:                *sizep = 0;
                    940:                return (0);
                    941:        }
                    942:        error = copyout((caddr_t)&filehead, where, sizeof(filehead));
                    943:        if (error)
                    944:                return (error);
                    945:        buflen -= sizeof(filehead);
                    946:        where += sizeof(filehead);
                    947:
                    948:        /*
                    949:         * followed by an array of file structures
                    950:         */
                    951:        LIST_FOREACH(fp, &filehead, f_list) {
                    952:                if (buflen < sizeof(struct file)) {
                    953:                        *sizep = where - start;
                    954:                        return (ENOMEM);
                    955:                }
                    956:                error = copyout((caddr_t)fp, where, sizeof (struct file));
                    957:                if (error)
                    958:                        return (error);
                    959:                buflen -= sizeof(struct file);
                    960:                where += sizeof(struct file);
                    961:        }
                    962:        *sizep = where - start;
                    963:        return (0);
                    964: }
                    965:
                    966: #ifndef SMALL_KERNEL
                    967:
                    968: /*
                    969:  * try over estimating by 5 procs
                    970:  */
                    971: #define KERN_PROCSLOP  (5 * sizeof (struct kinfo_proc))
                    972:
                    973: int
                    974: sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep)
                    975: {
                    976:        struct kinfo_proc2 *kproc2 = NULL;
                    977:        struct eproc *eproc = NULL;
                    978:        struct proc *p;
                    979:        char *dp;
                    980:        int arg, buflen, doingzomb, elem_size, elem_count;
                    981:        int error, needed, type, op;
                    982:
                    983:        dp = where;
                    984:        buflen = where != NULL ? *sizep : 0;
                    985:        needed = error = 0;
                    986:        type = name[0];
                    987:
                    988:        if (type == KERN_PROC) {
                    989:                if (namelen != 3 && !(namelen == 2 &&
                    990:                    (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD)))
                    991:                        return (EINVAL);
                    992:                op = name[1];
                    993:                arg = op == KERN_PROC_ALL ? 0 : name[2];
                    994:                elem_size = elem_count = 0;
                    995:                eproc = malloc(sizeof(struct eproc), M_TEMP, M_WAITOK);
                    996:        } else /* if (type == KERN_PROC2) */ {
                    997:                if (namelen != 5 || name[3] < 0 || name[4] < 0)
                    998:                        return (EINVAL);
                    999:                op = name[1];
                   1000:                arg = name[2];
                   1001:                elem_size = name[3];
                   1002:                elem_count = name[4];
                   1003:                kproc2 = malloc(sizeof(struct kinfo_proc2), M_TEMP, M_WAITOK);
                   1004:        }
                   1005:        p = LIST_FIRST(&allproc);
                   1006:        doingzomb = 0;
                   1007: again:
                   1008:        for (; p != 0; p = LIST_NEXT(p, p_list)) {
                   1009:                /*
                   1010:                 * Skip embryonic processes.
                   1011:                 */
                   1012:                if (p->p_stat == SIDL)
                   1013:                        continue;
                   1014:                /*
                   1015:                 * TODO - make more efficient (see notes below).
                   1016:                 */
                   1017:                switch (op) {
                   1018:
                   1019:                case KERN_PROC_PID:
                   1020:                        /* could do this with just a lookup */
                   1021:                        if (p->p_pid != (pid_t)arg)
                   1022:                                continue;
                   1023:                        break;
                   1024:
                   1025:                case KERN_PROC_PGRP:
                   1026:                        /* could do this by traversing pgrp */
                   1027:                        if (p->p_pgrp->pg_id != (pid_t)arg)
                   1028:                                continue;
                   1029:                        break;
                   1030:
                   1031:                case KERN_PROC_SESSION:
                   1032:                        if (p->p_session->s_leader == NULL ||
                   1033:                            p->p_session->s_leader->p_pid != (pid_t)arg)
                   1034:                                continue;
                   1035:                        break;
                   1036:
                   1037:                case KERN_PROC_TTY:
                   1038:                        if ((p->p_flag & P_CONTROLT) == 0 ||
                   1039:                            p->p_session->s_ttyp == NULL ||
                   1040:                            p->p_session->s_ttyp->t_dev != (dev_t)arg)
                   1041:                                continue;
                   1042:                        break;
                   1043:
                   1044:                case KERN_PROC_UID:
                   1045:                        if (p->p_ucred->cr_uid != (uid_t)arg)
                   1046:                                continue;
                   1047:                        break;
                   1048:
                   1049:                case KERN_PROC_RUID:
                   1050:                        if (p->p_cred->p_ruid != (uid_t)arg)
                   1051:                                continue;
                   1052:                        break;
                   1053:
                   1054:                case KERN_PROC_ALL:
                   1055:                        if (p->p_flag & P_SYSTEM)
                   1056:                                continue;
                   1057:                        break;
                   1058:                case KERN_PROC_KTHREAD:
                   1059:                        /* no filtering */
                   1060:                        break;
                   1061:                default:
                   1062:                        error = EINVAL;
                   1063:                        goto err;
                   1064:                }
                   1065:                if (type == KERN_PROC) {
                   1066:                        if (buflen >= sizeof(struct kinfo_proc)) {
                   1067:                                fill_eproc(p, eproc);
                   1068:                                error = copyout((caddr_t)p,
                   1069:                                    &((struct kinfo_proc *)dp)->kp_proc,
                   1070:                                    sizeof(struct proc));
                   1071:                                if (error)
                   1072:                                        goto err;
                   1073:                                error = copyout((caddr_t)eproc,
                   1074:                                    &((struct kinfo_proc *)dp)->kp_eproc,
                   1075:                                    sizeof(*eproc));
                   1076:                                if (error)
                   1077:                                        goto err;
                   1078:                                dp += sizeof(struct kinfo_proc);
                   1079:                                buflen -= sizeof(struct kinfo_proc);
                   1080:                        }
                   1081:                        needed += sizeof(struct kinfo_proc);
                   1082:                } else /* if (type == KERN_PROC2) */ {
                   1083:                        if (buflen >= elem_size && elem_count > 0) {
                   1084:                                fill_kproc2(p, kproc2);
                   1085:                                /*
                   1086:                                 * Copy out elem_size, but not larger than
                   1087:                                 * the size of a struct kinfo_proc2.
                   1088:                                 */
                   1089:                                error = copyout(kproc2, dp,
                   1090:                                    min(sizeof(*kproc2), elem_size));
                   1091:                                if (error)
                   1092:                                        goto err;
                   1093:                                dp += elem_size;
                   1094:                                buflen -= elem_size;
                   1095:                                elem_count--;
                   1096:                        }
                   1097:                        needed += elem_size;
                   1098:                }
                   1099:        }
                   1100:        if (doingzomb == 0) {
                   1101:                p = LIST_FIRST(&zombproc);
                   1102:                doingzomb++;
                   1103:                goto again;
                   1104:        }
                   1105:        if (where != NULL) {
                   1106:                *sizep = dp - where;
                   1107:                if (needed > *sizep) {
                   1108:                        error = ENOMEM;
                   1109:                        goto err;
                   1110:                }
                   1111:        } else {
                   1112:                needed += KERN_PROCSLOP;
                   1113:                *sizep = needed;
                   1114:        }
                   1115: err:
                   1116:        if (eproc)
                   1117:                free(eproc, M_TEMP);
                   1118:        if (kproc2)
                   1119:                free(kproc2, M_TEMP);
                   1120:        return (error);
                   1121: }
                   1122:
                   1123: #endif /* SMALL_KERNEL */
                   1124:
                   1125: /*
                   1126:  * Fill in an eproc structure for the specified process.
                   1127:  */
                   1128: void
                   1129: fill_eproc(struct proc *p, struct eproc *ep)
                   1130: {
                   1131:        struct tty *tp;
                   1132:
                   1133:        ep->e_paddr = p;
                   1134:        ep->e_sess = p->p_pgrp->pg_session;
                   1135:        ep->e_pcred = *p->p_cred;
                   1136:        ep->e_ucred = *p->p_ucred;
                   1137:        if (p->p_stat == SIDL || P_ZOMBIE(p)) {
                   1138:                ep->e_vm.vm_rssize = 0;
                   1139:                ep->e_vm.vm_tsize = 0;
                   1140:                ep->e_vm.vm_dsize = 0;
                   1141:                ep->e_vm.vm_ssize = 0;
                   1142:                bzero(&ep->e_pstats, sizeof(ep->e_pstats));
                   1143:                ep->e_pstats_valid = 0;
                   1144:        } else {
                   1145:                struct vmspace *vm = p->p_vmspace;
                   1146:
                   1147:                ep->e_vm.vm_rssize = vm_resident_count(vm);
                   1148:                ep->e_vm.vm_tsize = vm->vm_tsize;
                   1149:                ep->e_vm.vm_dsize = vm->vm_dused;
                   1150:                ep->e_vm.vm_ssize = vm->vm_ssize;
                   1151:                ep->e_pstats = *p->p_stats;
                   1152:                ep->e_pstats_valid = 1;
                   1153:        }
                   1154:        if (p->p_pptr)
                   1155:                ep->e_ppid = p->p_pptr->p_pid;
                   1156:        else
                   1157:                ep->e_ppid = 0;
                   1158:        ep->e_pgid = p->p_pgrp->pg_id;
                   1159:        ep->e_jobc = p->p_pgrp->pg_jobc;
                   1160:        if ((p->p_flag & P_CONTROLT) &&
                   1161:             (tp = ep->e_sess->s_ttyp)) {
                   1162:                ep->e_tdev = tp->t_dev;
                   1163:                ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
                   1164:                ep->e_tsess = tp->t_session;
                   1165:        } else
                   1166:                ep->e_tdev = NODEV;
                   1167:        ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
                   1168:        if (SESS_LEADER(p))
                   1169:                ep->e_flag |= EPROC_SLEADER;
                   1170:        strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN);
                   1171:        ep->e_wmesg[WMESGLEN] = '\0';
                   1172:        ep->e_xsize = ep->e_xrssize = 0;
                   1173:        ep->e_xccount = ep->e_xswrss = 0;
                   1174:        strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1);
                   1175:        ep->e_login[MAXLOGNAME-1] = '\0';
                   1176:        strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN);
                   1177:        ep->e_emul[EMULNAMELEN] = '\0';
                   1178:        ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0;
                   1179:        ep->e_limit = p->p_p->ps_limit;
                   1180: }
                   1181:
                   1182: #ifndef        SMALL_KERNEL
                   1183:
                   1184: /*
                   1185:  * Fill in a kproc2 structure for the specified process.
                   1186:  */
                   1187: void
                   1188: fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
                   1189: {
                   1190:        struct tty *tp;
                   1191:        struct timeval ut, st;
                   1192:
                   1193:        bzero(ki, sizeof(*ki));
                   1194:
                   1195:        ki->p_paddr = PTRTOINT64(p);
                   1196:        ki->p_fd = PTRTOINT64(p->p_fd);
                   1197:        ki->p_stats = PTRTOINT64(p->p_stats);
                   1198:        ki->p_limit = PTRTOINT64(p->p_p->ps_limit);
                   1199:        ki->p_vmspace = PTRTOINT64(p->p_vmspace);
                   1200:        ki->p_sigacts = PTRTOINT64(p->p_sigacts);
                   1201:        ki->p_sess = PTRTOINT64(p->p_session);
                   1202:        ki->p_tsess = 0;        /* may be changed if controlling tty below */
                   1203:        ki->p_ru = PTRTOINT64(p->p_ru);
                   1204:
                   1205:        ki->p_eflag = 0;
                   1206:        ki->p_exitsig = p->p_exitsig;
                   1207:        ki->p_flag = p->p_flag | P_INMEM;
                   1208:
                   1209:        ki->p_pid = p->p_pid;
                   1210:        if (p->p_pptr)
                   1211:                ki->p_ppid = p->p_pptr->p_pid;
                   1212:        else
                   1213:                ki->p_ppid = 0;
                   1214:        if (p->p_session->s_leader)
                   1215:                ki->p_sid = p->p_session->s_leader->p_pid;
                   1216:        else
                   1217:                ki->p_sid = 0;
                   1218:        ki->p__pgid = p->p_pgrp->pg_id;
                   1219:
                   1220:        ki->p_tpgid = -1;       /* may be changed if controlling tty below */
                   1221:
                   1222:        ki->p_uid = p->p_ucred->cr_uid;
                   1223:        ki->p_ruid = p->p_cred->p_ruid;
                   1224:        ki->p_gid = p->p_ucred->cr_gid;
                   1225:        ki->p_rgid = p->p_cred->p_rgid;
                   1226:        ki->p_svuid = p->p_cred->p_svuid;
                   1227:        ki->p_svgid = p->p_cred->p_svgid;
                   1228:
                   1229:        memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups,
                   1230:            min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups)));
                   1231:        ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups;
                   1232:
                   1233:        ki->p_jobc = p->p_pgrp->pg_jobc;
                   1234:        if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) {
                   1235:                ki->p_tdev = tp->t_dev;
                   1236:                ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1;
                   1237:                ki->p_tsess = PTRTOINT64(tp->t_session);
                   1238:        } else {
                   1239:                ki->p_tdev = NODEV;
                   1240:        }
                   1241:
                   1242:        ki->p_estcpu = p->p_estcpu;
                   1243:        ki->p_rtime_sec = p->p_rtime.tv_sec;
                   1244:        ki->p_rtime_usec = p->p_rtime.tv_usec;
                   1245:        ki->p_cpticks = p->p_cpticks;
                   1246:        ki->p_pctcpu = p->p_pctcpu;
                   1247:
                   1248:        ki->p_uticks = p->p_uticks;
                   1249:        ki->p_sticks = p->p_sticks;
                   1250:        ki->p_iticks = p->p_iticks;
                   1251:
                   1252:        ki->p_tracep = PTRTOINT64(p->p_tracep);
                   1253:        ki->p_traceflag = p->p_traceflag;
                   1254:
                   1255:        ki->p_siglist = p->p_siglist;
                   1256:        ki->p_sigmask = p->p_sigmask;
                   1257:        ki->p_sigignore = p->p_sigignore;
                   1258:        ki->p_sigcatch = p->p_sigcatch;
                   1259:
                   1260:        ki->p_stat = p->p_stat;
                   1261:        ki->p_nice = p->p_nice;
                   1262:
                   1263:        ki->p_xstat = p->p_xstat;
                   1264:        ki->p_acflag = p->p_acflag;
                   1265:
                   1266:        strlcpy(ki->p_emul, p->p_emul->e_name, sizeof(ki->p_emul));
                   1267:        strlcpy(ki->p_comm, p->p_comm, sizeof(ki->p_comm));
                   1268:        strncpy(ki->p_login, p->p_session->s_login,
                   1269:            min(sizeof(ki->p_login) - 1, sizeof(p->p_session->s_login)));
                   1270:
                   1271:        if (p->p_stat == SIDL || P_ZOMBIE(p)) {
                   1272:                ki->p_vm_rssize = 0;
                   1273:                ki->p_vm_tsize = 0;
                   1274:                ki->p_vm_dsize = 0;
                   1275:                ki->p_vm_ssize = 0;
                   1276:        } else {
                   1277:                struct vmspace *vm = p->p_vmspace;
                   1278:
                   1279:                ki->p_vm_rssize = vm_resident_count(vm);
                   1280:                ki->p_vm_tsize = vm->vm_tsize;
                   1281:                ki->p_vm_dsize = vm->vm_dused;
                   1282:                ki->p_vm_ssize = vm->vm_ssize;
                   1283:
                   1284:                ki->p_forw = PTRTOINT64(p->p_forw);
                   1285:                ki->p_back = PTRTOINT64(p->p_back);
                   1286:                ki->p_addr = PTRTOINT64(p->p_addr);
                   1287:                ki->p_stat = p->p_stat;
                   1288:                ki->p_swtime = p->p_swtime;
                   1289:                ki->p_slptime = p->p_slptime;
                   1290:                ki->p_schedflags = 0;
                   1291:                ki->p_holdcnt = 1;
                   1292:                ki->p_priority = p->p_priority;
                   1293:                ki->p_usrpri = p->p_usrpri;
                   1294:                if (p->p_wmesg)
                   1295:                        strlcpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg));
                   1296:                ki->p_wchan = PTRTOINT64(p->p_wchan);
                   1297:
                   1298:        }
                   1299:
                   1300:        if (p->p_session->s_ttyvp)
                   1301:                ki->p_eflag |= EPROC_CTTY;
                   1302:        if (SESS_LEADER(p))
                   1303:                ki->p_eflag |= EPROC_SLEADER;
                   1304:        if (p->p_rlimit)
                   1305:                ki->p_rlim_rss_cur = p->p_rlimit[RLIMIT_RSS].rlim_cur;
                   1306:
                   1307:        /* XXX Is this double check necessary? */
                   1308:        if (P_ZOMBIE(p)) {
                   1309:                ki->p_uvalid = 0;
                   1310:        } else {
                   1311:                ki->p_uvalid = 1;
                   1312:
                   1313:                ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
                   1314:                ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
                   1315:
                   1316:                calcru(p, &ut, &st, 0);
                   1317:                ki->p_uutime_sec = ut.tv_sec;
                   1318:                ki->p_uutime_usec = ut.tv_usec;
                   1319:                ki->p_ustime_sec = st.tv_sec;
                   1320:                ki->p_ustime_usec = st.tv_usec;
                   1321:
                   1322:                ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss;
                   1323:                ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss;
                   1324:                ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss;
                   1325:                ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss;
                   1326:                ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt;
                   1327:                ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt;
                   1328:                ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap;
                   1329:                ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock;
                   1330:                ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock;
                   1331:                ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd;
                   1332:                ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv;
                   1333:                ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals;
                   1334:                ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw;
                   1335:                ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw;
                   1336:
                   1337:                timeradd(&p->p_stats->p_cru.ru_utime,
                   1338:                         &p->p_stats->p_cru.ru_stime, &ut);
                   1339:                ki->p_uctime_sec = ut.tv_sec;
                   1340:                ki->p_uctime_usec = ut.tv_usec;
                   1341:                ki->p_cpuid = KI_NOCPU;
                   1342: #ifdef MULTIPROCESSOR
                   1343:                if (p->p_cpu != NULL)
                   1344:                        ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu);
                   1345: #endif
                   1346:        }
                   1347: }
                   1348:
                   1349: int
                   1350: sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
                   1351:     struct proc *cp)
                   1352: {
                   1353:        struct proc *vp;
                   1354:        pid_t pid;
                   1355:        int op;
                   1356:        struct ps_strings pss;
                   1357:        struct iovec iov;
                   1358:        struct uio uio;
                   1359:        int error;
                   1360:        size_t limit;
                   1361:        int cnt;
                   1362:        char **rargv, **vargv;          /* reader vs. victim */
                   1363:        char *rarg, *varg;
                   1364:        char *buf;
                   1365:
                   1366:        if (namelen > 2)
                   1367:                return (ENOTDIR);
                   1368:        if (namelen < 2)
                   1369:                return (EINVAL);
                   1370:
                   1371:        pid = name[0];
                   1372:        op = name[1];
                   1373:
                   1374:        switch (op) {
                   1375:        case KERN_PROC_ARGV:
                   1376:        case KERN_PROC_NARGV:
                   1377:        case KERN_PROC_ENV:
                   1378:        case KERN_PROC_NENV:
                   1379:                break;
                   1380:        default:
                   1381:                return (EOPNOTSUPP);
                   1382:        }
                   1383:
                   1384:        if ((vp = pfind(pid)) == NULL)
                   1385:                return (ESRCH);
                   1386:
                   1387:        if (oldp == NULL) {
                   1388:                if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV)
                   1389:                        *oldlenp = sizeof(int);
                   1390:                else
                   1391:                        *oldlenp = ARG_MAX;     /* XXX XXX XXX */
                   1392:                return (0);
                   1393:        }
                   1394:
                   1395:        if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM))
                   1396:                return (EINVAL);
                   1397:
                   1398:        /* Exiting - don't bother, it will be gone soon anyway */
                   1399:        if ((vp->p_flag & P_WEXIT))
                   1400:                return (ESRCH);
                   1401:
                   1402:        /* Execing - danger. */
                   1403:        if ((vp->p_flag & P_INEXEC))
                   1404:                return (EBUSY);
                   1405:
                   1406:        vp->p_vmspace->vm_refcnt++;     /* XXX */
                   1407:        buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
                   1408:
                   1409:        iov.iov_base = &pss;
                   1410:        iov.iov_len = sizeof(pss);
                   1411:        uio.uio_iov = &iov;
                   1412:        uio.uio_iovcnt = 1;
                   1413:        uio.uio_offset = (off_t)PS_STRINGS;
                   1414:        uio.uio_resid = sizeof(pss);
                   1415:        uio.uio_segflg = UIO_SYSSPACE;
                   1416:        uio.uio_rw = UIO_READ;
                   1417:        uio.uio_procp = cp;
                   1418:
                   1419:        if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0)
                   1420:                goto out;
                   1421:
                   1422:        if (op == KERN_PROC_NARGV) {
                   1423:                error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
                   1424:                goto out;
                   1425:        }
                   1426:        if (op == KERN_PROC_NENV) {
                   1427:                error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
                   1428:                goto out;
                   1429:        }
                   1430:
                   1431:        if (op == KERN_PROC_ARGV) {
                   1432:                cnt = pss.ps_nargvstr;
                   1433:                vargv = pss.ps_argvstr;
                   1434:        } else {
                   1435:                cnt = pss.ps_nenvstr;
                   1436:                vargv = pss.ps_envstr;
                   1437:        }
                   1438:
                   1439:        /* -1 to have space for a terminating NUL */
                   1440:        limit = *oldlenp - 1;
                   1441:        *oldlenp = 0;
                   1442:
                   1443:        rargv = oldp;
                   1444:
                   1445:        /*
                   1446:         * *oldlenp - number of bytes copied out into readers buffer.
                   1447:         * limit - maximal number of bytes allowed into readers buffer.
                   1448:         * rarg - pointer into readers buffer where next arg will be stored.
                   1449:         * rargv - pointer into readers buffer where the next rarg pointer
                   1450:         *  will be stored.
                   1451:         * vargv - pointer into victim address space where the next argument
                   1452:         *  will be read.
                   1453:         */
                   1454:
                   1455:        /* space for cnt pointers and a NULL */
                   1456:        rarg = (char *)(rargv + cnt + 1);
                   1457:        *oldlenp += (cnt + 1) * sizeof(char **);
                   1458:
                   1459:        while (cnt > 0 && *oldlenp < limit) {
                   1460:                size_t len, vstrlen;
                   1461:
                   1462:                /* Write to readers argv */
                   1463:                if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
                   1464:                        goto out;
                   1465:
                   1466:                /* read the victim argv */
                   1467:                iov.iov_base = &varg;
                   1468:                iov.iov_len = sizeof(varg);
                   1469:                uio.uio_iov = &iov;
                   1470:                uio.uio_iovcnt = 1;
                   1471:                uio.uio_offset = (off_t)(vaddr_t)vargv;
                   1472:                uio.uio_resid = sizeof(varg);
                   1473:                uio.uio_segflg = UIO_SYSSPACE;
                   1474:                uio.uio_rw = UIO_READ;
                   1475:                uio.uio_procp = cp;
                   1476:                if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0)
                   1477:                        goto out;
                   1478:
                   1479:                if (varg == NULL)
                   1480:                        break;
                   1481:
                   1482:                /*
                   1483:                 * read the victim arg. We must jump through hoops to avoid
                   1484:                 * crossing a page boundary too much and returning an error.
                   1485:                 */
                   1486: more:
                   1487:                len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
                   1488:                /* leave space for the terminating NUL */
                   1489:                iov.iov_base = buf;
                   1490:                iov.iov_len = len;
                   1491:                uio.uio_iov = &iov;
                   1492:                uio.uio_iovcnt = 1;
                   1493:                uio.uio_offset = (off_t)(vaddr_t)varg;
                   1494:                uio.uio_resid = len;
                   1495:                uio.uio_segflg = UIO_SYSSPACE;
                   1496:                uio.uio_rw = UIO_READ;
                   1497:                uio.uio_procp = cp;
                   1498:                if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0)
                   1499:                        goto out;
                   1500:
                   1501:                for (vstrlen = 0; vstrlen < len; vstrlen++) {
                   1502:                        if (buf[vstrlen] == '\0')
                   1503:                                break;
                   1504:                }
                   1505:
                   1506:                /* Don't overflow readers buffer. */
                   1507:                if (*oldlenp + vstrlen + 1 >= limit) {
                   1508:                        error = ENOMEM;
                   1509:                        goto out;
                   1510:                }
                   1511:
                   1512:                if ((error = copyout(buf, rarg, vstrlen)) != 0)
                   1513:                        goto out;
                   1514:
                   1515:                *oldlenp += vstrlen;
                   1516:                rarg += vstrlen;
                   1517:
                   1518:                /* The string didn't end in this page? */
                   1519:                if (vstrlen == len) {
                   1520:                        varg += vstrlen;
                   1521:                        goto more;
                   1522:                }
                   1523:
                   1524:                /* End of string. Terminate it with a NUL */
                   1525:                buf[0] = '\0';
                   1526:                if ((error = copyout(buf, rarg, 1)) != 0)
                   1527:                        goto out;
                   1528:                *oldlenp += 1;
                   1529:                rarg += 1;
                   1530:
                   1531:                vargv++;
                   1532:                rargv++;
                   1533:                cnt--;
                   1534:        }
                   1535:
                   1536:        if (*oldlenp >= limit) {
                   1537:                error = ENOMEM;
                   1538:                goto out;
                   1539:        }
                   1540:
                   1541:        /* Write the terminating null */
                   1542:        rarg = NULL;
                   1543:        error = copyout(&rarg, rargv, sizeof(rarg));
                   1544:
                   1545: out:
                   1546:        uvmspace_free(vp->p_vmspace);
                   1547:        free(buf, M_TEMP);
                   1548:        return (error);
                   1549: }
                   1550:
                   1551: #endif
                   1552:
                   1553: /*
                   1554:  * Initialize disknames/diskstats for export by sysctl. If update is set,
                   1555:  * then we simply update the disk statistics information.
                   1556:  */
                   1557: int
                   1558: sysctl_diskinit(int update, struct proc *p)
                   1559: {
                   1560:        struct diskstats *sdk;
                   1561:        struct disk *dk;
                   1562:        int i, tlen, l;
                   1563:
                   1564:        if ((i = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0)
                   1565:                return i;
                   1566:
                   1567:        if (disk_change) {
                   1568:                for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk;
                   1569:                    dk = TAILQ_NEXT(dk, dk_link))
                   1570:                        tlen += strlen(dk->dk_name) + 1;
                   1571:                tlen++;
                   1572:
                   1573:                if (disknames)
                   1574:                        free(disknames, M_SYSCTL);
                   1575:                if (diskstats)
                   1576:                        free(diskstats, M_SYSCTL);
                   1577:                diskstats = NULL;
                   1578:                disknames = NULL;
                   1579:                diskstats = malloc(disk_count * sizeof(struct diskstats),
                   1580:                    M_SYSCTL, M_WAITOK);
                   1581:                disknames = malloc(tlen, M_SYSCTL, M_WAITOK);
                   1582:                disknames[0] = '\0';
                   1583:
                   1584:                for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk;
                   1585:                    dk = TAILQ_NEXT(dk, dk_link), i++) {
                   1586:                        snprintf(disknames + l, tlen - l, "%s,",
                   1587:                            dk->dk_name ? dk->dk_name : "");
                   1588:                        l += strlen(disknames + l);
                   1589:                        sdk = diskstats + i;
                   1590:                        strlcpy(sdk->ds_name, dk->dk_name,
                   1591:                            sizeof(sdk->ds_name));
                   1592:                        sdk->ds_busy = dk->dk_busy;
                   1593:                        sdk->ds_rxfer = dk->dk_rxfer;
                   1594:                        sdk->ds_wxfer = dk->dk_wxfer;
                   1595:                        sdk->ds_seek = dk->dk_seek;
                   1596:                        sdk->ds_rbytes = dk->dk_rbytes;
                   1597:                        sdk->ds_wbytes = dk->dk_wbytes;
                   1598:                        sdk->ds_attachtime = dk->dk_attachtime;
                   1599:                        sdk->ds_timestamp = dk->dk_timestamp;
                   1600:                        sdk->ds_time = dk->dk_time;
                   1601:                }
                   1602:
                   1603:                /* Eliminate trailing comma */
                   1604:                if (l != 0)
                   1605:                        disknames[l - 1] = '\0';
                   1606:                disk_change = 0;
                   1607:        } else if (update) {
                   1608:                /* Just update, number of drives hasn't changed */
                   1609:                for (dk = TAILQ_FIRST(&disklist), i = 0; dk;
                   1610:                    dk = TAILQ_NEXT(dk, dk_link), i++) {
                   1611:                        sdk = diskstats + i;
                   1612:                        strlcpy(sdk->ds_name, dk->dk_name,
                   1613:                            sizeof(sdk->ds_name));
                   1614:                        sdk->ds_busy = dk->dk_busy;
                   1615:                        sdk->ds_rxfer = dk->dk_rxfer;
                   1616:                        sdk->ds_wxfer = dk->dk_wxfer;
                   1617:                        sdk->ds_seek = dk->dk_seek;
                   1618:                        sdk->ds_rbytes = dk->dk_rbytes;
                   1619:                        sdk->ds_wbytes = dk->dk_wbytes;
                   1620:                        sdk->ds_attachtime = dk->dk_attachtime;
                   1621:                        sdk->ds_timestamp = dk->dk_timestamp;
                   1622:                        sdk->ds_time = dk->dk_time;
                   1623:                }
                   1624:        }
                   1625:        rw_exit_write(&sysctl_disklock);
                   1626:        return 0;
                   1627: }
                   1628:
                   1629: #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
                   1630: int
                   1631: sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep)
                   1632: {
                   1633: #ifdef SYSVMSG
                   1634:        struct msg_sysctl_info *msgsi;
                   1635: #endif
                   1636: #ifdef SYSVSEM
                   1637:        struct sem_sysctl_info *semsi;
                   1638: #endif
                   1639: #ifdef SYSVSHM
                   1640:        struct shm_sysctl_info *shmsi;
                   1641: #endif
                   1642:        size_t infosize, dssize, tsize, buflen;
                   1643:        int i, nds, error, ret;
                   1644:        void *buf;
                   1645:
                   1646:        if (namelen != 1)
                   1647:                return (EINVAL);
                   1648:
                   1649:        buflen = *sizep;
                   1650:
                   1651:        switch (*name) {
                   1652:        case KERN_SYSVIPC_MSG_INFO:
                   1653: #ifdef SYSVMSG
                   1654:                infosize = sizeof(msgsi->msginfo);
                   1655:                nds = msginfo.msgmni;
                   1656:                dssize = sizeof(msgsi->msgids[0]);
                   1657:                break;
                   1658: #else
                   1659:                return (EOPNOTSUPP);
                   1660: #endif
                   1661:        case KERN_SYSVIPC_SEM_INFO:
                   1662: #ifdef SYSVSEM
                   1663:                infosize = sizeof(semsi->seminfo);
                   1664:                nds = seminfo.semmni;
                   1665:                dssize = sizeof(semsi->semids[0]);
                   1666:                break;
                   1667: #else
                   1668:                return (EOPNOTSUPP);
                   1669: #endif
                   1670:        case KERN_SYSVIPC_SHM_INFO:
                   1671: #ifdef SYSVSHM
                   1672:                infosize = sizeof(shmsi->shminfo);
                   1673:                nds = shminfo.shmmni;
                   1674:                dssize = sizeof(shmsi->shmids[0]);
                   1675:                break;
                   1676: #else
                   1677:                return (EOPNOTSUPP);
                   1678: #endif
                   1679:        default:
                   1680:                return (EINVAL);
                   1681:        }
                   1682:        tsize = infosize + (nds * dssize);
                   1683:
                   1684:        /* Return just the total size required. */
                   1685:        if (where == NULL) {
                   1686:                *sizep = tsize;
                   1687:                return (0);
                   1688:        }
                   1689:
                   1690:        /* Not enough room for even the info struct. */
                   1691:        if (buflen < infosize) {
                   1692:                *sizep = 0;
                   1693:                return (ENOMEM);
                   1694:        }
                   1695:        buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
                   1696:        bzero(buf, min(tsize, buflen));
                   1697:
                   1698:        switch (*name) {
                   1699: #ifdef SYSVMSG
                   1700:        case KERN_SYSVIPC_MSG_INFO:
                   1701:                msgsi = (struct msg_sysctl_info *)buf;
                   1702:                msgsi->msginfo = msginfo;
                   1703:                break;
                   1704: #endif
                   1705: #ifdef SYSVSEM
                   1706:        case KERN_SYSVIPC_SEM_INFO:
                   1707:                semsi = (struct sem_sysctl_info *)buf;
                   1708:                semsi->seminfo = seminfo;
                   1709:                break;
                   1710: #endif
                   1711: #ifdef SYSVSHM
                   1712:        case KERN_SYSVIPC_SHM_INFO:
                   1713:                shmsi = (struct shm_sysctl_info *)buf;
                   1714:                shmsi->shminfo = shminfo;
                   1715:                break;
                   1716: #endif
                   1717:        }
                   1718:        buflen -= infosize;
                   1719:
                   1720:        ret = 0;
                   1721:        if (buflen > 0) {
                   1722:                /* Fill in the IPC data structures.  */
                   1723:                for (i = 0; i < nds; i++) {
                   1724:                        if (buflen < dssize) {
                   1725:                                ret = ENOMEM;
                   1726:                                break;
                   1727:                        }
                   1728:                        switch (*name) {
                   1729: #ifdef SYSVMSG
                   1730:                        case KERN_SYSVIPC_MSG_INFO:
                   1731:                                bcopy(&msqids[i], &msgsi->msgids[i], dssize);
                   1732:                                break;
                   1733: #endif
                   1734: #ifdef SYSVSEM
                   1735:                        case KERN_SYSVIPC_SEM_INFO:
                   1736:                                if (sema[i] != NULL)
                   1737:                                        bcopy(sema[i], &semsi->semids[i],
                   1738:                                            dssize);
                   1739:                                else
                   1740:                                        bzero(&semsi->semids[i], dssize);
                   1741:                                break;
                   1742: #endif
                   1743: #ifdef SYSVSHM
                   1744:                        case KERN_SYSVIPC_SHM_INFO:
                   1745:                                if (shmsegs[i] != NULL)
                   1746:                                        bcopy(shmsegs[i], &shmsi->shmids[i],
                   1747:                                            dssize);
                   1748:                                else
                   1749:                                        bzero(&shmsi->shmids[i], dssize);
                   1750:                                break;
                   1751: #endif
                   1752:                        }
                   1753:                        buflen -= dssize;
                   1754:                }
                   1755:        }
                   1756:        *sizep -= buflen;
                   1757:        error = copyout(buf, where, *sizep);
                   1758:        free(buf, M_TEMP);
                   1759:        /* If copyout succeeded, use return code set earlier. */
                   1760:        return (error ? error : ret);
                   1761: }
                   1762: #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
                   1763:
                   1764: #ifndef        SMALL_KERNEL
                   1765:
                   1766: int
                   1767: sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
                   1768: {
                   1769:        return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0));
                   1770: }
                   1771:
                   1772:
                   1773: int
                   1774: sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
                   1775:     void *newp, size_t newlen)
                   1776: {
                   1777:        struct ksensor *ks;
                   1778:        struct sensor *us;
                   1779:        struct ksensordev *ksd;
                   1780:        struct sensordev *usd;
                   1781:        int dev, numt, ret;
                   1782:        enum sensor_type type;
                   1783:
                   1784:        if (namelen != 1 && namelen != 3)
                   1785:                return (ENOTDIR);
                   1786:
                   1787:        dev = name[0];
                   1788:        if (namelen == 1) {
                   1789:                ksd = sensordev_get(dev);
                   1790:                if (ksd == NULL)
                   1791:                        return (ENOENT);
                   1792:
                   1793:                /* Grab a copy, to clear the kernel pointers */
                   1794:                usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK);
                   1795:                bzero(usd, sizeof(*usd));
                   1796:                usd->num = ksd->num;
                   1797:                strlcpy(usd->xname, ksd->xname, sizeof(usd->xname));
                   1798:                memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt));
                   1799:                usd->sensors_count = ksd->sensors_count;
                   1800:
                   1801:                ret = sysctl_rdstruct(oldp, oldlenp, newp, usd,
                   1802:                    sizeof(struct sensordev));
                   1803:
                   1804:                free(usd, M_TEMP);
                   1805:                return (ret);
                   1806:        }
                   1807:
                   1808:        type = name[1];
                   1809:        numt = name[2];
                   1810:
                   1811:        ks = sensor_find(dev, type, numt);
                   1812:        if (ks == NULL)
                   1813:                return (ENOENT);
                   1814:
                   1815:        /* Grab a copy, to clear the kernel pointers */
                   1816:        us = malloc(sizeof(*us), M_TEMP, M_WAITOK);
                   1817:        bzero(us, sizeof(*us));
                   1818:        memcpy(us->desc, ks->desc, sizeof(us->desc));
                   1819:        us->tv = ks->tv;
                   1820:        us->value = ks->value;
                   1821:        us->type = ks->type;
                   1822:        us->status = ks->status;
                   1823:        us->numt = ks->numt;
                   1824:        us->flags = ks->flags;
                   1825:
                   1826:        ret = sysctl_rdstruct(oldp, oldlenp, newp, us,
                   1827:            sizeof(struct sensor));
                   1828:        free(us, M_TEMP);
                   1829:        return (ret);
                   1830: }
                   1831:
                   1832: int
                   1833: sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp,
                   1834:     void *newp, size_t newlen)
                   1835: {
                   1836:        int enabled, error;
                   1837:        struct emul *e;
                   1838:
                   1839:        if (name[0] == KERN_EMUL_NUM) {
                   1840:                if (namelen != 1)
                   1841:                        return (ENOTDIR);
                   1842:                return (sysctl_rdint(oldp, oldlenp, newp, nexecs));
                   1843:        }
                   1844:
                   1845:        if (namelen != 2)
                   1846:                return (ENOTDIR);
                   1847:        if (name[0] > nexecs || name[0] < 0)
                   1848:                return (EINVAL);
                   1849:        e = execsw[name[0] - 1].es_emul;
                   1850:        if (e == NULL)
                   1851:                return (EINVAL);
                   1852:
                   1853:        switch (name[1]) {
                   1854:        case KERN_EMUL_NAME:
                   1855:                return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name));
                   1856:        case KERN_EMUL_ENABLED:
                   1857:                enabled = (e->e_flags & EMUL_ENABLED);
                   1858:                error = sysctl_int(oldp, oldlenp, newp, newlen,
                   1859:                    &enabled);
                   1860:                e->e_flags = (enabled & EMUL_ENABLED);
                   1861:                return (error);
                   1862:        default:
                   1863:                return (EINVAL);
                   1864:        }
                   1865: }
                   1866:
                   1867: #endif /* SMALL_KERNEL */
                   1868:
                   1869: int
                   1870: sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp,
                   1871:     void *newp, size_t newlen)
                   1872: {
                   1873:        CPU_INFO_ITERATOR cii;
                   1874:        struct cpu_info *ci;
                   1875:        int i;
                   1876:
                   1877:        if (namelen != 1)
                   1878:                return (ENOTDIR);
                   1879:
                   1880:        i = name[0];
                   1881:
                   1882:        CPU_INFO_FOREACH(cii, ci) {
                   1883:                if (i-- == 0)
                   1884:                        break;
                   1885:        }
                   1886:        if (i > 0)
                   1887:                return (ENOENT);
                   1888:
                   1889:        return (sysctl_rdstruct(oldp, oldlenp, newp,
                   1890:            &ci->ci_schedstate.spc_cp_time,
                   1891:            sizeof(ci->ci_schedstate.spc_cp_time)));
                   1892: }

CVSweb