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