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.20 1994/12/18 13:56:50 guido 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_MAXFILES: 221 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 222 case KERN_UPDATEINTERVAL: 223 /* 224 * NB: this simple-minded approach only works because 225 * `tsleep' takes a timeout argument of 0 as meaning 226 * `no timeout'. 227 */ 228 error = sysctl_int(oldp, oldlenp, newp, newlen, 229 &vfs_update_interval); 230 if(!error) { 231 wakeup(&vfs_update_wakeup); 232 } 233 return error; 234 case KERN_ARGMAX: 235 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 236 case KERN_SECURELVL: 237 level = securelevel; 238 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 239 newp == NULL) 240 return (error); 241 if (level < securelevel && p->p_pid != 1) 242 return (EPERM); 243 securelevel = level; 244 return (0); 245 case KERN_HOSTNAME: 246 error = sysctl_string(oldp, oldlenp, newp, newlen, 247 hostname, sizeof(hostname)); 248 if (newp && !error) 249 hostnamelen = newlen; 250 return (error); 251 case KERN_DOMAINNAME: 252 error = sysctl_string(oldp, oldlenp, newp, newlen, 253 domainname, sizeof(domainname)); 254 if (newp && !error) 255 domainnamelen = newlen; 256 return (error); 257 case KERN_HOSTID: 258 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 259 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 260 hostid = inthostid; 261 return (error); 262 case KERN_CLOCKRATE: 263 return (sysctl_clockrate(oldp, oldlenp)); 264 case KERN_BOOTTIME: 265 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 266 sizeof(struct timeval))); 267 case KERN_VNODE: 268 return (sysctl_vnode(oldp, oldlenp)); 269 case KERN_PROC: 270 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 271 case KERN_FILE: 272 return (sysctl_file(oldp, oldlenp)); 273 #ifdef GPROF 274 case KERN_PROF: 275 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 276 newp, newlen)); 277 #endif 278 case KERN_POSIX1: 279 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 280 case KERN_NGROUPS: 281 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 282 case KERN_JOB_CONTROL: 283 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 284 case KERN_SAVED_IDS: 285 #ifdef _POSIX_SAVED_IDS 286 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 287 #else 288 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 289 #endif 290 case KERN_NTP_PLL: 291 return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp, 292 newp, newlen, p)); 293 default: 294 return (EOPNOTSUPP); 295 } 296 /* NOTREACHED */ 297 } 298 299 /* 300 * hardware related system variables. 301 */ 302 int 303 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 304 int *name; 305 u_int namelen; 306 void *oldp; 307 size_t *oldlenp; 308 void *newp; 309 size_t newlen; 310 struct proc *p; 311 { 312 extern char machine[], cpu_model[]; 313 extern int hw_float; 314 315 /* almost all sysctl names at this level are terminal */ 316 if (namelen != 1 && name[0] != HW_DEVCONF) 317 return (ENOTDIR); /* overloaded */ 318 319 switch (name[0]) { 320 case HW_MACHINE: 321 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 322 case HW_MODEL: 323 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 324 case HW_NCPU: 325 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 326 case HW_BYTEORDER: 327 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 328 case HW_PHYSMEM: 329 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 330 case HW_USERMEM: 331 return (sysctl_rdint(oldp, oldlenp, newp, 332 ctob(physmem - cnt.v_wire_count))); 333 case HW_PAGESIZE: 334 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 335 case HW_FLOATINGPT: 336 return (sysctl_rdint(oldp, oldlenp, newp, hw_float)); 337 case HW_DEVCONF: 338 return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp, 339 newp, newlen, p)); 340 default: 341 return (EOPNOTSUPP); 342 } 343 /* NOTREACHED */ 344 } 345 346 #ifdef DEBUG 347 /* 348 * Debugging related system variables. 349 */ 350 struct ctldebug debug0, debug1, debug2, debug3, debug4; 351 struct ctldebug debug5, debug6, debug7, debug8, debug9; 352 struct ctldebug debug10, debug11, debug12, debug13, debug14; 353 struct ctldebug debug15, debug16, debug17, debug18, debug19; 354 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 355 &debug0, &debug1, &debug2, &debug3, &debug4, 356 &debug5, &debug6, &debug7, &debug8, &debug9, 357 &debug10, &debug11, &debug12, &debug13, &debug14, 358 &debug15, &debug16, &debug17, &debug18, &debug19, 359 }; 360 static int 361 debug_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 struct ctldebug *cdp; 371 372 /* all sysctl names at this level are name and field */ 373 if (namelen != 2) 374 return (ENOTDIR); /* overloaded */ 375 cdp = debugvars[name[0]]; 376 if (cdp->debugname == 0) 377 return (EOPNOTSUPP); 378 switch (name[1]) { 379 case CTL_DEBUG_NAME: 380 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 381 case CTL_DEBUG_VALUE: 382 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 383 default: 384 return (EOPNOTSUPP); 385 } 386 /* NOTREACHED */ 387 } 388 #endif /* DEBUG */ 389 390 /* 391 * Validate parameters and get old / set new parameters 392 * for an integer-valued sysctl function. 393 */ 394 int 395 sysctl_int(oldp, oldlenp, newp, newlen, valp) 396 void *oldp; 397 size_t *oldlenp; 398 void *newp; 399 size_t newlen; 400 int *valp; 401 { 402 int error = 0; 403 404 if (oldp && *oldlenp < sizeof(int)) 405 return (ENOMEM); 406 if (newp && newlen != sizeof(int)) 407 return (EINVAL); 408 *oldlenp = sizeof(int); 409 if (oldp) 410 error = copyout(valp, oldp, sizeof(int)); 411 if (error == 0 && newp) 412 error = copyin(newp, valp, sizeof(int)); 413 return (error); 414 } 415 416 /* 417 * As above, but read-only. 418 */ 419 int 420 sysctl_rdint(oldp, oldlenp, newp, val) 421 void *oldp; 422 size_t *oldlenp; 423 void *newp; 424 int val; 425 { 426 int error = 0; 427 428 if (oldp && *oldlenp < sizeof(int)) 429 return (ENOMEM); 430 if (newp) 431 return (EPERM); 432 *oldlenp = sizeof(int); 433 if (oldp) 434 error = copyout((caddr_t)&val, oldp, sizeof(int)); 435 return (error); 436 } 437 438 /* 439 * Validate parameters and get old / set new parameters 440 * for a string-valued sysctl function. 441 */ 442 int 443 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 444 void *oldp; 445 size_t *oldlenp; 446 void *newp; 447 size_t newlen; 448 char *str; 449 int maxlen; 450 { 451 int len, error = 0; 452 453 len = strlen(str) + 1; 454 if (oldp && *oldlenp < len) 455 len = *oldlenp; 456 if (newp && newlen >= maxlen) 457 return (EINVAL); 458 if (oldp) { 459 *oldlenp = len; 460 error = copyout(str, oldp, len); 461 } 462 if (error == 0 && newp) { 463 error = copyin(newp, str, newlen); 464 str[newlen] = 0; 465 } 466 return (error); 467 } 468 469 /* 470 * As above, but read-only. 471 */ 472 int 473 sysctl_rdstring(oldp, oldlenp, newp, str) 474 void *oldp; 475 size_t *oldlenp; 476 void *newp; 477 char *str; 478 { 479 int len, error = 0; 480 481 len = strlen(str) + 1; 482 if (oldp && *oldlenp < len) 483 return (ENOMEM); 484 if (newp) 485 return (EPERM); 486 *oldlenp = len; 487 if (oldp) 488 error = copyout(str, oldp, len); 489 return (error); 490 } 491 492 /* 493 * Validate parameters and get old / set new parameters 494 * for a structure oriented sysctl function. 495 */ 496 int 497 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 498 void *oldp; 499 size_t *oldlenp; 500 void *newp; 501 size_t newlen; 502 void *sp; 503 int len; 504 { 505 int error = 0; 506 507 if (oldp && *oldlenp < len) 508 return (ENOMEM); 509 if (newp && newlen > len) 510 return (EINVAL); 511 if (oldp) { 512 *oldlenp = len; 513 error = copyout(sp, oldp, len); 514 } 515 if (error == 0 && newp) 516 error = copyin(newp, sp, len); 517 return (error); 518 } 519 520 /* 521 * Validate parameters and get old parameters 522 * for a structure oriented sysctl function. 523 */ 524 int 525 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 526 void *oldp; 527 size_t *oldlenp; 528 void *newp, *sp; 529 int len; 530 { 531 int error = 0; 532 533 if (oldp && *oldlenp < len) 534 return (ENOMEM); 535 if (newp) 536 return (EPERM); 537 *oldlenp = len; 538 if (oldp) 539 error = copyout(sp, oldp, len); 540 return (error); 541 } 542 543 /* 544 * Get file structures. 545 */ 546 int 547 sysctl_file(where, sizep) 548 char *where; 549 size_t *sizep; 550 { 551 int buflen, error; 552 struct file *fp; 553 char *start = where; 554 555 buflen = *sizep; 556 if (where == NULL) { 557 /* 558 * overestimate by 10 files 559 */ 560 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 561 return (0); 562 } 563 564 /* 565 * first copyout filehead 566 */ 567 if (buflen < sizeof(filehead)) { 568 *sizep = 0; 569 return (0); 570 } 571 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 572 if (error) 573 return (error); 574 buflen -= sizeof(filehead); 575 where += sizeof(filehead); 576 577 /* 578 * followed by an array of file structures 579 */ 580 for (fp = filehead; fp != NULL; fp = fp->f_filef) { 581 if (buflen < sizeof(struct file)) { 582 *sizep = where - start; 583 return (ENOMEM); 584 } 585 error = copyout((caddr_t)fp, where, sizeof (struct file)); 586 if (error) 587 return (error); 588 buflen -= sizeof(struct file); 589 where += sizeof(struct file); 590 } 591 *sizep = where - start; 592 return (0); 593 } 594 595 /* 596 * try over estimating by 5 procs 597 */ 598 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 599 600 int 601 sysctl_doproc(name, namelen, where, sizep) 602 int *name; 603 u_int namelen; 604 char *where; 605 size_t *sizep; 606 { 607 register struct proc *p; 608 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 609 register int needed = 0; 610 int buflen = where != NULL ? *sizep : 0; 611 int doingzomb; 612 struct eproc eproc; 613 int error = 0; 614 615 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 616 return (EINVAL); 617 p = (struct proc *)allproc; 618 doingzomb = 0; 619 again: 620 for (; p != NULL; p = p->p_next) { 621 /* 622 * Skip embryonic processes. 623 */ 624 if (p->p_stat == SIDL) 625 continue; 626 /* 627 * TODO - make more efficient (see notes below). 628 * do by session. 629 */ 630 switch (name[0]) { 631 632 case KERN_PROC_PID: 633 /* could do this with just a lookup */ 634 if (p->p_pid != (pid_t)name[1]) 635 continue; 636 break; 637 638 case KERN_PROC_PGRP: 639 /* could do this by traversing pgrp */ 640 if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 641 continue; 642 break; 643 644 case KERN_PROC_TTY: 645 if ((p->p_flag & P_CONTROLT) == 0 || 646 p->p_session == NULL || 647 p->p_session->s_ttyp == NULL || 648 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 649 continue; 650 break; 651 652 case KERN_PROC_UID: 653 if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 654 continue; 655 break; 656 657 case KERN_PROC_RUID: 658 if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 659 continue; 660 break; 661 } 662 if (buflen >= sizeof(struct kinfo_proc)) { 663 fill_eproc(p, &eproc); 664 error = copyout((caddr_t)p, &dp->kp_proc, 665 sizeof(struct proc)); 666 if (error) 667 return (error); 668 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 669 sizeof(eproc)); 670 if (error) 671 return (error); 672 dp++; 673 buflen -= sizeof(struct kinfo_proc); 674 } 675 needed += sizeof(struct kinfo_proc); 676 } 677 if (doingzomb == 0) { 678 p = zombproc; 679 doingzomb++; 680 goto again; 681 } 682 if (where != NULL) { 683 *sizep = (caddr_t)dp - where; 684 if (needed > *sizep) 685 return (ENOMEM); 686 } else { 687 needed += KERN_PROCSLOP; 688 *sizep = needed; 689 } 690 return (0); 691 } 692 693 /* 694 * Fill in an eproc structure for the specified process. 695 */ 696 void 697 fill_eproc(p, ep) 698 register struct proc *p; 699 register struct eproc *ep; 700 { 701 register struct tty *tp; 702 703 bzero(ep, sizeof(*ep)); 704 705 ep->e_paddr = p; 706 if (p->p_cred) 707 ep->e_pcred = *p->p_cred; 708 if (p->p_ucred) 709 ep->e_ucred = *p->p_ucred; 710 if (p->p_stat != SIDL && p->p_stat != SZOMB) { 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 #ifndef sparc 722 ep->e_vm.vm_pmap = vm->vm_pmap; 723 #endif 724 } 725 if (p->p_pptr) 726 ep->e_ppid = p->p_pptr->p_pid; 727 if (p->p_pgrp) { 728 ep->e_sess = p->p_pgrp->pg_session; 729 ep->e_pgid = p->p_pgrp->pg_id; 730 ep->e_jobc = p->p_pgrp->pg_jobc; 731 } 732 if ((p->p_flag & P_CONTROLT) && 733 (ep->e_sess != NULL) && 734 ((tp = ep->e_sess->s_ttyp) != NULL)) { 735 ep->e_tdev = tp->t_dev; 736 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 737 ep->e_tsess = tp->t_session; 738 } else 739 ep->e_tdev = NODEV; 740 if (ep->e_sess && ep->e_sess->s_ttyvp) 741 ep->e_flag = EPROC_CTTY; 742 if (SESS_LEADER(p)) 743 ep->e_flag |= EPROC_SLEADER; 744 if (p->p_wmesg) { 745 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 746 ep->e_wmesg[WMESGLEN] = 0; 747 } 748 } 749 750 #ifdef COMPAT_43 751 #include <sys/socket.h> 752 #define KINFO_PROC (0<<8) 753 #define KINFO_RT (1<<8) 754 #define KINFO_VNODE (2<<8) 755 #define KINFO_FILE (3<<8) 756 #define KINFO_METER (4<<8) 757 #define KINFO_LOADAVG (5<<8) 758 #define KINFO_CLOCKRATE (6<<8) 759 760 struct getkerninfo_args { 761 int op; 762 char *where; 763 int *size; 764 int arg; 765 }; 766 767 int 768 ogetkerninfo(p, uap, retval) 769 struct proc *p; 770 register struct getkerninfo_args *uap; 771 int *retval; 772 { 773 int error, name[5]; 774 u_int size; 775 776 if (uap->size && 777 (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 778 return (error); 779 780 switch (uap->op & 0xff00) { 781 782 case KINFO_RT: 783 name[0] = PF_ROUTE; 784 name[1] = 0; 785 name[2] = (uap->op & 0xff0000) >> 16; 786 name[3] = uap->op & 0xff; 787 name[4] = uap->arg; 788 error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 789 break; 790 791 case KINFO_VNODE: 792 name[0] = KERN_VNODE; 793 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 794 break; 795 796 case KINFO_PROC: 797 name[0] = KERN_PROC; 798 name[1] = uap->op & 0xff; 799 name[2] = uap->arg; 800 error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 801 break; 802 803 case KINFO_FILE: 804 name[0] = KERN_FILE; 805 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 806 break; 807 808 case KINFO_METER: 809 name[0] = VM_METER; 810 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 811 break; 812 813 case KINFO_LOADAVG: 814 name[0] = VM_LOADAVG; 815 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 816 break; 817 818 case KINFO_CLOCKRATE: 819 name[0] = KERN_CLOCKRATE; 820 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 821 break; 822 823 default: 824 return (EOPNOTSUPP); 825 } 826 if (error) 827 return (error); 828 *retval = size; 829 if (uap->size) 830 error = copyout((caddr_t)&size, (caddr_t)uap->size, 831 sizeof(size)); 832 return (error); 833 } 834 #endif /* COMPAT_43 */ 835