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