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