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