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