kern_sysctl.c revision 9455
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.25 1995/05/30 08:05:46 rgrimes 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 <sys/conf.h> 56#include <vm/vm.h> 57#include <sys/sysctl.h> 58 59#ifdef DEBUG 60static sysctlfn debug_sysctl; 61#endif 62 63/* 64 * Locking and stats 65 */ 66static struct sysctl_lock { 67 int sl_lock; 68 int sl_want; 69 int sl_locked; 70} memlock; 71 72struct sysctl_args { 73 int *name; 74 u_int namelen; 75 void *old; 76 size_t *oldlenp; 77 void *new; 78 size_t newlen; 79}; 80 81int 82__sysctl(p, uap, retval) 83 struct proc *p; 84 register struct sysctl_args *uap; 85 int *retval; 86{ 87 int error, dolock = 1; 88 u_int savelen = 0, oldlen = 0; 89 sysctlfn *fn; 90 int name[CTL_MAXNAME]; 91 92 if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 93 return (error); 94 /* 95 * all top-level sysctl names are non-terminal 96 */ 97 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 98 return (EINVAL); 99 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 100 if (error) 101 return (error); 102 103 switch (name[0]) { 104 case CTL_KERN: 105 fn = kern_sysctl; 106 if (name[1] != KERN_VNODE) /* XXX */ 107 dolock = 0; 108 break; 109 case CTL_HW: 110 fn = hw_sysctl; 111 break; 112 case CTL_VM: 113 fn = vm_sysctl; 114 break; 115 case CTL_NET: 116 fn = net_sysctl; 117 break; 118 case CTL_FS: 119 fn = fs_sysctl; 120 break; 121 case CTL_MACHDEP: 122 fn = cpu_sysctl; 123 break; 124#ifdef DEBUG 125 case CTL_DEBUG: 126 fn = debug_sysctl; 127 break; 128#endif 129 default: 130 return (EOPNOTSUPP); 131 } 132 133 if (uap->oldlenp && 134 (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 135 return (error); 136 if (uap->old != NULL) { 137 if (!useracc(uap->old, oldlen, B_WRITE)) 138 return (EFAULT); 139 while (memlock.sl_lock) { 140 memlock.sl_want = 1; 141 (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 142 memlock.sl_locked++; 143 } 144 memlock.sl_lock = 1; 145 if (dolock) 146 vslock(uap->old, oldlen); 147 savelen = oldlen; 148 } 149 error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 150 uap->new, uap->newlen, p); 151 if (uap->old != NULL) { 152 if (dolock) 153 vsunlock(uap->old, savelen, B_WRITE); 154 memlock.sl_lock = 0; 155 if (memlock.sl_want) { 156 memlock.sl_want = 0; 157 wakeup((caddr_t)&memlock); 158 } 159 } 160 if (error) 161 return (error); 162 if (uap->oldlenp) 163 error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 164 *retval = oldlen; 165 return (0); 166} 167 168/* 169 * Attributes stored in the kernel. 170 */ 171char hostname[MAXHOSTNAMELEN]; 172int hostnamelen; 173char domainname[MAXHOSTNAMELEN]; 174int domainnamelen; 175long hostid; 176int securelevel = -1; 177char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 178extern int vfs_update_wakeup; 179extern int vfs_update_interval; 180extern int osreldate; 181 182/* 183 * kernel related system variables. 184 */ 185int 186kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 187 int *name; 188 u_int namelen; 189 void *oldp; 190 size_t *oldlenp; 191 void *newp; 192 size_t newlen; 193 struct proc *p; 194{ 195 int error, level, inthostid; 196 dev_t ndumpdev; 197 198 /* all sysctl names at this level are terminal */ 199 if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 200 || name[0] == KERN_NTP_PLL)) 201 return (ENOTDIR); /* overloaded */ 202 203 switch (name[0]) { 204 case KERN_OSTYPE: 205 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 206 case KERN_OSRELEASE: 207 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 208 case KERN_OSREV: 209 return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 210 case KERN_VERSION: 211 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 212 case KERN_OSRELDATE: 213 return (sysctl_rdint(oldp, oldlenp, newp, osreldate)); 214 case KERN_BOOTFILE: 215 return (sysctl_string(oldp, oldlenp, newp, newlen, 216 kernelname, sizeof kernelname)); 217 case KERN_MAXVNODES: 218 return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 219 case KERN_MAXPROC: 220 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 221 case KERN_MAXPROCPERUID: 222 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxprocperuid)); 223 case KERN_MAXFILES: 224 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 225 case KERN_MAXFILESPERPROC: 226 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfilesperproc)); 227 case KERN_UPDATEINTERVAL: 228 /* 229 * NB: this simple-minded approach only works because 230 * `tsleep' takes a timeout argument of 0 as meaning 231 * `no timeout'. 232 */ 233 error = sysctl_int(oldp, oldlenp, newp, newlen, 234 &vfs_update_interval); 235 if(!error) { 236 wakeup(&vfs_update_wakeup); 237 } 238 return error; 239 case KERN_ARGMAX: 240 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 241 case KERN_SECURELVL: 242 level = securelevel; 243 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 244 newp == NULL) 245 return (error); 246 if (level < securelevel && p->p_pid != 1) 247 return (EPERM); 248 securelevel = level; 249 return (0); 250 case KERN_HOSTNAME: 251 error = sysctl_string(oldp, oldlenp, newp, newlen, 252 hostname, sizeof(hostname)); 253 if (newp && !error) 254 hostnamelen = newlen; 255 return (error); 256 case KERN_DOMAINNAME: 257 error = sysctl_string(oldp, oldlenp, newp, newlen, 258 domainname, sizeof(domainname)); 259 if (newp && !error) 260 domainnamelen = newlen; 261 return (error); 262 case KERN_HOSTID: 263 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 264 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 265 hostid = inthostid; 266 return (error); 267 case KERN_CLOCKRATE: 268 return (sysctl_clockrate(oldp, oldlenp)); 269 case KERN_BOOTTIME: 270 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 271 sizeof(struct timeval))); 272 case KERN_VNODE: 273 return (sysctl_vnode(oldp, oldlenp)); 274 case KERN_PROC: 275 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 276 case KERN_FILE: 277 return (sysctl_file(oldp, oldlenp)); 278#ifdef GPROF 279 case KERN_PROF: 280 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 281 newp, newlen)); 282#endif 283 case KERN_POSIX1: 284 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 285 case KERN_NGROUPS: 286 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 287 case KERN_JOB_CONTROL: 288 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 289 case KERN_SAVED_IDS: 290#ifdef _POSIX_SAVED_IDS 291 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 292#else 293 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 294#endif 295 case KERN_NTP_PLL: 296 return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp, 297 newp, newlen, p)); 298 case KERN_DUMPDEV: 299 ndumpdev = dumpdev; 300 error = sysctl_struct(oldp, oldlenp, newp, newlen, &ndumpdev, 301 sizeof ndumpdev); 302 if (!error && ndumpdev != dumpdev) { 303 error = setdumpdev(ndumpdev); 304 } 305 return error; 306 default: 307 return (EOPNOTSUPP); 308 } 309 /* NOTREACHED */ 310} 311 312/* 313 * hardware related system variables. 314 */ 315int 316hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 317 int *name; 318 u_int namelen; 319 void *oldp; 320 size_t *oldlenp; 321 void *newp; 322 size_t newlen; 323 struct proc *p; 324{ 325 /* almost all sysctl names at this level are terminal */ 326 if (namelen != 1 && name[0] != HW_DEVCONF) 327 return (ENOTDIR); /* overloaded */ 328 329 switch (name[0]) { 330 case HW_MACHINE: 331 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 332 case HW_MODEL: 333 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 334 case HW_NCPU: 335 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 336 case HW_BYTEORDER: 337 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 338 case HW_PHYSMEM: 339 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 340 case HW_USERMEM: 341 return (sysctl_rdint(oldp, oldlenp, newp, 342 ctob(physmem - cnt.v_wire_count))); 343 case HW_PAGESIZE: 344 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 345 case HW_FLOATINGPT: 346 return (sysctl_rdint(oldp, oldlenp, newp, hw_float)); 347 case HW_DEVCONF: 348 return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp, 349 newp, newlen, p)); 350 default: 351 return (EOPNOTSUPP); 352 } 353 /* NOTREACHED */ 354} 355 356#ifdef DEBUG 357/* 358 * Debugging related system variables. 359 */ 360struct ctldebug debug0, debug1, debug2, debug3, debug4; 361struct ctldebug debug5, debug6, debug7, debug8, debug9; 362struct ctldebug debug10, debug11, debug12, debug13, debug14; 363struct ctldebug debug15, debug16, debug17, debug18, debug19; 364static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 365 &debug0, &debug1, &debug2, &debug3, &debug4, 366 &debug5, &debug6, &debug7, &debug8, &debug9, 367 &debug10, &debug11, &debug12, &debug13, &debug14, 368 &debug15, &debug16, &debug17, &debug18, &debug19, 369}; 370static int 371debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 372 int *name; 373 u_int namelen; 374 void *oldp; 375 size_t *oldlenp; 376 void *newp; 377 size_t newlen; 378 struct proc *p; 379{ 380 struct ctldebug *cdp; 381 382 /* all sysctl names at this level are name and field */ 383 if (namelen != 2) 384 return (ENOTDIR); /* overloaded */ 385 cdp = debugvars[name[0]]; 386 if (cdp->debugname == 0) 387 return (EOPNOTSUPP); 388 switch (name[1]) { 389 case CTL_DEBUG_NAME: 390 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 391 case CTL_DEBUG_VALUE: 392 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 393 default: 394 return (EOPNOTSUPP); 395 } 396 /* NOTREACHED */ 397} 398#endif /* DEBUG */ 399 400/* 401 * Validate parameters and get old / set new parameters 402 * for an integer-valued sysctl function. 403 */ 404int 405sysctl_int(oldp, oldlenp, newp, newlen, valp) 406 void *oldp; 407 size_t *oldlenp; 408 void *newp; 409 size_t newlen; 410 int *valp; 411{ 412 int error = 0; 413 414 if (oldp && *oldlenp < sizeof(int)) 415 return (ENOMEM); 416 if (newp && newlen != sizeof(int)) 417 return (EINVAL); 418 *oldlenp = sizeof(int); 419 if (oldp) 420 error = copyout(valp, oldp, sizeof(int)); 421 if (error == 0 && newp) 422 error = copyin(newp, valp, sizeof(int)); 423 return (error); 424} 425 426/* 427 * As above, but read-only. 428 */ 429int 430sysctl_rdint(oldp, oldlenp, newp, val) 431 void *oldp; 432 size_t *oldlenp; 433 void *newp; 434 int val; 435{ 436 int error = 0; 437 438 if (oldp && *oldlenp < sizeof(int)) 439 return (ENOMEM); 440 if (newp) 441 return (EPERM); 442 *oldlenp = sizeof(int); 443 if (oldp) 444 error = copyout((caddr_t)&val, oldp, sizeof(int)); 445 return (error); 446} 447 448/* 449 * Validate parameters and get old / set new parameters 450 * for a string-valued sysctl function. 451 */ 452int 453sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 454 void *oldp; 455 size_t *oldlenp; 456 void *newp; 457 size_t newlen; 458 char *str; 459 int maxlen; 460{ 461 int len, error = 0; 462 463 len = strlen(str) + 1; 464 if (oldp && *oldlenp < len) 465 len = *oldlenp; 466 if (newp && newlen >= maxlen) 467 return (EINVAL); 468 if (oldp) { 469 *oldlenp = len; 470 error = copyout(str, oldp, len); 471 } 472 if (error == 0 && newp) { 473 error = copyin(newp, str, newlen); 474 str[newlen] = 0; 475 } 476 return (error); 477} 478 479/* 480 * As above, but read-only. 481 */ 482int 483sysctl_rdstring(oldp, oldlenp, newp, str) 484 void *oldp; 485 size_t *oldlenp; 486 void *newp; 487 char *str; 488{ 489 int len, error = 0; 490 491 len = strlen(str) + 1; 492 if (oldp && *oldlenp < len) 493 return (ENOMEM); 494 if (newp) 495 return (EPERM); 496 *oldlenp = len; 497 if (oldp) 498 error = copyout(str, oldp, len); 499 return (error); 500} 501 502/* 503 * Validate parameters and get old / set new parameters 504 * for a structure oriented sysctl function. 505 */ 506int 507sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 508 void *oldp; 509 size_t *oldlenp; 510 void *newp; 511 size_t newlen; 512 void *sp; 513 int len; 514{ 515 int error = 0; 516 517 if (oldp && *oldlenp < len) 518 return (ENOMEM); 519 if (newp && newlen > len) 520 return (EINVAL); 521 if (oldp) { 522 *oldlenp = len; 523 error = copyout(sp, oldp, len); 524 } 525 if (error == 0 && newp) 526 error = copyin(newp, sp, len); 527 return (error); 528} 529 530/* 531 * Validate parameters and get old parameters 532 * for a structure oriented sysctl function. 533 */ 534int 535sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 536 void *oldp; 537 size_t *oldlenp; 538 void *newp, *sp; 539 int len; 540{ 541 int error = 0; 542 543 if (oldp && *oldlenp < len) 544 return (ENOMEM); 545 if (newp) 546 return (EPERM); 547 *oldlenp = len; 548 if (oldp) 549 error = copyout(sp, oldp, len); 550 return (error); 551} 552 553/* 554 * Get file structures. 555 */ 556int 557sysctl_file(where, sizep) 558 char *where; 559 size_t *sizep; 560{ 561 int buflen, error; 562 struct file *fp; 563 char *start = where; 564 565 buflen = *sizep; 566 if (where == NULL) { 567 /* 568 * overestimate by 10 files 569 */ 570 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 571 return (0); 572 } 573 574 /* 575 * first copyout filehead 576 */ 577 if (buflen < sizeof(filehead)) { 578 *sizep = 0; 579 return (0); 580 } 581 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 582 if (error) 583 return (error); 584 buflen -= sizeof(filehead); 585 where += sizeof(filehead); 586 587 /* 588 * followed by an array of file structures 589 */ 590 for (fp = filehead; fp != NULL; fp = fp->f_filef) { 591 if (buflen < sizeof(struct file)) { 592 *sizep = where - start; 593 return (ENOMEM); 594 } 595 error = copyout((caddr_t)fp, where, sizeof (struct file)); 596 if (error) 597 return (error); 598 buflen -= sizeof(struct file); 599 where += sizeof(struct file); 600 } 601 *sizep = where - start; 602 return (0); 603} 604 605/* 606 * try over estimating by 5 procs 607 */ 608#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 609 610int 611sysctl_doproc(name, namelen, where, sizep) 612 int *name; 613 u_int namelen; 614 char *where; 615 size_t *sizep; 616{ 617 register struct proc *p; 618 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 619 register int needed = 0; 620 int buflen = where != NULL ? *sizep : 0; 621 int doingzomb; 622 struct eproc eproc; 623 int error = 0; 624 625 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 626 return (EINVAL); 627 p = (struct proc *)allproc; 628 doingzomb = 0; 629again: 630 for (; p != NULL; p = p->p_next) { 631 /* 632 * Skip embryonic processes. 633 */ 634 if (p->p_stat == SIDL) 635 continue; 636 /* 637 * TODO - make more efficient (see notes below). 638 * do by session. 639 */ 640 switch (name[0]) { 641 642 case KERN_PROC_PID: 643 /* could do this with just a lookup */ 644 if (p->p_pid != (pid_t)name[1]) 645 continue; 646 break; 647 648 case KERN_PROC_PGRP: 649 /* could do this by traversing pgrp */ 650 if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 651 continue; 652 break; 653 654 case KERN_PROC_TTY: 655 if ((p->p_flag & P_CONTROLT) == 0 || 656 p->p_session == NULL || 657 p->p_session->s_ttyp == NULL || 658 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 659 continue; 660 break; 661 662 case KERN_PROC_UID: 663 if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 664 continue; 665 break; 666 667 case KERN_PROC_RUID: 668 if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 669 continue; 670 break; 671 } 672 if (buflen >= sizeof(struct kinfo_proc)) { 673 fill_eproc(p, &eproc); 674 error = copyout((caddr_t)p, &dp->kp_proc, 675 sizeof(struct proc)); 676 if (error) 677 return (error); 678 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 679 sizeof(eproc)); 680 if (error) 681 return (error); 682 dp++; 683 buflen -= sizeof(struct kinfo_proc); 684 } 685 needed += sizeof(struct kinfo_proc); 686 } 687 if (doingzomb == 0) { 688 p = zombproc; 689 doingzomb++; 690 goto again; 691 } 692 if (where != NULL) { 693 *sizep = (caddr_t)dp - where; 694 if (needed > *sizep) 695 return (ENOMEM); 696 } else { 697 needed += KERN_PROCSLOP; 698 *sizep = needed; 699 } 700 return (0); 701} 702 703/* 704 * Fill in an eproc structure for the specified process. 705 */ 706void 707fill_eproc(p, ep) 708 register struct proc *p; 709 register struct eproc *ep; 710{ 711 register struct tty *tp; 712 713 bzero(ep, sizeof(*ep)); 714 715 ep->e_paddr = p; 716 if (p->p_cred) 717 ep->e_pcred = *p->p_cred; 718 if (p->p_ucred) 719 ep->e_ucred = *p->p_ucred; 720 if (p->p_stat != SIDL && p->p_stat != SZOMB) { 721 register struct vmspace *vm = p->p_vmspace; 722 723#ifdef pmap_resident_count 724 ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 725#else 726 ep->e_vm.vm_rssize = vm->vm_rssize; 727#endif 728 ep->e_vm.vm_tsize = vm->vm_tsize; 729 ep->e_vm.vm_dsize = vm->vm_dsize; 730 ep->e_vm.vm_ssize = vm->vm_ssize; 731#ifndef sparc 732 ep->e_vm.vm_pmap = vm->vm_pmap; 733#endif 734 } 735 if (p->p_pptr) 736 ep->e_ppid = p->p_pptr->p_pid; 737 if (p->p_pgrp) { 738 ep->e_sess = p->p_pgrp->pg_session; 739 ep->e_pgid = p->p_pgrp->pg_id; 740 ep->e_jobc = p->p_pgrp->pg_jobc; 741 } 742 if ((p->p_flag & P_CONTROLT) && 743 (ep->e_sess != NULL) && 744 ((tp = ep->e_sess->s_ttyp) != NULL)) { 745 ep->e_tdev = tp->t_dev; 746 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 747 ep->e_tsess = tp->t_session; 748 } else 749 ep->e_tdev = NODEV; 750 if (ep->e_sess && ep->e_sess->s_ttyvp) 751 ep->e_flag = EPROC_CTTY; 752 if (SESS_LEADER(p)) 753 ep->e_flag |= EPROC_SLEADER; 754 if (p->p_wmesg) { 755 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 756 ep->e_wmesg[WMESGLEN] = 0; 757 } 758} 759 760#ifdef COMPAT_43 761#include <sys/socket.h> 762#define KINFO_PROC (0<<8) 763#define KINFO_RT (1<<8) 764#define KINFO_VNODE (2<<8) 765#define KINFO_FILE (3<<8) 766#define KINFO_METER (4<<8) 767#define KINFO_LOADAVG (5<<8) 768#define KINFO_CLOCKRATE (6<<8) 769 770/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 771#define KINFO_BSDI_SYSINFO (101<<8) 772 773/* 774 * XXX this is bloat, but I hope it's better here than on the potentially 775 * limited kernel stack... -Peter 776 */ 777 778struct { 779 int bsdi_machine; /* "i386" on BSD/386 */ 780/* ^^^ this is an offset to the string, relative to the struct start */ 781 char *pad0; 782 long pad1; 783 long pad2; 784 long pad3; 785 u_long pad4; 786 u_long pad5; 787 u_long pad6; 788 789 int bsdi_ostype; /* "BSD/386" on BSD/386 */ 790 int bsdi_osrelease; /* "1.1" on BSD/386 */ 791 long pad7; 792 long pad8; 793 char *pad9; 794 795 long pad10; 796 long pad11; 797 int pad12; 798 long pad13; 799 quad_t pad14; 800 long pad15; 801 802 struct timeval pad16; 803 /* we dont set this, because BSDI's uname used gethostname() instead */ 804 int bsdi_hostname; /* hostname on BSD/386 */ 805 806 /* the actual string data is appended here */ 807 808} bsdi_si; 809/* 810 * this data is appended to the end of the bsdi_si structure during copyout. 811 * The "char *" offsets are relative to the base of the bsdi_si struct. 812 * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 813 * should not exceed the length of the buffer here... (or else!! :-) 814 */ 815char bsdi_strings[80]; /* It had better be less than this! */ 816 817struct getkerninfo_args { 818 int op; 819 char *where; 820 int *size; 821 int arg; 822}; 823 824int 825ogetkerninfo(p, uap, retval) 826 struct proc *p; 827 register struct getkerninfo_args *uap; 828 int *retval; 829{ 830 int error, name[5]; 831 u_int size; 832 833 if (uap->size && 834 (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 835 return (error); 836 837 switch (uap->op & 0xff00) { 838 839 case KINFO_RT: 840 name[0] = PF_ROUTE; 841 name[1] = 0; 842 name[2] = (uap->op & 0xff0000) >> 16; 843 name[3] = uap->op & 0xff; 844 name[4] = uap->arg; 845 error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 846 break; 847 848 case KINFO_VNODE: 849 name[0] = KERN_VNODE; 850 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 851 break; 852 853 case KINFO_PROC: 854 name[0] = KERN_PROC; 855 name[1] = uap->op & 0xff; 856 name[2] = uap->arg; 857 error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 858 break; 859 860 case KINFO_FILE: 861 name[0] = KERN_FILE; 862 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 863 break; 864 865 case KINFO_METER: 866 name[0] = VM_METER; 867 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 868 break; 869 870 case KINFO_LOADAVG: 871 name[0] = VM_LOADAVG; 872 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 873 break; 874 875 case KINFO_CLOCKRATE: 876 name[0] = KERN_CLOCKRATE; 877 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 878 break; 879 880 case KINFO_BSDI_SYSINFO: { 881 /* 882 * this is pretty crude, but it's just enough for uname() 883 * from BSDI's 1.x libc to work. 884 * 885 * In particular, it doesn't return the same results when 886 * the supplied buffer is too small. BSDI's version apparently 887 * will return the amount copied, and set the *size to how 888 * much was needed. The emulation framework here isn't capable 889 * of that, so we just set both to the amount copied. 890 * BSDI's 2.x product apparently fails with ENOMEM in this 891 * scenario. 892 */ 893 894 u_int needed; 895 u_int left; 896 char *s; 897 898 bzero((char *)&bsdi_si, sizeof(bsdi_si)); 899 bzero(bsdi_strings, sizeof(bsdi_strings)); 900 901 s = bsdi_strings; 902 903 bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 904 strcpy(s, ostype); 905 s += strlen(s) + 1; 906 907 bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 908 strcpy(s, osrelease); 909 s += strlen(s) + 1; 910 911 bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 912 strcpy(s, machine); 913 s += strlen(s) + 1; 914 915 needed = sizeof(bsdi_si) + (s - bsdi_strings); 916 917 if (uap->where == NULL) { 918 /* process is asking how much buffer to supply.. */ 919 size = needed; 920 error = 0; 921 break; 922 } 923 924 925 /* if too much buffer supplied, trim it down */ 926 if (size > needed) 927 size = needed; 928 929 /* how much of the buffer is remaining */ 930 left = size; 931 932 if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 933 break; 934 935 /* is there any point in continuing? */ 936 if (left > sizeof(bsdi_si)) { 937 left -= sizeof(bsdi_si); 938 error = copyout(&bsdi_strings, 939 uap->where + sizeof(bsdi_si), left); 940 } 941 break; 942 } 943 944 default: 945 return (EOPNOTSUPP); 946 } 947 if (error) 948 return (error); 949 *retval = size; 950 if (uap->size) 951 error = copyout((caddr_t)&size, (caddr_t)uap->size, 952 sizeof(size)); 953 return (error); 954} 955#endif /* COMPAT_43 */ 956