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