1 /*- 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Mike Karels at Berkeley Software Design, Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)kern_sysctl.c 8.7 (Berkeley) 02/14/95 11 */ 12 13 /* 14 * sysctl system call. 15 */ 16 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/kernel.h> 20 #include <sys/malloc.h> 21 #include <sys/proc.h> 22 #include <sys/file.h> 23 #include <sys/vnode.h> 24 #include <sys/unistd.h> 25 #include <sys/buf.h> 26 #include <sys/ioctl.h> 27 #include <sys/tty.h> 28 #include <vm/vm.h> 29 #include <sys/sysctl.h> 30 31 #include <sys/mount.h> 32 #include <sys/syscallargs.h> 33 34 sysctlfn kern_sysctl; 35 sysctlfn hw_sysctl; 36 #ifdef DEBUG 37 sysctlfn debug_sysctl; 38 #endif 39 extern sysctlfn vm_sysctl; 40 extern sysctlfn fs_sysctl; 41 extern sysctlfn net_sysctl; 42 extern sysctlfn cpu_sysctl; 43 44 /* 45 * Locking and stats 46 */ 47 static struct sysctl_lock { 48 int sl_lock; 49 int sl_want; 50 int sl_locked; 51 } memlock; 52 53 int 54 __sysctl(p, uap, retval) 55 struct proc *p; 56 register struct __sysctl_args /* { 57 syscallarg(int *) name; 58 syscallarg(u_int) namelen; 59 syscallarg(void *) old; 60 syscallarg(size_t *) oldlenp; 61 syscallarg(void *) new; 62 syscallarg(size_t) newlen; 63 } */ *uap; 64 register_t *retval; 65 { 66 int error, dolock = 1; 67 size_t savelen, oldlen = 0; 68 sysctlfn *fn; 69 int name[CTL_MAXNAME]; 70 71 if (SCARG(uap, new) != NULL && 72 (error = suser(p->p_ucred, &p->p_acflag))) 73 return (error); 74 /* 75 * all top-level sysctl names are non-terminal 76 */ 77 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 78 return (EINVAL); 79 if (error = 80 copyin(SCARG(uap, name), &name, SCARG(uap, namelen) * sizeof(int))) 81 return (error); 82 83 switch (name[0]) { 84 case CTL_KERN: 85 fn = kern_sysctl; 86 if (name[2] == KERN_VNODE) /* XXX */ 87 dolock = 0; 88 break; 89 case CTL_HW: 90 fn = hw_sysctl; 91 break; 92 case CTL_VM: 93 fn = vm_sysctl; 94 break; 95 case CTL_NET: 96 fn = net_sysctl; 97 break; 98 #ifdef notyet 99 case CTL_FS: 100 fn = fs_sysctl; 101 break; 102 #endif 103 case CTL_MACHDEP: 104 fn = cpu_sysctl; 105 break; 106 #ifdef DEBUG 107 case CTL_DEBUG: 108 fn = debug_sysctl; 109 break; 110 #endif 111 default: 112 return (EOPNOTSUPP); 113 } 114 115 if (SCARG(uap, oldlenp) && 116 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen)))) 117 return (error); 118 if (SCARG(uap, old) != NULL) { 119 if (!useracc(SCARG(uap, old), oldlen, B_WRITE)) 120 return (EFAULT); 121 while (memlock.sl_lock) { 122 memlock.sl_want = 1; 123 sleep((caddr_t)&memlock, PRIBIO+1); 124 memlock.sl_locked++; 125 } 126 memlock.sl_lock = 1; 127 if (dolock) 128 vslock(SCARG(uap, old), oldlen); 129 savelen = oldlen; 130 } 131 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old), 132 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); 133 if (SCARG(uap, old) != NULL) { 134 if (dolock) 135 vsunlock(SCARG(uap, old), savelen, B_WRITE); 136 memlock.sl_lock = 0; 137 if (memlock.sl_want) { 138 memlock.sl_want = 0; 139 wakeup((caddr_t)&memlock); 140 } 141 } 142 if (error) 143 return (error); 144 if (SCARG(uap, oldlenp)) 145 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 146 *retval = oldlen; 147 return (0); 148 } 149 150 /* 151 * Attributes stored in the kernel. 152 */ 153 char hostname[MAXHOSTNAMELEN]; 154 int hostnamelen; 155 long hostid; 156 int securelevel; 157 158 /* 159 * kernel related system variables. 160 */ 161 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 162 int *name; 163 u_int namelen; 164 void *oldp; 165 size_t *oldlenp; 166 void *newp; 167 size_t newlen; 168 struct proc *p; 169 { 170 int error, level, inthostid; 171 extern char ostype[], osrelease[], version[]; 172 173 /* all sysctl names at this level are terminal */ 174 if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) 175 return (ENOTDIR); /* overloaded */ 176 177 switch (name[0]) { 178 case KERN_OSTYPE: 179 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 180 case KERN_OSRELEASE: 181 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 182 case KERN_OSREV: 183 return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 184 case KERN_VERSION: 185 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 186 case KERN_MAXVNODES: 187 return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 188 case KERN_MAXPROC: 189 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 190 case KERN_MAXFILES: 191 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 192 case KERN_ARGMAX: 193 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 194 case KERN_SECURELVL: 195 level = securelevel; 196 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 197 newp == NULL) 198 return (error); 199 if (level < securelevel && p->p_pid != 1) 200 return (EPERM); 201 securelevel = level; 202 return (0); 203 case KERN_HOSTNAME: 204 error = sysctl_string(oldp, oldlenp, newp, newlen, 205 hostname, sizeof(hostname)); 206 if (newp && !error) 207 hostnamelen = newlen; 208 return (error); 209 case KERN_HOSTID: 210 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 211 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 212 hostid = inthostid; 213 return (error); 214 case KERN_CLOCKRATE: 215 return (sysctl_clockrate(oldp, oldlenp)); 216 case KERN_BOOTTIME: 217 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 218 sizeof(struct timeval))); 219 case KERN_VNODE: 220 return (sysctl_vnode(oldp, oldlenp)); 221 case KERN_PROC: 222 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 223 case KERN_FILE: 224 return (sysctl_file(oldp, oldlenp)); 225 #ifdef GPROF 226 case KERN_PROF: 227 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 228 newp, newlen)); 229 #endif 230 case KERN_POSIX1: 231 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 232 case KERN_NGROUPS: 233 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 234 case KERN_JOB_CONTROL: 235 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 236 case KERN_SAVED_IDS: 237 #ifdef _POSIX_SAVED_IDS 238 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 239 #else 240 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 241 #endif 242 default: 243 return (EOPNOTSUPP); 244 } 245 /* NOTREACHED */ 246 } 247 248 /* 249 * hardware related system variables. 250 */ 251 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 252 int *name; 253 u_int namelen; 254 void *oldp; 255 size_t *oldlenp; 256 void *newp; 257 size_t newlen; 258 struct proc *p; 259 { 260 extern char machine[], cpu_model[]; 261 262 /* all sysctl names at this level are terminal */ 263 if (namelen != 1) 264 return (ENOTDIR); /* overloaded */ 265 266 switch (name[0]) { 267 case HW_MACHINE: 268 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 269 case HW_MODEL: 270 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 271 case HW_NCPU: 272 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 273 case HW_BYTEORDER: 274 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 275 case HW_PHYSMEM: 276 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 277 case HW_USERMEM: 278 return (sysctl_rdint(oldp, oldlenp, newp, 279 ctob(physmem - cnt.v_wire_count))); 280 case HW_PAGESIZE: 281 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 282 default: 283 return (EOPNOTSUPP); 284 } 285 /* NOTREACHED */ 286 } 287 288 #ifdef DEBUG 289 /* 290 * Debugging related system variables. 291 */ 292 struct ctldebug debug0, debug1, debug2, debug3, debug4; 293 struct ctldebug debug5, debug6, debug7, debug8, debug9; 294 struct ctldebug debug10, debug11, debug12, debug13, debug14; 295 struct ctldebug debug15, debug16, debug17, debug18, debug19; 296 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 297 &debug0, &debug1, &debug2, &debug3, &debug4, 298 &debug5, &debug6, &debug7, &debug8, &debug9, 299 &debug10, &debug11, &debug12, &debug13, &debug14, 300 &debug15, &debug16, &debug17, &debug18, &debug19, 301 }; 302 int 303 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 304 int *name; 305 u_int namelen; 306 void *oldp; 307 size_t *oldlenp; 308 void *newp; 309 size_t newlen; 310 struct proc *p; 311 { 312 struct ctldebug *cdp; 313 314 /* all sysctl names at this level are name and field */ 315 if (namelen != 2) 316 return (ENOTDIR); /* overloaded */ 317 cdp = debugvars[name[0]]; 318 if (cdp->debugname == 0) 319 return (EOPNOTSUPP); 320 switch (name[1]) { 321 case CTL_DEBUG_NAME: 322 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 323 case CTL_DEBUG_VALUE: 324 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 325 default: 326 return (EOPNOTSUPP); 327 } 328 /* NOTREACHED */ 329 } 330 #endif /* DEBUG */ 331 332 /* 333 * Validate parameters and get old / set new parameters 334 * for an integer-valued sysctl function. 335 */ 336 sysctl_int(oldp, oldlenp, newp, newlen, valp) 337 void *oldp; 338 size_t *oldlenp; 339 void *newp; 340 size_t newlen; 341 int *valp; 342 { 343 int error = 0; 344 345 if (oldp && *oldlenp < sizeof(int)) 346 return (ENOMEM); 347 if (newp && newlen != sizeof(int)) 348 return (EINVAL); 349 *oldlenp = sizeof(int); 350 if (oldp) 351 error = copyout(valp, oldp, sizeof(int)); 352 if (error == 0 && newp) 353 error = copyin(newp, valp, sizeof(int)); 354 return (error); 355 } 356 357 /* 358 * As above, but read-only. 359 */ 360 sysctl_rdint(oldp, oldlenp, newp, val) 361 void *oldp; 362 size_t *oldlenp; 363 void *newp; 364 int val; 365 { 366 int error = 0; 367 368 if (oldp && *oldlenp < sizeof(int)) 369 return (ENOMEM); 370 if (newp) 371 return (EPERM); 372 *oldlenp = sizeof(int); 373 if (oldp) 374 error = copyout((caddr_t)&val, oldp, sizeof(int)); 375 return (error); 376 } 377 378 /* 379 * Validate parameters and get old / set new parameters 380 * for a string-valued sysctl function. 381 */ 382 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 383 void *oldp; 384 size_t *oldlenp; 385 void *newp; 386 size_t newlen; 387 char *str; 388 int maxlen; 389 { 390 int len, error = 0; 391 392 len = strlen(str) + 1; 393 if (oldp && *oldlenp < len) 394 return (ENOMEM); 395 if (newp && newlen >= maxlen) 396 return (EINVAL); 397 if (oldp) { 398 *oldlenp = len; 399 error = copyout(str, oldp, len); 400 } 401 if (error == 0 && newp) { 402 error = copyin(newp, str, newlen); 403 str[newlen] = 0; 404 } 405 return (error); 406 } 407 408 /* 409 * As above, but read-only. 410 */ 411 sysctl_rdstring(oldp, oldlenp, newp, str) 412 void *oldp; 413 size_t *oldlenp; 414 void *newp; 415 char *str; 416 { 417 int len, error = 0; 418 419 len = strlen(str) + 1; 420 if (oldp && *oldlenp < len) 421 return (ENOMEM); 422 if (newp) 423 return (EPERM); 424 *oldlenp = len; 425 if (oldp) 426 error = copyout(str, oldp, len); 427 return (error); 428 } 429 430 /* 431 * Validate parameters and get old / set new parameters 432 * for a structure oriented sysctl function. 433 */ 434 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 435 void *oldp; 436 size_t *oldlenp; 437 void *newp; 438 size_t newlen; 439 void *sp; 440 int len; 441 { 442 int error = 0; 443 444 if (oldp && *oldlenp < len) 445 return (ENOMEM); 446 if (newp && newlen > len) 447 return (EINVAL); 448 if (oldp) { 449 *oldlenp = len; 450 error = copyout(sp, oldp, len); 451 } 452 if (error == 0 && newp) 453 error = copyin(newp, sp, len); 454 return (error); 455 } 456 457 /* 458 * Validate parameters and get old parameters 459 * for a structure oriented sysctl function. 460 */ 461 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 462 void *oldp; 463 size_t *oldlenp; 464 void *newp, *sp; 465 int len; 466 { 467 int error = 0; 468 469 if (oldp && *oldlenp < len) 470 return (ENOMEM); 471 if (newp) 472 return (EPERM); 473 *oldlenp = len; 474 if (oldp) 475 error = copyout(sp, oldp, len); 476 return (error); 477 } 478 479 /* 480 * Get file structures. 481 */ 482 sysctl_file(where, sizep) 483 char *where; 484 size_t *sizep; 485 { 486 int buflen, error; 487 struct file *fp; 488 char *start = where; 489 490 buflen = *sizep; 491 if (where == NULL) { 492 /* 493 * overestimate by 10 files 494 */ 495 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 496 return (0); 497 } 498 499 /* 500 * first copyout filehead 501 */ 502 if (buflen < sizeof(filehead)) { 503 *sizep = 0; 504 return (0); 505 } 506 if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) 507 return (error); 508 buflen -= sizeof(filehead); 509 where += sizeof(filehead); 510 511 /* 512 * followed by an array of file structures 513 */ 514 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) { 515 if (buflen < sizeof(struct file)) { 516 *sizep = where - start; 517 return (ENOMEM); 518 } 519 if (error = copyout((caddr_t)fp, where, sizeof (struct file))) 520 return (error); 521 buflen -= sizeof(struct file); 522 where += sizeof(struct file); 523 } 524 *sizep = where - start; 525 return (0); 526 } 527 528 /* 529 * try over estimating by 5 procs 530 */ 531 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 532 533 sysctl_doproc(name, namelen, where, sizep) 534 int *name; 535 u_int namelen; 536 char *where; 537 size_t *sizep; 538 { 539 register struct proc *p; 540 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 541 register int needed = 0; 542 int buflen = where != NULL ? *sizep : 0; 543 int doingzomb; 544 struct eproc eproc; 545 int error = 0; 546 547 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 548 return (EINVAL); 549 p = allproc.lh_first; 550 doingzomb = 0; 551 again: 552 for (; p != 0; p = p->p_list.le_next) { 553 /* 554 * Skip embryonic processes. 555 */ 556 if (p->p_stat == SIDL) 557 continue; 558 /* 559 * TODO - make more efficient (see notes below). 560 * do by session. 561 */ 562 switch (name[0]) { 563 564 case KERN_PROC_PID: 565 /* could do this with just a lookup */ 566 if (p->p_pid != (pid_t)name[1]) 567 continue; 568 break; 569 570 case KERN_PROC_PGRP: 571 /* could do this by traversing pgrp */ 572 if (p->p_pgrp->pg_id != (pid_t)name[1]) 573 continue; 574 break; 575 576 case KERN_PROC_TTY: 577 if ((p->p_flag & P_CONTROLT) == 0 || 578 p->p_session->s_ttyp == NULL || 579 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 580 continue; 581 break; 582 583 case KERN_PROC_UID: 584 if (p->p_ucred->cr_uid != (uid_t)name[1]) 585 continue; 586 break; 587 588 case KERN_PROC_RUID: 589 if (p->p_cred->p_ruid != (uid_t)name[1]) 590 continue; 591 break; 592 } 593 if (buflen >= sizeof(struct kinfo_proc)) { 594 fill_eproc(p, &eproc); 595 if (error = copyout((caddr_t)p, &dp->kp_proc, 596 sizeof(struct proc))) 597 return (error); 598 if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 599 sizeof(eproc))) 600 return (error); 601 dp++; 602 buflen -= sizeof(struct kinfo_proc); 603 } 604 needed += sizeof(struct kinfo_proc); 605 } 606 if (doingzomb == 0) { 607 p = zombproc.lh_first; 608 doingzomb++; 609 goto again; 610 } 611 if (where != NULL) { 612 *sizep = (caddr_t)dp - where; 613 if (needed > *sizep) 614 return (ENOMEM); 615 } else { 616 needed += KERN_PROCSLOP; 617 *sizep = needed; 618 } 619 return (0); 620 } 621 622 /* 623 * Fill in an eproc structure for the specified process. 624 */ 625 void 626 fill_eproc(p, ep) 627 register struct proc *p; 628 register struct eproc *ep; 629 { 630 register struct tty *tp; 631 632 ep->e_paddr = p; 633 ep->e_sess = p->p_pgrp->pg_session; 634 ep->e_pcred = *p->p_cred; 635 ep->e_ucred = *p->p_ucred; 636 if (p->p_stat == SIDL || p->p_stat == SZOMB) { 637 ep->e_vm.vm_rssize = 0; 638 ep->e_vm.vm_tsize = 0; 639 ep->e_vm.vm_dsize = 0; 640 ep->e_vm.vm_ssize = 0; 641 #ifndef sparc 642 /* ep->e_vm.vm_pmap = XXX; */ 643 #endif 644 } else { 645 register struct vmspace *vm = p->p_vmspace; 646 647 #ifdef pmap_resident_count 648 ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 649 #else 650 ep->e_vm.vm_rssize = vm->vm_rssize; 651 #endif 652 ep->e_vm.vm_tsize = vm->vm_tsize; 653 ep->e_vm.vm_dsize = vm->vm_dsize; 654 ep->e_vm.vm_ssize = vm->vm_ssize; 655 #ifndef sparc 656 ep->e_vm.vm_pmap = vm->vm_pmap; 657 #endif 658 } 659 if (p->p_pptr) 660 ep->e_ppid = p->p_pptr->p_pid; 661 else 662 ep->e_ppid = 0; 663 ep->e_pgid = p->p_pgrp->pg_id; 664 ep->e_jobc = p->p_pgrp->pg_jobc; 665 if ((p->p_flag & P_CONTROLT) && 666 (tp = ep->e_sess->s_ttyp)) { 667 ep->e_tdev = tp->t_dev; 668 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 669 ep->e_tsess = tp->t_session; 670 } else 671 ep->e_tdev = NODEV; 672 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 673 if (SESS_LEADER(p)) 674 ep->e_flag |= EPROC_SLEADER; 675 if (p->p_wmesg) 676 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 677 ep->e_xsize = ep->e_xrssize = 0; 678 ep->e_xccount = ep->e_xswrss = 0; 679 } 680 681 #ifdef COMPAT_43 682 #include <sys/socket.h> 683 #define KINFO_PROC (0<<8) 684 #define KINFO_RT (1<<8) 685 #define KINFO_VNODE (2<<8) 686 #define KINFO_FILE (3<<8) 687 #define KINFO_METER (4<<8) 688 #define KINFO_LOADAVG (5<<8) 689 #define KINFO_CLOCKRATE (6<<8) 690 691 compat_43_getkerninfo(p, uap, retval) 692 struct proc *p; 693 register struct compat_43_getkerninfo_args /* { 694 syscallarg(int) op; 695 syscallarg(char *) where; 696 syscallarg(int *) size; 697 syscallarg(int) arg; 698 } */ *uap; 699 register_t *retval; 700 { 701 int error, name[5]; 702 size_t size; 703 704 if (SCARG(uap, size) && (error = copyin((caddr_t)SCARG(uap, size), 705 (caddr_t)&size, sizeof(size)))) 706 return (error); 707 708 switch (SCARG(uap, op) & 0xff00) { 709 710 case KINFO_RT: 711 name[0] = PF_ROUTE; 712 name[1] = 0; 713 name[2] = (SCARG(uap, op) & 0xff0000) >> 16; 714 name[3] = SCARG(uap, op) & 0xff; 715 name[4] = SCARG(uap, arg); 716 error = 717 net_sysctl(name, 5, SCARG(uap, where), &size, NULL, 0, p); 718 break; 719 720 case KINFO_VNODE: 721 name[0] = KERN_VNODE; 722 error = 723 kern_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); 724 break; 725 726 case KINFO_PROC: 727 name[0] = KERN_PROC; 728 name[1] = SCARG(uap, op) & 0xff; 729 name[2] = SCARG(uap, arg); 730 error = 731 kern_sysctl(name, 3, SCARG(uap, where), &size, NULL, 0, p); 732 break; 733 734 case KINFO_FILE: 735 name[0] = KERN_FILE; 736 error = 737 kern_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); 738 break; 739 740 case KINFO_METER: 741 name[0] = VM_METER; 742 error = 743 vm_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); 744 break; 745 746 case KINFO_LOADAVG: 747 name[0] = VM_LOADAVG; 748 error = 749 vm_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); 750 break; 751 752 case KINFO_CLOCKRATE: 753 name[0] = KERN_CLOCKRATE; 754 error = 755 kern_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); 756 break; 757 758 default: 759 return (EOPNOTSUPP); 760 } 761 if (error) 762 return (error); 763 *retval = size; 764 if (SCARG(uap, size)) 765 error = copyout((caddr_t)&size, (caddr_t)SCARG(uap, size), 766 sizeof(size)); 767 return (error); 768 } 769 #endif /* COMPAT_43 */ 770