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