xref: /csrg-svn/sys/kern/kern_sysctl.c (revision 58461)
157843Smckusick /*-
257843Smckusick  * Copyright (c) 1982, 1986, 1989, 1993 Regents of the University of California.
339963Smarc  * All rights reserved.
439963Smarc  *
557843Smckusick  * This code is derived from software contributed to Berkeley by
657843Smckusick  * Mike Karels at Berkeley Software Design, Inc.
757843Smckusick  *
844435Sbostic  * %sccs.include.redist.c%
939963Smarc  *
10*58461Smckusick  *	@(#)kern_sysctl.c	7.30 (Berkeley) 03/04/93
1139963Smarc  */
1239963Smarc 
1357843Smckusick /*
1457843Smckusick  * sysctl system call.
1557843Smckusick  */
1657843Smckusick 
1756517Sbostic #include <sys/param.h>
1857843Smckusick #include <sys/systm.h>
1957843Smckusick #include <sys/malloc.h>
2056517Sbostic #include <sys/proc.h>
2157843Smckusick #include <sys/file.h>
2257843Smckusick #include <sys/sysctl.h>
2357843Smckusick #include <sys/unistd.h>
2457843Smckusick #include <sys/buf.h>
2556517Sbostic #include <sys/ioctl.h>
2656517Sbostic #include <sys/tty.h>
2739963Smarc 
2856517Sbostic #include <vm/vm.h>
2948407Skarels 
3056517Sbostic #include <sys/kinfo_proc.h>
3148407Skarels 
3257843Smckusick sysctlfn kern_sysctl;
3357843Smckusick sysctlfn hw_sysctl;
3457843Smckusick extern sysctlfn vm_sysctl;
3557843Smckusick extern sysctlfn fs_sysctl;
3657843Smckusick extern sysctlfn net_sysctl;
3757843Smckusick extern sysctlfn cpu_sysctl;
3840068Smarc 
3957843Smckusick /*
4057843Smckusick  * Locking and stats
4157843Smckusick  */
4257843Smckusick static struct sysctl_lock {
4357843Smckusick 	int	sl_lock;
4457843Smckusick 	int	sl_want;
4557843Smckusick 	int	sl_locked;
4657843Smckusick } memlock;
4757843Smckusick 
4857843Smckusick struct sysctl_args {
4957843Smckusick 	int	*name;
5057843Smckusick 	u_int	namelen;
5157843Smckusick 	void	*old;
5257843Smckusick 	u_int	*oldlenp;
5357843Smckusick 	void	*new;
5457843Smckusick 	u_int	newlen;
5554923Storek };
5657843Smckusick 
5757843Smckusick sysctl(p, uap, retval)
5843444Smckusick 	struct proc *p;
5957843Smckusick 	register struct sysctl_args *uap;
6043444Smckusick 	int *retval;
6143444Smckusick {
6257843Smckusick 	int error, dolock = 1;
6357843Smckusick 	u_int savelen, oldlen = 0;
6457843Smckusick 	sysctlfn *fn;
6557843Smckusick 	int name[CTL_MAXNAME];
6639963Smarc 
6757843Smckusick 	if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag)))
6857843Smckusick 		return (error);
6957843Smckusick 	/*
7057843Smckusick 	 * all top-level sysctl names are non-terminal
7157843Smckusick 	 */
7257843Smckusick 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
7357843Smckusick 		return (EINVAL);
7457843Smckusick 	if (error = copyin(uap->name, &name, uap->namelen * sizeof(int)))
7557843Smckusick 		return (error);
7639963Smarc 
7757843Smckusick 	switch (name[0]) {
7857843Smckusick 	case CTL_KERN:
7957843Smckusick 		fn = kern_sysctl;
8057843Smckusick 		if (name[2] != KERN_VNODE)	/* XXX */
8157843Smckusick 			dolock = 0;
8239963Smarc 		break;
8357843Smckusick 	case CTL_HW:
8457843Smckusick 		fn = hw_sysctl;
8540068Smarc 		break;
8657843Smckusick 	case CTL_VM:
8757843Smckusick 		fn = vm_sysctl;
8841181Smarc 		break;
8957843Smckusick 	case CTL_NET:
9057843Smckusick 		fn = net_sysctl;
9150149Smarc 		break;
9257843Smckusick #ifdef notyet
9357843Smckusick 	case CTL_FS:
9457843Smckusick 		fn = fs_sysctl;
9550909Smckusick 		break;
9657843Smckusick 	case CTL_DEBUG:
9757843Smckusick 		fn = debug_sysctl;
9852669Smckusick 		break;
9957843Smckusick 	case CTL_MACHDEP:
10057843Smckusick 		fn = cpu_sysctl;
10152669Smckusick 		break;
10257843Smckusick #endif
10339963Smarc 	default:
10457843Smckusick 		return (EOPNOTSUPP);
10539963Smarc 	}
10657843Smckusick 
10757843Smckusick 	if (uap->oldlenp &&
10857843Smckusick 	    (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
10957843Smckusick 		return (error);
11057843Smckusick 	if (uap->old != NULL) {
11157843Smckusick 		if (!useracc(uap->old, oldlen, B_WRITE))
11257843Smckusick 			return (EFAULT);
11357843Smckusick 		while (memlock.sl_lock) {
11457843Smckusick 			memlock.sl_want = 1;
11557843Smckusick 			sleep((caddr_t)&memlock, PRIBIO+1);
11657843Smckusick 			memlock.sl_locked++;
11757843Smckusick 		}
11857843Smckusick 		memlock.sl_lock = 1;
11957843Smckusick 		if (dolock)
12057843Smckusick 			vslock(uap->old, oldlen);
12157843Smckusick 		savelen = oldlen;
12240813Smarc 	}
12357843Smckusick 	error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen,
12458415Smckusick 	    uap->new, uap->newlen, p);
12557843Smckusick 	if (uap->old != NULL) {
12657843Smckusick 		if (dolock)
12757843Smckusick 			vsunlock(uap->old, savelen, B_WRITE);
12857843Smckusick 		memlock.sl_lock = 0;
12957843Smckusick 		if (memlock.sl_want) {
13057843Smckusick 			memlock.sl_want = 0;
13157843Smckusick 			wakeup((caddr_t)&memlock);
13257843Smckusick 		}
13340206Smarc 	}
13457843Smckusick 	if (error)
13557843Smckusick 		return (error);
13657843Smckusick 	if (uap->oldlenp)
13757843Smckusick 		error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
13857843Smckusick 	*retval = oldlen;
13957843Smckusick 	return (0);
14057843Smckusick }
14140206Smarc 
14257843Smckusick /*
14357843Smckusick  * Attributes stored in the kernel.
14457843Smckusick  */
14557843Smckusick char hostname[MAXHOSTNAMELEN];
14657843Smckusick int hostnamelen;
14757843Smckusick long hostid;
14858415Smckusick int securelevel;
14957843Smckusick 
15058415Smckusick /*
15158415Smckusick  * kernel related system variables.
15258415Smckusick  */
15358415Smckusick kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
15457843Smckusick 	int *name;
15557843Smckusick 	u_int namelen;
15657843Smckusick 	void *oldp;
15757843Smckusick 	u_int *oldlenp;
15857843Smckusick 	void *newp;
15957843Smckusick 	u_int newlen;
16058415Smckusick 	struct proc *p;
16157843Smckusick {
16258415Smckusick 	int error, level;
16357843Smckusick 	extern char ostype[], osrelease[], version[];
16457843Smckusick 
16557843Smckusick 	/* all sysctl names at this level are terminal */
16657843Smckusick 	if (namelen != 1 && name[0] != KERN_PROC)
16757843Smckusick 		return (ENOTDIR);		/* overloaded */
16857843Smckusick 
16957843Smckusick 	switch (name[0]) {
17057843Smckusick 	case KERN_OSTYPE:
17157843Smckusick 		return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
17257843Smckusick 	case KERN_OSRELEASE:
17357843Smckusick 		return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
17457843Smckusick 	case KERN_OSREV:
17557843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp, BSD));
17657843Smckusick 	case KERN_VERSION:
17757843Smckusick 		return (sysctl_rdstring(oldp, oldlenp, newp, version));
17857843Smckusick 	case KERN_POSIX1:
17957843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
18057843Smckusick 	case KERN_MAXPROC:
18157843Smckusick 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
18257843Smckusick 	case KERN_MAXFILES:
18357843Smckusick 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
18457843Smckusick 	case KERN_ARGMAX:
18557843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
18657843Smckusick 	case KERN_HOSTNAME:
18757843Smckusick 		error = sysctl_string(oldp, oldlenp, newp, newlen,
18857843Smckusick 		    hostname, sizeof(hostname));
18957843Smckusick 		if (!error)
19057843Smckusick 			hostnamelen = newlen;
19157843Smckusick 		return (error);
19257843Smckusick 	case KERN_HOSTID:
19357843Smckusick 		return (sysctl_int(oldp, oldlenp, newp, newlen, &hostid));
19458415Smckusick 	case KERN_SECURELVL:
19558415Smckusick 		level = securelevel;
19658415Smckusick 		if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
19758415Smckusick 		    newp == NULL)
19858415Smckusick 			return (error);
19958415Smckusick 		if (level < securelevel && p->p_pid != 1)
20058415Smckusick 			return (EPERM);
20158415Smckusick 		securelevel = level;
20258415Smckusick 		return (0);
20357843Smckusick 	case KERN_CLOCKRATE:
20457843Smckusick 		return (sysctl_clockrate(oldp, oldlenp));
20557843Smckusick 	case KERN_FILE:
20657843Smckusick 		return (sysctl_file(oldp, oldlenp));
20757843Smckusick 	case KERN_VNODE:
20857843Smckusick 		return (sysctl_vnode(oldp, oldlenp));
20957843Smckusick 	case KERN_PROC:
21057843Smckusick 		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
21157843Smckusick 	default:
21257843Smckusick 		return (EOPNOTSUPP);
21352405Storek 	}
21457843Smckusick 	/* NOTREACHED */
21557843Smckusick }
21657843Smckusick 
21758415Smckusick /*
21858415Smckusick  * hardware related system variables.
21958415Smckusick  */
22058415Smckusick hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
22157843Smckusick 	int *name;
22257843Smckusick 	u_int namelen;
22357843Smckusick 	void *oldp;
22457843Smckusick 	u_int *oldlenp;
22557843Smckusick 	void *newp;
22657843Smckusick 	u_int newlen;
22758415Smckusick 	struct proc *p;
22857843Smckusick {
22957843Smckusick 	extern char machine[], cpu_model[];
23057843Smckusick 
23157843Smckusick 	/* all sysctl names at this level are terminal */
23257843Smckusick 	if (namelen != 1)
23357843Smckusick 		return (ENOTDIR);		/* overloaded */
23457843Smckusick 
23557843Smckusick 	switch (name[0]) {
23657843Smckusick 	case HW_MACHINE:
23757843Smckusick 		return (sysctl_rdstring(oldp, oldlenp, newp, machine));
23857843Smckusick 	case HW_MODEL:
23957843Smckusick 		return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
24057843Smckusick 	case HW_NCPU:
24157843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp, 1));	/* XXX */
24257843Smckusick 	case HW_CPUSPEED:
24357843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
24457843Smckusick 	case HW_PHYSMEM:
24557843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
24657843Smckusick 	case HW_USERMEM:
24757843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp,
24857843Smckusick 		    ctob(physmem - cnt.v_wire_count)));
24957843Smckusick 	case HW_PAGESIZE:
25057843Smckusick 		return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
25157843Smckusick 	default:
25257843Smckusick 		return (EOPNOTSUPP);
25357843Smckusick 	}
25457843Smckusick 	/* NOTREACHED */
25557843Smckusick }
25657843Smckusick 
25757843Smckusick /*
25857843Smckusick  * Validate parameters and get old / set new parameters
25957843Smckusick  * for an integer-valued sysctl function.
26057843Smckusick  */
26157843Smckusick sysctl_int(oldp, oldlenp, newp, newlen, valp)
26257843Smckusick 	void *oldp;
26357843Smckusick 	u_int *oldlenp;
26457843Smckusick 	void *newp;
26557843Smckusick 	u_int newlen;
26657843Smckusick 	int *valp;
26757843Smckusick {
26857843Smckusick 	int error = 0;
26957843Smckusick 
27057843Smckusick 	if (oldp && *oldlenp < sizeof(int))
27157843Smckusick 		return (ENOMEM);
27257843Smckusick 	if (newp && newlen != sizeof(int))
27357843Smckusick 		return (EINVAL);
27457843Smckusick 	*oldlenp = sizeof(int);
27557843Smckusick 	if (oldp)
27657843Smckusick 		error = copyout(valp, oldp, sizeof(int));
27757843Smckusick 	if (error == 0 && newp)
27857843Smckusick 		error = copyin(newp, valp, sizeof(int));
27943444Smckusick 	return (error);
28039963Smarc }
28139963Smarc 
28257843Smckusick /*
28357843Smckusick  * As above, but read-only.
28457843Smckusick  */
28557843Smckusick sysctl_rdint(oldp, oldlenp, newp, val)
28657843Smckusick 	void *oldp;
28757843Smckusick 	u_int *oldlenp;
28857843Smckusick 	void *newp;
28957843Smckusick 	int val;
29057843Smckusick {
29157843Smckusick 	int error = 0;
29257843Smckusick 
29357843Smckusick 	if (oldp && *oldlenp < sizeof(int))
29457843Smckusick 		return (ENOMEM);
29557843Smckusick 	if (newp)
29657843Smckusick 		return (EPERM);
29757843Smckusick 	*oldlenp = sizeof(int);
29857843Smckusick 	if (oldp)
29957843Smckusick 		error = copyout((caddr_t)&val, oldp, sizeof(int));
30057843Smckusick 	return (error);
30157843Smckusick }
30257843Smckusick 
30357843Smckusick /*
30457843Smckusick  * Validate parameters and get old / set new parameters
30557843Smckusick  * for a string-valued sysctl function.
30657843Smckusick  */
30757843Smckusick sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
30857843Smckusick 	void *oldp;
30957843Smckusick 	u_int *oldlenp;
31057843Smckusick 	void *newp;
31157843Smckusick 	u_int newlen;
31257843Smckusick 	char *str;
31357843Smckusick 	int maxlen;
31457843Smckusick {
31557843Smckusick 	int len, error = 0;
31657843Smckusick 
31757843Smckusick 	len = strlen(str) + 1;
31857843Smckusick 	if (oldp && *oldlenp < len)
31957843Smckusick 		return (ENOMEM);
32057843Smckusick 	if (newp && newlen >= maxlen)
32157843Smckusick 		return (EINVAL);
32258128Sralph 	if (oldp) {
32358128Sralph 		*oldlenp = len;
32457843Smckusick 		error = copyout(str, oldp, len);
32558128Sralph 	}
32657843Smckusick 	if (error == 0 && newp) {
32757843Smckusick 		error = copyin(newp, str, newlen);
32857843Smckusick 		str[newlen] = 0;
32957843Smckusick 	}
33057843Smckusick 	return (error);
33157843Smckusick }
33257843Smckusick 
33357843Smckusick /*
33457843Smckusick  * As above, but read-only.
33557843Smckusick  */
33657843Smckusick sysctl_rdstring(oldp, oldlenp, newp, str)
33757843Smckusick 	void *oldp;
33857843Smckusick 	u_int *oldlenp;
33957843Smckusick 	void *newp;
34057843Smckusick 	char *str;
34157843Smckusick {
34257843Smckusick 	int len, error = 0;
34357843Smckusick 
34457843Smckusick 	len = strlen(str) + 1;
34557843Smckusick 	if (oldp && *oldlenp < len)
34657843Smckusick 		return (ENOMEM);
34757843Smckusick 	if (newp)
34857843Smckusick 		return (EPERM);
34957843Smckusick 	*oldlenp = len;
35057843Smckusick 	if (oldp)
35157843Smckusick 		error = copyout(str, oldp, len);
35257843Smckusick 	return (error);
35357843Smckusick }
35457843Smckusick 
35557843Smckusick /*
35657843Smckusick  * Validate parameters and get old parameters
35757843Smckusick  * for a structure oriented sysctl function.
35857843Smckusick  */
35957843Smckusick sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
36057843Smckusick 	void *oldp;
36157843Smckusick 	u_int *oldlenp;
36257843Smckusick 	void *newp;
36357843Smckusick 	void *sp;
36457843Smckusick 	int len;
36557843Smckusick {
36657843Smckusick 	int error = 0;
36757843Smckusick 
36857843Smckusick 	if (oldp && *oldlenp < len)
36957843Smckusick 		return (ENOMEM);
37057843Smckusick 	if (newp)
37157843Smckusick 		return (EPERM);
37257843Smckusick 	*oldlenp = len;
37357843Smckusick 	if (oldp)
37457843Smckusick 		error = copyout(sp, oldp, len);
37557843Smckusick 	return (error);
37657843Smckusick }
37757843Smckusick 
37857843Smckusick /*
37957843Smckusick  * Get file structures.
38057843Smckusick  */
38157843Smckusick sysctl_file(where, sizep)
38257843Smckusick 	char *where;
38357843Smckusick 	int *sizep;
38457843Smckusick {
38557843Smckusick 	int buflen, error;
38657843Smckusick 	struct file *fp;
38757843Smckusick 	char *start = where;
38857843Smckusick 
38957843Smckusick 	buflen = *sizep;
39057843Smckusick 	if (where == NULL) {
39157843Smckusick 		/*
39257843Smckusick 		 * overestimate by 10 files
39357843Smckusick 		 */
39457843Smckusick 		*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
39557843Smckusick 		return (0);
39657843Smckusick 	}
39757843Smckusick 
39857843Smckusick 	/*
39957843Smckusick 	 * first copyout filehead
40057843Smckusick 	 */
40157843Smckusick 	if (buflen < sizeof(filehead)) {
40257843Smckusick 		*sizep = 0;
40357843Smckusick 		return (0);
40457843Smckusick 	}
40557843Smckusick 	if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
40657843Smckusick 		return (error);
40757843Smckusick 	buflen += sizeof(filehead);
40857843Smckusick 	where += sizeof(filehead);
40957843Smckusick 
41057843Smckusick 	/*
41157843Smckusick 	 * followed by an array of file structures
41257843Smckusick 	 */
41357843Smckusick 	for (fp = filehead; fp != NULL; fp = fp->f_filef) {
41457843Smckusick 		if (buflen < sizeof(struct file)) {
41557843Smckusick 			*sizep = where - start;
41657843Smckusick 			return (ENOMEM);
41757843Smckusick 		}
41857843Smckusick 		if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
41957843Smckusick 			return (error);
42057843Smckusick 		buflen -= sizeof(struct file);
42157843Smckusick 		where += sizeof(struct file);
42257843Smckusick 	}
42357843Smckusick 	*sizep = where - start;
42457843Smckusick 	return (0);
42557843Smckusick }
42657843Smckusick 
42739963Smarc /*
42839963Smarc  * try over estimating by 5 procs
42939963Smarc  */
43057843Smckusick #define KERN_PROCSLOP	(5 * sizeof (struct kinfo_proc))
43139963Smarc 
43257843Smckusick sysctl_doproc(name, namelen, where, sizep)
43357843Smckusick 	int *name;
43457843Smckusick 	int namelen;
43539963Smarc 	char *where;
43657843Smckusick 	int *sizep;
43739963Smarc {
43839963Smarc 	register struct proc *p;
43943419Smarc 	register struct kinfo_proc *dp = (struct kinfo_proc *)where;
44057843Smckusick 	register int needed = 0;
44157843Smckusick 	int buflen = where != NULL ? *sizep : 0;
44239963Smarc 	int doingzomb;
44340067Smarc 	struct eproc eproc;
44439963Smarc 	int error = 0;
44539963Smarc 
44657843Smckusick 	if (namelen != 2)
44757843Smckusick 		return (EINVAL);
44854755Storek 	p = (struct proc *)allproc;
44939963Smarc 	doingzomb = 0;
45039963Smarc again:
45139963Smarc 	for (; p != NULL; p = p->p_nxt) {
45253819Smckusick 		/*
45353819Smckusick 		 * Skip embryonic processes.
45453819Smckusick 		 */
45553819Smckusick 		if (p->p_stat == SIDL)
45653819Smckusick 			continue;
45739963Smarc 		/*
45839963Smarc 		 * TODO - make more efficient (see notes below).
45939963Smarc 		 * do by session.
46039963Smarc 		 */
46157843Smckusick 		switch (name[0]) {
46239963Smarc 
46357843Smckusick 		case KERN_PROC_PID:
46439963Smarc 			/* could do this with just a lookup */
46557843Smckusick 			if (p->p_pid != (pid_t)name[1])
46639963Smarc 				continue;
46739963Smarc 			break;
46839963Smarc 
46957843Smckusick 		case KERN_PROC_PGRP:
47039963Smarc 			/* could do this by traversing pgrp */
47157843Smckusick 			if (p->p_pgrp->pg_id != (pid_t)name[1])
47239963Smarc 				continue;
47339963Smarc 			break;
47439963Smarc 
47557843Smckusick 		case KERN_PROC_TTY:
47639963Smarc 			if ((p->p_flag&SCTTY) == 0 ||
47739963Smarc 			    p->p_session->s_ttyp == NULL ||
47857843Smckusick 			    p->p_session->s_ttyp->t_dev != (dev_t)name[1])
47939963Smarc 				continue;
48039963Smarc 			break;
48139963Smarc 
48257843Smckusick 		case KERN_PROC_UID:
48357843Smckusick 			if (p->p_ucred->cr_uid != (uid_t)name[1])
48439963Smarc 				continue;
48539963Smarc 			break;
48639963Smarc 
48757843Smckusick 		case KERN_PROC_RUID:
48857843Smckusick 			if (p->p_cred->p_ruid != (uid_t)name[1])
48939963Smarc 				continue;
49039963Smarc 			break;
49139963Smarc 		}
49257843Smckusick 		if (buflen >= sizeof(struct kinfo_proc)) {
49348407Skarels 			fill_eproc(p, &eproc);
49443419Smarc 			if (error = copyout((caddr_t)p, &dp->kp_proc,
49557843Smckusick 			    sizeof(struct proc)))
49639963Smarc 				return (error);
49743419Smarc 			if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
49857843Smckusick 			    sizeof(eproc)))
49939963Smarc 				return (error);
50043419Smarc 			dp++;
50157843Smckusick 			buflen -= sizeof(struct kinfo_proc);
50239963Smarc 		}
50357843Smckusick 		needed += sizeof(struct kinfo_proc);
50439963Smarc 	}
50539963Smarc 	if (doingzomb == 0) {
50639963Smarc 		p = zombproc;
50739963Smarc 		doingzomb++;
50839963Smarc 		goto again;
50939963Smarc 	}
51057843Smckusick 	if (where != NULL) {
51157843Smckusick 		*sizep = (caddr_t)dp - where;
51257843Smckusick 		if (needed > *sizep)
51357843Smckusick 			return (ENOMEM);
51457843Smckusick 	} else {
51557843Smckusick 		needed += KERN_PROCSLOP;
51657843Smckusick 		*sizep = needed;
51757843Smckusick 	}
51839963Smarc 	return (0);
51939963Smarc }
52048407Skarels 
52148407Skarels /*
52248407Skarels  * Fill in an eproc structure for the specified process.
52348407Skarels  */
52448407Skarels void
52548407Skarels fill_eproc(p, ep)
52648407Skarels 	register struct proc *p;
52748407Skarels 	register struct eproc *ep;
52848407Skarels {
52948407Skarels 	register struct tty *tp;
53048407Skarels 
53148407Skarels 	ep->e_paddr = p;
53248407Skarels 	ep->e_sess = p->p_pgrp->pg_session;
53348407Skarels 	ep->e_pcred = *p->p_cred;
53448407Skarels 	ep->e_ucred = *p->p_ucred;
53552405Storek 	if (p->p_stat == SIDL || p->p_stat == SZOMB) {
53652405Storek 		ep->e_vm.vm_rssize = 0;
53752405Storek 		ep->e_vm.vm_tsize = 0;
53852405Storek 		ep->e_vm.vm_dsize = 0;
53952405Storek 		ep->e_vm.vm_ssize = 0;
54052405Storek #ifndef sparc
54152405Storek 		/* ep->e_vm.vm_pmap = XXX; */
54252405Storek #endif
54352405Storek 	} else {
54452405Storek 		register struct vmspace *vm = p->p_vmspace;
54552405Storek 
54652405Storek 		ep->e_vm.vm_rssize = vm->vm_rssize;
54752405Storek 		ep->e_vm.vm_tsize = vm->vm_tsize;
54852405Storek 		ep->e_vm.vm_dsize = vm->vm_dsize;
54952405Storek 		ep->e_vm.vm_ssize = vm->vm_ssize;
55052405Storek #ifndef sparc
55152405Storek 		ep->e_vm.vm_pmap = vm->vm_pmap;
55252405Storek #endif
55352405Storek 	}
55449141Skarels 	if (p->p_pptr)
55549141Skarels 		ep->e_ppid = p->p_pptr->p_pid;
55649141Skarels 	else
55749141Skarels 		ep->e_ppid = 0;
55848407Skarels 	ep->e_pgid = p->p_pgrp->pg_id;
55948407Skarels 	ep->e_jobc = p->p_pgrp->pg_jobc;
56048407Skarels 	if ((p->p_flag&SCTTY) &&
56148407Skarels 	     (tp = ep->e_sess->s_ttyp)) {
56248407Skarels 		ep->e_tdev = tp->t_dev;
56350022Skarels 		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
56448407Skarels 		ep->e_tsess = tp->t_session;
56548407Skarels 	} else
56648407Skarels 		ep->e_tdev = NODEV;
56748407Skarels 	ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
56848407Skarels 	if (SESS_LEADER(p))
56948407Skarels 		ep->e_flag |= EPROC_SLEADER;
57048407Skarels 	if (p->p_wmesg)
57148407Skarels 		strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
57248407Skarels 	ep->e_xsize = ep->e_xrssize = 0;
57348407Skarels 	ep->e_xccount = ep->e_xswrss = 0;
57448407Skarels }
57550149Smarc 
57657843Smckusick #ifdef COMPAT_43
57757843Smckusick #include <sys/socket.h>
57857906Smckusick #define	KINFO_PROC		(0<<8)
57957906Smckusick #define	KINFO_RT		(1<<8)
58057906Smckusick #define	KINFO_VNODE		(2<<8)
58157906Smckusick #define	KINFO_FILE		(3<<8)
58257906Smckusick #define	KINFO_METER		(4<<8)
58357906Smckusick #define	KINFO_LOADAVG		(5<<8)
58457906Smckusick #define	KINFO_CLOCKRATE		(6<<8)
58557843Smckusick 
58657843Smckusick struct getkerninfo_args {
58757843Smckusick 	int	op;
58857843Smckusick 	char	*where;
58957843Smckusick 	int	*size;
59057843Smckusick 	int	arg;
59157843Smckusick };
59257843Smckusick 
59357843Smckusick getkerninfo(p, uap, retval)
59457843Smckusick 	struct proc *p;
59557843Smckusick 	register struct getkerninfo_args *uap;
59657843Smckusick 	int *retval;
59750149Smarc {
59857843Smckusick 	int error, name[5];
59957843Smckusick 	u_int size;
60050149Smarc 
601*58461Smckusick 	if (uap->size &&
602*58461Smckusick 	    error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))
60357843Smckusick 		return (error);
60450149Smarc 
60557906Smckusick 	switch (uap->op & 0xff00) {
60650149Smarc 
60757843Smckusick 	case KINFO_RT:
60857843Smckusick 		name[0] = PF_ROUTE;
60957843Smckusick 		name[1] = 0;
61057843Smckusick 		name[2] = (uap->op & 0xff0000) >> 16;
61157843Smckusick 		name[3] = uap->op & 0xff;
61257843Smckusick 		name[4] = uap->arg;
61358415Smckusick 		error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p);
61457843Smckusick 		break;
61557843Smckusick 
61657843Smckusick 	case KINFO_VNODE:
61757843Smckusick 		name[0] = KERN_VNODE;
61858415Smckusick 		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
61957843Smckusick 		break;
62057843Smckusick 
62157843Smckusick 	case KINFO_PROC:
62257843Smckusick 		name[0] = KERN_PROC;
62357843Smckusick 		name[1] = uap->op & 0xff;
62457843Smckusick 		name[2] = uap->arg;
62558415Smckusick 		error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p);
62657843Smckusick 		break;
62757843Smckusick 
62857843Smckusick 	case KINFO_FILE:
62957843Smckusick 		name[0] = KERN_FILE;
63058415Smckusick 		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
63157843Smckusick 		break;
63257843Smckusick 
63357843Smckusick 	case KINFO_METER:
63457843Smckusick 		name[0] = VM_METER;
63558415Smckusick 		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
63657843Smckusick 		break;
63757843Smckusick 
63857843Smckusick 	case KINFO_LOADAVG:
63957843Smckusick 		name[0] = VM_LOADAVG;
64058415Smckusick 		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
64157843Smckusick 		break;
64257843Smckusick 
64357843Smckusick 	case KINFO_CLOCKRATE:
64457843Smckusick 		name[0] = KERN_CLOCKRATE;
64558415Smckusick 		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
64657843Smckusick 		break;
64757843Smckusick 
64857843Smckusick 	default:
64958415Smckusick 		return (EOPNOTSUPP);
65050149Smarc 	}
65157843Smckusick 	if (error)
65257843Smckusick 		return (error);
65357843Smckusick 	*retval = size;
654*58461Smckusick 	if (uap->size)
655*58461Smckusick 		error = copyout((caddr_t)&size, (caddr_t)uap->size,
656*58461Smckusick 		    sizeof(size));
657*58461Smckusick 	return (error);
65850149Smarc }
65957843Smckusick #endif /* COMPAT_43 */
660