Annotation of sys/kern/kern_sysctl.c, Revision 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