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