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