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