9ae159169a
are running under. Here's how to bootstrap (order is important): 1) Re-compile gcc (just the driver is all you need). 2) Re-compile libc. 3) Re-compile your kernel. Reboot. 4) cd /usr/src/include; make install You can now detect the compilation environment with the following code: #if !defined(__FreeBSD__) #define __FreeBSD_version 199401 #elif __FreeBSD__ == 1 #define __FreeBSD_version 199405 #else #include <osreldate.h> #endif You can determine the run-time environment by calling the new C library function getosreldate(), or by examining the MIB variable kern.osreldate. For the time being, the release date is defined as 199409, which we have already established as our target.
825 lines
19 KiB
C
825 lines
19 KiB
C
/*-
|
|
* Copyright (c) 1982, 1986, 1989, 1993
|
|
* The Regents of the University of California. All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to Berkeley by
|
|
* Mike Karels at Berkeley Software Design, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
|
|
* $Id: kern_sysctl.c,v 1.5 1994/08/08 15:40:58 wollman Exp $
|
|
*/
|
|
|
|
/*
|
|
* sysctl system call.
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/file.h>
|
|
#include <sys/vnode.h>
|
|
#include <sys/unistd.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/tty.h>
|
|
#include <vm/vm.h>
|
|
#include <sys/sysctl.h>
|
|
|
|
sysctlfn kern_sysctl;
|
|
sysctlfn hw_sysctl;
|
|
#ifdef DEBUG
|
|
sysctlfn debug_sysctl;
|
|
#endif
|
|
extern sysctlfn vm_sysctl;
|
|
extern sysctlfn fs_sysctl;
|
|
extern sysctlfn net_sysctl;
|
|
extern sysctlfn cpu_sysctl;
|
|
|
|
/*
|
|
* Locking and stats
|
|
*/
|
|
static struct sysctl_lock {
|
|
int sl_lock;
|
|
int sl_want;
|
|
int sl_locked;
|
|
} memlock;
|
|
|
|
struct sysctl_args {
|
|
int *name;
|
|
u_int namelen;
|
|
void *old;
|
|
size_t *oldlenp;
|
|
void *new;
|
|
size_t newlen;
|
|
};
|
|
|
|
int
|
|
__sysctl(p, uap, retval)
|
|
struct proc *p;
|
|
register struct sysctl_args *uap;
|
|
int *retval;
|
|
{
|
|
int error, dolock = 1;
|
|
u_int savelen = 0, oldlen = 0;
|
|
sysctlfn *fn;
|
|
int name[CTL_MAXNAME];
|
|
|
|
if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag)))
|
|
return (error);
|
|
/*
|
|
* all top-level sysctl names are non-terminal
|
|
*/
|
|
if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
|
|
return (EINVAL);
|
|
if (error = copyin(uap->name, &name, uap->namelen * sizeof(int)))
|
|
return (error);
|
|
|
|
switch (name[0]) {
|
|
case CTL_KERN:
|
|
fn = kern_sysctl;
|
|
if (name[2] != KERN_VNODE) /* XXX */
|
|
dolock = 0;
|
|
break;
|
|
case CTL_HW:
|
|
fn = hw_sysctl;
|
|
break;
|
|
case CTL_VM:
|
|
fn = vm_sysctl;
|
|
break;
|
|
case CTL_NET:
|
|
fn = net_sysctl;
|
|
break;
|
|
#ifdef notyet
|
|
case CTL_FS:
|
|
fn = fs_sysctl;
|
|
break;
|
|
#endif
|
|
case CTL_MACHDEP:
|
|
fn = cpu_sysctl;
|
|
break;
|
|
#ifdef DEBUG
|
|
case CTL_DEBUG:
|
|
fn = debug_sysctl;
|
|
break;
|
|
#endif
|
|
default:
|
|
return (EOPNOTSUPP);
|
|
}
|
|
|
|
if (uap->oldlenp &&
|
|
(error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
|
|
return (error);
|
|
if (uap->old != NULL) {
|
|
if (!useracc(uap->old, oldlen, B_WRITE))
|
|
return (EFAULT);
|
|
while (memlock.sl_lock) {
|
|
memlock.sl_want = 1;
|
|
sleep((caddr_t)&memlock, PRIBIO+1);
|
|
memlock.sl_locked++;
|
|
}
|
|
memlock.sl_lock = 1;
|
|
if (dolock)
|
|
vslock(uap->old, oldlen);
|
|
savelen = oldlen;
|
|
}
|
|
error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen,
|
|
uap->new, uap->newlen, p);
|
|
if (uap->old != NULL) {
|
|
if (dolock)
|
|
vsunlock(uap->old, savelen, B_WRITE);
|
|
memlock.sl_lock = 0;
|
|
if (memlock.sl_want) {
|
|
memlock.sl_want = 0;
|
|
wakeup((caddr_t)&memlock);
|
|
}
|
|
}
|
|
if (error)
|
|
return (error);
|
|
if (uap->oldlenp)
|
|
error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
|
|
*retval = oldlen;
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Attributes stored in the kernel.
|
|
*/
|
|
char hostname[MAXHOSTNAMELEN];
|
|
int hostnamelen;
|
|
char domainname[MAXHOSTNAMELEN];
|
|
int domainnamelen;
|
|
long hostid;
|
|
int securelevel = -1;
|
|
extern int vfs_update_wakeup;
|
|
extern int vfs_update_interval;
|
|
extern int osreldate;
|
|
|
|
/*
|
|
* kernel related system variables.
|
|
*/
|
|
int
|
|
kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
int *name;
|
|
u_int namelen;
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
size_t newlen;
|
|
struct proc *p;
|
|
{
|
|
int error, level, inthostid;
|
|
extern char ostype[], osrelease[], version[];
|
|
|
|
/* all sysctl names at this level are terminal */
|
|
if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
|
|
return (ENOTDIR); /* overloaded */
|
|
|
|
switch (name[0]) {
|
|
case KERN_OSTYPE:
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
|
|
case KERN_OSRELEASE:
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
|
|
case KERN_OSREV:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, BSD));
|
|
case KERN_VERSION:
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, version));
|
|
case KERN_OSRELDATE:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, osreldate));
|
|
case KERN_MAXVNODES:
|
|
return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
|
|
case KERN_MAXPROC:
|
|
return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
|
|
case KERN_MAXFILES:
|
|
return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
|
|
case KERN_UPDATEINTERVAL:
|
|
/*
|
|
* NB: this simple-minded approach only works because
|
|
* `tsleep' takes a timeout argument of 0 as meaning
|
|
* `no timeout'.
|
|
*/
|
|
error = sysctl_int(oldp, oldlenp, newp, newlen,
|
|
&vfs_update_interval);
|
|
if(!error) {
|
|
wakeup(&vfs_update_wakeup);
|
|
}
|
|
return error;
|
|
case KERN_ARGMAX:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
|
|
case KERN_SECURELVL:
|
|
level = securelevel;
|
|
if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
|
|
newp == NULL)
|
|
return (error);
|
|
if (level < securelevel && p->p_pid != 1)
|
|
return (EPERM);
|
|
securelevel = level;
|
|
return (0);
|
|
case KERN_HOSTNAME:
|
|
error = sysctl_string(oldp, oldlenp, newp, newlen,
|
|
hostname, sizeof(hostname));
|
|
if (newp && !error)
|
|
hostnamelen = newlen;
|
|
return (error);
|
|
case KERN_DOMAINNAME:
|
|
error = sysctl_string(oldp, oldlenp, newp, newlen,
|
|
domainname, sizeof(domainname));
|
|
if (newp && !error)
|
|
domainnamelen = newlen;
|
|
return (error);
|
|
case KERN_HOSTID:
|
|
inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
|
|
error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
|
|
hostid = inthostid;
|
|
return (error);
|
|
case KERN_CLOCKRATE:
|
|
return (sysctl_clockrate(oldp, oldlenp));
|
|
case KERN_BOOTTIME:
|
|
return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
|
|
sizeof(struct timeval)));
|
|
case KERN_VNODE:
|
|
return (sysctl_vnode(oldp, oldlenp));
|
|
case KERN_PROC:
|
|
return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
|
|
case KERN_FILE:
|
|
return (sysctl_file(oldp, oldlenp));
|
|
#ifdef GPROF
|
|
case KERN_PROF:
|
|
return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
|
|
newp, newlen));
|
|
#endif
|
|
case KERN_POSIX1:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
|
|
case KERN_NGROUPS:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
|
|
case KERN_JOB_CONTROL:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
case KERN_SAVED_IDS:
|
|
#ifdef _POSIX_SAVED_IDS
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
#else
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 0));
|
|
#endif
|
|
default:
|
|
return (EOPNOTSUPP);
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
/*
|
|
* hardware related system variables.
|
|
*/
|
|
int
|
|
hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
int *name;
|
|
u_int namelen;
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
size_t newlen;
|
|
struct proc *p;
|
|
{
|
|
extern char machine[], cpu_model[];
|
|
|
|
/* all sysctl names at this level are terminal */
|
|
if (namelen != 1)
|
|
return (ENOTDIR); /* overloaded */
|
|
|
|
switch (name[0]) {
|
|
case HW_MACHINE:
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, machine));
|
|
case HW_MODEL:
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
|
|
case HW_NCPU:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */
|
|
case HW_BYTEORDER:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
|
|
case HW_PHYSMEM:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
|
|
case HW_USERMEM:
|
|
return (sysctl_rdint(oldp, oldlenp, newp,
|
|
ctob(physmem - cnt.v_wire_count)));
|
|
case HW_PAGESIZE:
|
|
return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
|
|
default:
|
|
return (EOPNOTSUPP);
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/*
|
|
* Debugging related system variables.
|
|
*/
|
|
struct ctldebug debug0, debug1, debug2, debug3, debug4;
|
|
struct ctldebug debug5, debug6, debug7, debug8, debug9;
|
|
struct ctldebug debug10, debug11, debug12, debug13, debug14;
|
|
struct ctldebug debug15, debug16, debug17, debug18, debug19;
|
|
static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
|
|
&debug0, &debug1, &debug2, &debug3, &debug4,
|
|
&debug5, &debug6, &debug7, &debug8, &debug9,
|
|
&debug10, &debug11, &debug12, &debug13, &debug14,
|
|
&debug15, &debug16, &debug17, &debug18, &debug19,
|
|
};
|
|
int
|
|
debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
int *name;
|
|
u_int namelen;
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
size_t newlen;
|
|
struct proc *p;
|
|
{
|
|
struct ctldebug *cdp;
|
|
|
|
/* all sysctl names at this level are name and field */
|
|
if (namelen != 2)
|
|
return (ENOTDIR); /* overloaded */
|
|
cdp = debugvars[name[0]];
|
|
if (cdp->debugname == 0)
|
|
return (EOPNOTSUPP);
|
|
switch (name[1]) {
|
|
case CTL_DEBUG_NAME:
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
|
|
case CTL_DEBUG_VALUE:
|
|
return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
|
|
default:
|
|
return (EOPNOTSUPP);
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
/*
|
|
* Validate parameters and get old / set new parameters
|
|
* for an integer-valued sysctl function.
|
|
*/
|
|
int
|
|
sysctl_int(oldp, oldlenp, newp, newlen, valp)
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
size_t newlen;
|
|
int *valp;
|
|
{
|
|
int error = 0;
|
|
|
|
if (oldp && *oldlenp < sizeof(int))
|
|
return (ENOMEM);
|
|
if (newp && newlen != sizeof(int))
|
|
return (EINVAL);
|
|
*oldlenp = sizeof(int);
|
|
if (oldp)
|
|
error = copyout(valp, oldp, sizeof(int));
|
|
if (error == 0 && newp)
|
|
error = copyin(newp, valp, sizeof(int));
|
|
return (error);
|
|
}
|
|
|
|
/*
|
|
* As above, but read-only.
|
|
*/
|
|
int
|
|
sysctl_rdint(oldp, oldlenp, newp, val)
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
int val;
|
|
{
|
|
int error = 0;
|
|
|
|
if (oldp && *oldlenp < sizeof(int))
|
|
return (ENOMEM);
|
|
if (newp)
|
|
return (EPERM);
|
|
*oldlenp = sizeof(int);
|
|
if (oldp)
|
|
error = copyout((caddr_t)&val, oldp, sizeof(int));
|
|
return (error);
|
|
}
|
|
|
|
/*
|
|
* Validate parameters and get old / set new parameters
|
|
* for a string-valued sysctl function.
|
|
*/
|
|
int
|
|
sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
size_t newlen;
|
|
char *str;
|
|
int maxlen;
|
|
{
|
|
int len, error = 0;
|
|
|
|
len = strlen(str) + 1;
|
|
if (oldp && *oldlenp < len)
|
|
return (ENOMEM);
|
|
if (newp && newlen >= maxlen)
|
|
return (EINVAL);
|
|
if (oldp) {
|
|
*oldlenp = len;
|
|
error = copyout(str, oldp, len);
|
|
}
|
|
if (error == 0 && newp) {
|
|
error = copyin(newp, str, newlen);
|
|
str[newlen] = 0;
|
|
}
|
|
return (error);
|
|
}
|
|
|
|
/*
|
|
* As above, but read-only.
|
|
*/
|
|
int
|
|
sysctl_rdstring(oldp, oldlenp, newp, str)
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
char *str;
|
|
{
|
|
int len, error = 0;
|
|
|
|
len = strlen(str) + 1;
|
|
if (oldp && *oldlenp < len)
|
|
return (ENOMEM);
|
|
if (newp)
|
|
return (EPERM);
|
|
*oldlenp = len;
|
|
if (oldp)
|
|
error = copyout(str, oldp, len);
|
|
return (error);
|
|
}
|
|
|
|
/*
|
|
* Validate parameters and get old / set new parameters
|
|
* for a structure oriented sysctl function.
|
|
*/
|
|
int
|
|
sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
size_t newlen;
|
|
void *sp;
|
|
int len;
|
|
{
|
|
int error = 0;
|
|
|
|
if (oldp && *oldlenp < len)
|
|
return (ENOMEM);
|
|
if (newp && newlen > len)
|
|
return (EINVAL);
|
|
if (oldp) {
|
|
*oldlenp = len;
|
|
error = copyout(sp, oldp, len);
|
|
}
|
|
if (error == 0 && newp)
|
|
error = copyin(newp, sp, len);
|
|
return (error);
|
|
}
|
|
|
|
/*
|
|
* Validate parameters and get old parameters
|
|
* for a structure oriented sysctl function.
|
|
*/
|
|
int
|
|
sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp, *sp;
|
|
int len;
|
|
{
|
|
int error = 0;
|
|
|
|
if (oldp && *oldlenp < len)
|
|
return (ENOMEM);
|
|
if (newp)
|
|
return (EPERM);
|
|
*oldlenp = len;
|
|
if (oldp)
|
|
error = copyout(sp, oldp, len);
|
|
return (error);
|
|
}
|
|
|
|
/*
|
|
* Get file structures.
|
|
*/
|
|
int
|
|
sysctl_file(where, sizep)
|
|
char *where;
|
|
size_t *sizep;
|
|
{
|
|
int buflen, error;
|
|
struct file *fp;
|
|
char *start = where;
|
|
|
|
buflen = *sizep;
|
|
if (where == NULL) {
|
|
/*
|
|
* overestimate by 10 files
|
|
*/
|
|
*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* first copyout filehead
|
|
*/
|
|
if (buflen < sizeof(filehead)) {
|
|
*sizep = 0;
|
|
return (0);
|
|
}
|
|
if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
|
|
return (error);
|
|
buflen -= sizeof(filehead);
|
|
where += sizeof(filehead);
|
|
|
|
/*
|
|
* followed by an array of file structures
|
|
*/
|
|
for (fp = filehead; fp != NULL; fp = fp->f_filef) {
|
|
if (buflen < sizeof(struct file)) {
|
|
*sizep = where - start;
|
|
return (ENOMEM);
|
|
}
|
|
if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
|
|
return (error);
|
|
buflen -= sizeof(struct file);
|
|
where += sizeof(struct file);
|
|
}
|
|
*sizep = where - start;
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* try over estimating by 5 procs
|
|
*/
|
|
#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
|
|
|
|
int
|
|
sysctl_doproc(name, namelen, where, sizep)
|
|
int *name;
|
|
u_int namelen;
|
|
char *where;
|
|
size_t *sizep;
|
|
{
|
|
register struct proc *p;
|
|
register struct kinfo_proc *dp = (struct kinfo_proc *)where;
|
|
register int needed = 0;
|
|
int buflen = where != NULL ? *sizep : 0;
|
|
int doingzomb;
|
|
struct eproc eproc;
|
|
int error = 0;
|
|
|
|
if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
|
|
return (EINVAL);
|
|
p = (struct proc *)allproc;
|
|
doingzomb = 0;
|
|
again:
|
|
for (; p != NULL; p = p->p_next) {
|
|
/*
|
|
* Skip embryonic processes.
|
|
*/
|
|
if (p->p_stat == SIDL)
|
|
continue;
|
|
/*
|
|
* TODO - make more efficient (see notes below).
|
|
* do by session.
|
|
*/
|
|
switch (name[0]) {
|
|
|
|
case KERN_PROC_PID:
|
|
/* could do this with just a lookup */
|
|
if (p->p_pid != (pid_t)name[1])
|
|
continue;
|
|
break;
|
|
|
|
case KERN_PROC_PGRP:
|
|
/* could do this by traversing pgrp */
|
|
if (p->p_pgrp->pg_id != (pid_t)name[1])
|
|
continue;
|
|
break;
|
|
|
|
case KERN_PROC_TTY:
|
|
if ((p->p_flag & P_CONTROLT) == 0 ||
|
|
p->p_session->s_ttyp == NULL ||
|
|
p->p_session->s_ttyp->t_dev != (dev_t)name[1])
|
|
continue;
|
|
break;
|
|
|
|
case KERN_PROC_UID:
|
|
if (p->p_ucred->cr_uid != (uid_t)name[1])
|
|
continue;
|
|
break;
|
|
|
|
case KERN_PROC_RUID:
|
|
if (p->p_cred->p_ruid != (uid_t)name[1])
|
|
continue;
|
|
break;
|
|
}
|
|
if (buflen >= sizeof(struct kinfo_proc)) {
|
|
fill_eproc(p, &eproc);
|
|
if (error = copyout((caddr_t)p, &dp->kp_proc,
|
|
sizeof(struct proc)))
|
|
return (error);
|
|
if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
|
|
sizeof(eproc)))
|
|
return (error);
|
|
dp++;
|
|
buflen -= sizeof(struct kinfo_proc);
|
|
}
|
|
needed += sizeof(struct kinfo_proc);
|
|
}
|
|
if (doingzomb == 0) {
|
|
p = zombproc;
|
|
doingzomb++;
|
|
goto again;
|
|
}
|
|
if (where != NULL) {
|
|
*sizep = (caddr_t)dp - where;
|
|
if (needed > *sizep)
|
|
return (ENOMEM);
|
|
} else {
|
|
needed += KERN_PROCSLOP;
|
|
*sizep = needed;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Fill in an eproc structure for the specified process.
|
|
*/
|
|
void
|
|
fill_eproc(p, ep)
|
|
register struct proc *p;
|
|
register struct eproc *ep;
|
|
{
|
|
register struct tty *tp;
|
|
|
|
ep->e_paddr = p;
|
|
ep->e_sess = p->p_pgrp->pg_session;
|
|
ep->e_pcred = *p->p_cred;
|
|
ep->e_ucred = *p->p_ucred;
|
|
if (p->p_stat == SIDL || p->p_stat == SZOMB) {
|
|
ep->e_vm.vm_rssize = 0;
|
|
ep->e_vm.vm_tsize = 0;
|
|
ep->e_vm.vm_dsize = 0;
|
|
ep->e_vm.vm_ssize = 0;
|
|
#ifndef sparc
|
|
/* ep->e_vm.vm_pmap = XXX; */
|
|
#endif
|
|
} else {
|
|
register struct vmspace *vm = p->p_vmspace;
|
|
|
|
#ifdef pmap_resident_count
|
|
ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/
|
|
#else
|
|
ep->e_vm.vm_rssize = vm->vm_rssize;
|
|
#endif
|
|
ep->e_vm.vm_tsize = vm->vm_tsize;
|
|
ep->e_vm.vm_dsize = vm->vm_dsize;
|
|
ep->e_vm.vm_ssize = vm->vm_ssize;
|
|
#ifndef sparc
|
|
ep->e_vm.vm_pmap = vm->vm_pmap;
|
|
#endif
|
|
}
|
|
if (p->p_pptr)
|
|
ep->e_ppid = p->p_pptr->p_pid;
|
|
else
|
|
ep->e_ppid = 0;
|
|
ep->e_pgid = p->p_pgrp->pg_id;
|
|
ep->e_jobc = p->p_pgrp->pg_jobc;
|
|
if ((p->p_flag & P_CONTROLT) &&
|
|
(tp = ep->e_sess->s_ttyp)) {
|
|
ep->e_tdev = tp->t_dev;
|
|
ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
|
|
ep->e_tsess = tp->t_session;
|
|
} else
|
|
ep->e_tdev = NODEV;
|
|
ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
|
|
if (SESS_LEADER(p))
|
|
ep->e_flag |= EPROC_SLEADER;
|
|
if (p->p_wmesg)
|
|
strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
|
|
ep->e_xsize = ep->e_xrssize = 0;
|
|
ep->e_xccount = ep->e_xswrss = 0;
|
|
}
|
|
|
|
#ifdef COMPAT_43
|
|
#include <sys/socket.h>
|
|
#define KINFO_PROC (0<<8)
|
|
#define KINFO_RT (1<<8)
|
|
#define KINFO_VNODE (2<<8)
|
|
#define KINFO_FILE (3<<8)
|
|
#define KINFO_METER (4<<8)
|
|
#define KINFO_LOADAVG (5<<8)
|
|
#define KINFO_CLOCKRATE (6<<8)
|
|
|
|
struct getkerninfo_args {
|
|
int op;
|
|
char *where;
|
|
int *size;
|
|
int arg;
|
|
};
|
|
|
|
int
|
|
ogetkerninfo(p, uap, retval)
|
|
struct proc *p;
|
|
register struct getkerninfo_args *uap;
|
|
int *retval;
|
|
{
|
|
int error, name[5];
|
|
u_int size;
|
|
|
|
if (uap->size &&
|
|
(error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size))))
|
|
return (error);
|
|
|
|
switch (uap->op & 0xff00) {
|
|
|
|
case KINFO_RT:
|
|
name[0] = PF_ROUTE;
|
|
name[1] = 0;
|
|
name[2] = (uap->op & 0xff0000) >> 16;
|
|
name[3] = uap->op & 0xff;
|
|
name[4] = uap->arg;
|
|
error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p);
|
|
break;
|
|
|
|
case KINFO_VNODE:
|
|
name[0] = KERN_VNODE;
|
|
error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
|
|
break;
|
|
|
|
case KINFO_PROC:
|
|
name[0] = KERN_PROC;
|
|
name[1] = uap->op & 0xff;
|
|
name[2] = uap->arg;
|
|
error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p);
|
|
break;
|
|
|
|
case KINFO_FILE:
|
|
name[0] = KERN_FILE;
|
|
error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
|
|
break;
|
|
|
|
case KINFO_METER:
|
|
name[0] = VM_METER;
|
|
error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
|
|
break;
|
|
|
|
case KINFO_LOADAVG:
|
|
name[0] = VM_LOADAVG;
|
|
error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
|
|
break;
|
|
|
|
case KINFO_CLOCKRATE:
|
|
name[0] = KERN_CLOCKRATE;
|
|
error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
|
|
break;
|
|
|
|
default:
|
|
return (EOPNOTSUPP);
|
|
}
|
|
if (error)
|
|
return (error);
|
|
*retval = size;
|
|
if (uap->size)
|
|
error = copyout((caddr_t)&size, (caddr_t)uap->size,
|
|
sizeof(size));
|
|
return (error);
|
|
}
|
|
#endif /* COMPAT_43 */
|