kern_sysctl.c revision 11863
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software contributed to Berkeley by
61541Srgrimes * Mike Karels at Berkeley Software Design, Inc.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms, with or without
91541Srgrimes * modification, are permitted provided that the following conditions
101541Srgrimes * are met:
111541Srgrimes * 1. Redistributions of source code must retain the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer.
131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer in the
151541Srgrimes *    documentation and/or other materials provided with the distribution.
161541Srgrimes * 3. All advertising materials mentioning features or use of this software
171541Srgrimes *    must display the following acknowledgement:
181541Srgrimes *	This product includes software developed by the University of
191541Srgrimes *	California, Berkeley and its contributors.
201541Srgrimes * 4. Neither the name of the University nor the names of its contributors
211541Srgrimes *    may be used to endorse or promote products derived from this software
221541Srgrimes *    without specific prior written permission.
231541Srgrimes *
241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341541Srgrimes * SUCH DAMAGE.
351541Srgrimes *
361541Srgrimes *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
3711863Sphk * $Id: kern_sysctl.c,v 1.28 1995/07/31 10:07:31 mpp Exp $
381541Srgrimes */
391541Srgrimes
401541Srgrimes/*
411541Srgrimes * sysctl system call.
421541Srgrimes */
431541Srgrimes
441541Srgrimes#include <sys/param.h>
451541Srgrimes#include <sys/systm.h>
461541Srgrimes#include <sys/kernel.h>
471541Srgrimes#include <sys/malloc.h>
481541Srgrimes#include <sys/proc.h>
491541Srgrimes#include <sys/file.h>
501541Srgrimes#include <sys/vnode.h>
511541Srgrimes#include <sys/unistd.h>
521541Srgrimes#include <sys/buf.h>
531541Srgrimes#include <sys/ioctl.h>
541541Srgrimes#include <sys/tty.h>
558481Swollman#include <sys/conf.h>
561541Srgrimes#include <vm/vm.h>
571541Srgrimes#include <sys/sysctl.h>
581541Srgrimes
591541Srgrimes#ifdef DEBUG
604467Sbdestatic sysctlfn debug_sysctl;
611541Srgrimes#endif
621541Srgrimes
6311863Sphk/* BEGIN_MIB */
6411863SphkSYSCTL_NODE(,CTL_KERN,	kern,	0,	"High kernel, proc, limits &c");
6511863SphkSYSCTL_NODE(,CTL_VM,	vm,	0,	"Virtual memory");
6611863SphkSYSCTL_NODE(,CTL_FS,	fs,	0,	"File system");
6711863SphkSYSCTL_NODE(,CTL_NET,	net,	0,	"Network, (see socket.h)");
6811863SphkSYSCTL_NODE(,CTL_DEBUG,	debug,	0,	"Debugging");
6911863SphkSYSCTL_NODE(,CTL_HW,	hw,	0,	"hardware");
7011863SphkSYSCTL_NODE(,CTL_MACHDEP,	machdep,0,	"machine dependent");
7111863SphkSYSCTL_NODE(,CTL_USER,	user,	0,	"user-level");
7211863Sphk
7311863SphkSYSCTL_STRING(_kern,KERN_OSTYPE, ostype,
7411863Sphk	CTLFLAG_RD, ostype, 0, 0, "");
7511863Sphk
7611863SphkSYSCTL_STRING(_kern,KERN_OSRELEASE, osrelease,
7711863Sphk	CTLFLAG_RD, osrelease, 0, 0, "");
7811863Sphk
7911863SphkSYSCTL_INT(_kern,KERN_OSREV, osrevision,
8011863Sphk	CTLFLAG_RD, 0, BSD, 0, "");
8111863Sphk
8211863SphkSYSCTL_STRING(_kern,KERN_VERSION, version,
8311863Sphk	CTLFLAG_RD, version, 0, 0, "");
8411863Sphk
8511863Sphkextern int osreldate;
8611863SphkSYSCTL_INT(_kern,KERN_OSRELDATE, osreldate,
8711863Sphk	CTLFLAG_RD, &osreldate, 0, 0, "");
8811863Sphk
8911863SphkSYSCTL_INT(_kern,KERN_MAXVNODES, maxvnodes,
9011863Sphk	CTLFLAG_RD, &desiredvnodes, 0, 0, "");
9111863Sphk
9211863SphkSYSCTL_INT(_kern,KERN_MAXPROC, maxproc,
9311863Sphk	CTLFLAG_RD, &maxproc, 0, 0, "");
9411863Sphk
9511863SphkSYSCTL_INT(_kern,KERN_MAXPROCPERUID,maxprocperuid,
9611863Sphk	CTLFLAG_RD, &maxprocperuid, 0, 0, "");
9711863Sphk
9811863SphkSYSCTL_INT(_kern,KERN_MAXFILESPERPROC, maxfilesperproc,
9911863Sphk	CTLFLAG_RD, &maxfilesperproc, 0, 0, "");
10011863Sphk
10111863SphkSYSCTL_INT(_kern,KERN_ARGMAX, argmax,
10211863Sphk	CTLFLAG_RD, 0, ARG_MAX, 0, "");
10311863Sphk
10411863SphkSYSCTL_INT(_kern,KERN_POSIX1, posix1version,
10511863Sphk	CTLFLAG_RD, 0, _POSIX_VERSION, 0, "");
10611863Sphk
10711863SphkSYSCTL_INT(_kern,KERN_NGROUPS, ngroups,
10811863Sphk	CTLFLAG_RD, 0, NGROUPS_MAX, 0, "");
10911863Sphk
11011863SphkSYSCTL_INT(_kern,KERN_JOB_CONTROL, job_control,
11111863Sphk	CTLFLAG_RD, 0, 1, 0, "");
11211863Sphk
11311863SphkSYSCTL_INT(_kern,KERN_MAXFILES, maxfiles,
11411863Sphk	CTLFLAG_RW, &maxfiles, 0, 0, "");
11511863Sphk
11611863Sphk#ifdef _POSIX_SAVED_IDS
11711863SphkSYSCTL_INT(_kern,KERN_SAVED_IDS, saved_ids,
11811863Sphk	CTLFLAG_RD, 0, 1, 0, "");
11911863Sphk#else
12011863SphkSYSCTL_INT(_kern,KERN_SAVED_IDS, saved_ids,
12111863Sphk	CTLFLAG_RD, 0, 0, 0, "");
12211863Sphk#endif
12311863Sphk
12411863Sphkchar kernelname[MAXPATHLEN] = "/kernel";	/* XXX bloat */
12511863Sphk
12611863SphkSYSCTL_STRING(_kern,KERN_BOOTFILE, bootfile,
12711863Sphk	CTLFLAG_RW, kernelname, sizeof kernelname, 0, "");
12811863Sphk
12911863SphkSYSCTL_STRUCT(_kern,KERN_BOOTTIME, boottime,
13011863Sphk	CTLFLAG_RW, &boottime, timeval, 0, "");
13111863Sphk
13211863SphkSYSCTL_STRING(_hw,HW_MACHINE, machine,
13311863Sphk	CTLFLAG_RD, machine, 0, 0, "");
13411863Sphk
13511863SphkSYSCTL_STRING(_hw,HW_MACHINE, model,
13611863Sphk	CTLFLAG_RD, cpu_model, 0, 0, "");
13711863Sphk
13811863SphkSYSCTL_INT(_hw,HW_NCPU, ncpu,
13911863Sphk	CTLFLAG_RD, 0, 1, 0, "");
14011863Sphk
14111863SphkSYSCTL_INT(_hw,HW_BYTEORDER, byteorder,
14211863Sphk	CTLFLAG_RD, 0, BYTE_ORDER, 0, "");
14311863Sphk
14411863SphkSYSCTL_INT(_hw,HW_PAGESIZE, pagesize,
14511863Sphk	CTLFLAG_RD, 0, PAGE_SIZE, 0, "");
14611863Sphk
14711863SphkSYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
14811863Sphk	CTLFLAG_RD, &hw_float, 0, 0, "");
14911863Sphk
15011863Sphk/* END_MIB */
15111863Sphk
15211863Sphkextern int vfs_update_wakeup;
15311863Sphkextern int vfs_update_interval;
15411863Sphkstatic int
15511863Sphksysctl_kern_updateinterval(oidp, when, error)
15611863Sphk	struct sysctl_oid *oidp;
15711863Sphk	int when;
15811863Sphk	int error;
15911863Sphk{
16011863Sphk	if (when == CTLAFTER && !error)
16111863Sphk		wakeup(&vfs_update_wakeup);
16211863Sphk	return 0;
16311863Sphk}
16411863Sphk
16511863SphkSYSCTL_INT(_kern,KERN_UPDATEINTERVAL, update,
16611863Sphk	CTLFLAG_RD, &vfs_update_interval, 0, sysctl_kern_updateinterval,"");
16711863Sphk
16811863Sphk
16911863Sphkstatic int
17011863Sphkdo_int(oidp, oldp, oldlenp, newp, newlen)
17111863Sphk	struct sysctl_oid *oidp;
17211863Sphk	void *oldp;
17311863Sphk	size_t *oldlenp;
17411863Sphk	void *newp;
17511863Sphk	size_t newlen;
17611863Sphk{
17711863Sphk	int error = 0;
17811863Sphk
17911863Sphk	/* If there isn't sufficient space to return */
18011863Sphk	if (oldp && *oldlenp < sizeof(int))
18111863Sphk		return (ENOMEM);
18211863Sphk
18311863Sphk	/* If it is a constant, don't write */
18411863Sphk	if (newp && !oidp->oid_arg1)
18511863Sphk		return (EPERM);
18611863Sphk
18711863Sphk	/* If we get more than an int */
18811863Sphk	if (newp && newlen != sizeof(int))
18911863Sphk		return (EINVAL);
19011863Sphk
19111863Sphk	*oldlenp = sizeof(int);
19211863Sphk	if (oldp && oidp->oid_arg1 )
19311863Sphk		error = copyout(oidp->oid_arg1, oldp, sizeof(int));
19411863Sphk	else if (oldp)
19511863Sphk		error = copyout(&oidp->oid_arg2, oldp, sizeof(int));
19611863Sphk	if (error == 0 && newp)
19711863Sphk		error = copyin(newp, oidp->oid_arg1, sizeof(int));
19811863Sphk	return (error);
19911863Sphk}
20011863Sphk
20111863Sphkstatic int
20211863Sphkdo_string(oidp, oldp, oldlenp, newp, newlen)
20311863Sphk	struct sysctl_oid *oidp;
20411863Sphk	void *oldp;
20511863Sphk	size_t *oldlenp;
20611863Sphk	void *newp;
20711863Sphk	size_t newlen;
20811863Sphk{
20911863Sphk	int len, error = 0, rval = 0;
21011863Sphk	int maxlen = oidp->oid_arg2;
21111863Sphk	char *str = (char *)(oidp->oid_arg1);
21211863Sphk
21311863Sphk	len = strlen(str) + 1;
21411863Sphk
21511863Sphk	if (oldp && *oldlenp < len) {
21611863Sphk		len = *oldlenp;
21711863Sphk		rval = ENOMEM;
21811863Sphk	}
21911863Sphk
22011863Sphk	if (newp && newlen >= maxlen)
22111863Sphk		return (EINVAL);
22211863Sphk
22311863Sphk	if (oldp) {
22411863Sphk		*oldlenp = len;
22511863Sphk		error = copyout(str, oldp, len);
22611863Sphk		if (error)
22711863Sphk			rval = error;
22811863Sphk	}
22911863Sphk	if ((error == 0 || error == ENOMEM) && newp) {
23011863Sphk		error = copyin(newp, str, newlen);
23111863Sphk		if (error)
23211863Sphk			rval = error;
23311863Sphk		str[newlen] = 0;
23411863Sphk	}
23511863Sphk	return (rval);
23611863Sphk}
23711863Sphk
23811863Sphkstatic int
23911863Sphkdo_opaque(oidp, oldp, oldlenp, newp, newlen)
24011863Sphk	struct sysctl_oid *oidp;
24111863Sphk	void *oldp;
24211863Sphk	size_t *oldlenp;
24311863Sphk	void *newp;
24411863Sphk	size_t newlen;
24511863Sphk{
24611863Sphk	int error = 0, rval = 0;
24711863Sphk	char *str = (char *)(oidp->oid_arg1);
24811863Sphk	int len = oidp->oid_arg2;
24911863Sphk
25011863Sphk	if (oldp && *oldlenp < len) {
25111863Sphk		return (ENOMEM);
25211863Sphk	}
25311863Sphk
25411863Sphk	if (newp && newlen != len)
25511863Sphk		return (EINVAL);
25611863Sphk
25711863Sphk	if (oldp) {
25811863Sphk		*oldlenp = len;
25911863Sphk		error = copyout(str, oldp, len);
26011863Sphk		if (error)
26111863Sphk			rval = error;
26211863Sphk	}
26311863Sphk	if ((error == 0 || error == ENOMEM) && newp) {
26411863Sphk		error = copyin(newp, str, len);
26511863Sphk		if (error)
26611863Sphk			rval = error;
26711863Sphk		str[newlen] = 0;
26811863Sphk	}
26911863Sphk	return (rval);
27011863Sphk}
27111863Sphk
27211863Sphk
2731541Srgrimes/*
2741541Srgrimes * Locking and stats
2751541Srgrimes */
2761541Srgrimesstatic struct sysctl_lock {
2771541Srgrimes	int	sl_lock;
2781541Srgrimes	int	sl_want;
2791541Srgrimes	int	sl_locked;
2801541Srgrimes} memlock;
2811541Srgrimes
2821541Srgrimesstruct sysctl_args {
2831541Srgrimes	int	*name;
2841541Srgrimes	u_int	namelen;
2851541Srgrimes	void	*old;
2861541Srgrimes	size_t	*oldlenp;
2871541Srgrimes	void	*new;
2881541Srgrimes	size_t	newlen;
2891541Srgrimes};
2901541Srgrimes
29111863Sphkextern struct linker_set sysctl_;
29211863Sphk
2931541Srgrimesint
2941541Srgrimes__sysctl(p, uap, retval)
2951541Srgrimes	struct proc *p;
2961541Srgrimes	register struct sysctl_args *uap;
2971541Srgrimes	int *retval;
2981541Srgrimes{
29911863Sphk	int error, dolock = 1, i;
3001549Srgrimes	u_int savelen = 0, oldlen = 0;
3011541Srgrimes	sysctlfn *fn;
3021541Srgrimes	int name[CTL_MAXNAME];
30311863Sphk        struct linker_set *lsp;
30411863Sphk	struct sysctl_oid **oidp;
3051541Srgrimes
3061541Srgrimes	if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag)))
3071541Srgrimes		return (error);
30811863Sphk
3091541Srgrimes	/*
3101541Srgrimes	 * all top-level sysctl names are non-terminal
3111541Srgrimes	 */
31211863Sphk
3131541Srgrimes	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
3141541Srgrimes		return (EINVAL);
31511863Sphk
3163308Sphk 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
3173308Sphk 	if (error)
3181541Srgrimes		return (error);
3191541Srgrimes
32011863Sphk	oidp = (struct sysctl_oid **) &sysctl_.ls_items[0];
32111863Sphk
32211863Sphk	for (i=0; *oidp && i < CTL_MAXNAME; oidp++) {
32311863Sphk		if ((*oidp)->oid_arg1 == (void *) *oidp)
32411863Sphk			continue;
32511863Sphk		if ((*oidp)->oid_number != name[i])
32611863Sphk			continue;
32711863Sphk		i++;
32811863Sphk		if (((*oidp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
32911863Sphk			if (i == uap->namelen)
33011863Sphk				/* XXX fail when "old" goes away */
33111863Sphk				goto old;
33211863Sphk	                lsp = (struct linker_set*)(*oidp)->oid_arg1;
33311863Sphk	                oidp = (struct sysctl_oid **) &lsp->ls_items[0];
33411863Sphk		} else {
33511863Sphk			if (i != uap->namelen)
33611863Sphk				/* XXX fail when "old" goes away */
33711863Sphk				goto old;
33811863Sphk			goto found;
33911863Sphk		}
34011863Sphk	}
34111863Sphk	/* XXX fail when "old" goes away */
34211863Sphk	goto old;
34311863Sphkfound:
34411863Sphk#if 0
34511863Sphk	printf("Found <%s> %x %p\n",
34611863Sphk		(*oidp)->oid_name, (*oidp)->oid_kind, (*oidp)->oid_arg1);
34711863Sphk#endif
34811863Sphk
34911863Sphk	if ((*oidp)->oid_handler) {
35011863Sphk		i = ((*oidp)->oid_handler) (*oidp,CTLBEFORE,0);
35111863Sphk		if (i)
35211863Sphk			return i;
35311863Sphk	}
35411863Sphk	if ((*oidp)->oid_kind & CTLFLAG_NOLOCK)
35511863Sphk		dolock = 0;
35611863Sphk
35711863Sphk	if (uap->oldlenp &&
35811863Sphk	    (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
35911863Sphk		return (error);
36011863Sphk
36111863Sphk	if (uap->old != NULL) {
36211863Sphk		if (!useracc(uap->old, oldlen, B_WRITE))
36311863Sphk			return (EFAULT);
36411863Sphk		while (memlock.sl_lock) {
36511863Sphk			memlock.sl_want = 1;
36611863Sphk			(void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0);
36711863Sphk			memlock.sl_locked++;
36811863Sphk		}
36911863Sphk		memlock.sl_lock = 1;
37011863Sphk		if (dolock)
37111863Sphk			vslock(uap->old, oldlen);
37211863Sphk		savelen = oldlen;
37311863Sphk	}
37411863Sphk
37511863Sphk	/* If writing isn't allowed */
37611863Sphk	if (uap->new && !((*oidp)->oid_kind & CTLFLAG_WR))
37711863Sphk		return (EPERM);
37811863Sphk
37911863Sphk	switch ((*oidp)->oid_kind & CTLTYPE) {
38011863Sphk		case CTLTYPE_INT:
38111863Sphk			error = do_int(*oidp,
38211863Sphk				    uap->old, &oldlen,
38311863Sphk				    uap->new, uap->newlen);
38411863Sphk			break;
38511863Sphk		case CTLTYPE_STRING:
38611863Sphk			error = do_string(*oidp,
38711863Sphk				    uap->old, &oldlen,
38811863Sphk				    uap->new, uap->newlen);
38911863Sphk			break;
39011863Sphk		case CTLTYPE_OPAQUE:
39111863Sphk			error = do_opaque(*oidp,
39211863Sphk				    uap->old, &oldlen,
39311863Sphk				    uap->new, uap->newlen);
39411863Sphk			break;
39511863Sphk		default:
39611863Sphk			printf("sysctl not handled\n");
39711863Sphk			error = EINVAL;
39811863Sphk			break;
39911863Sphk	}
40011863Sphk
40111863Sphk	if ((*oidp)->oid_handler) {
40211863Sphk		i = ((*oidp)->oid_handler) (*oidp,CTLAFTER,error);
40311863Sphk		if (i)
40411863Sphk			error = i;
40511863Sphk	}
40611863Sphk	goto over_and_out;
40711863Sphk
40811863Sphk    old:
4091541Srgrimes	switch (name[0]) {
4101541Srgrimes	case CTL_KERN:
4111541Srgrimes		fn = kern_sysctl;
4122903Sache		if (name[1] != KERN_VNODE)      /* XXX */
4131541Srgrimes			dolock = 0;
4141541Srgrimes		break;
4151541Srgrimes	case CTL_HW:
4161541Srgrimes		fn = hw_sysctl;
4171541Srgrimes		break;
4181541Srgrimes	case CTL_VM:
4191541Srgrimes		fn = vm_sysctl;
4201541Srgrimes		break;
4211541Srgrimes	case CTL_NET:
4221541Srgrimes		fn = net_sysctl;
4231541Srgrimes		break;
4241541Srgrimes	case CTL_FS:
4251541Srgrimes		fn = fs_sysctl;
4261541Srgrimes		break;
4271541Srgrimes	case CTL_MACHDEP:
4281541Srgrimes		fn = cpu_sysctl;
4291541Srgrimes		break;
4301541Srgrimes#ifdef DEBUG
4311541Srgrimes	case CTL_DEBUG:
4321541Srgrimes		fn = debug_sysctl;
4331541Srgrimes		break;
4341541Srgrimes#endif
4351541Srgrimes	default:
4361541Srgrimes		return (EOPNOTSUPP);
4371541Srgrimes	}
4381541Srgrimes	if (uap->oldlenp &&
4391541Srgrimes	    (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
4401541Srgrimes		return (error);
44111863Sphk
4421541Srgrimes	if (uap->old != NULL) {
4431541Srgrimes		if (!useracc(uap->old, oldlen, B_WRITE))
4441541Srgrimes			return (EFAULT);
4451541Srgrimes		while (memlock.sl_lock) {
4461541Srgrimes			memlock.sl_want = 1;
4473396Sdg			(void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0);
4481541Srgrimes			memlock.sl_locked++;
4491541Srgrimes		}
4501541Srgrimes		memlock.sl_lock = 1;
4511541Srgrimes		if (dolock)
4521541Srgrimes			vslock(uap->old, oldlen);
4531541Srgrimes		savelen = oldlen;
4541541Srgrimes	}
45511863Sphk
45611863Sphk
4571541Srgrimes	error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen,
4581541Srgrimes	    uap->new, uap->newlen, p);
45911863Sphk     over_and_out:
4601541Srgrimes	if (uap->old != NULL) {
4611541Srgrimes		if (dolock)
4621541Srgrimes			vsunlock(uap->old, savelen, B_WRITE);
4631541Srgrimes		memlock.sl_lock = 0;
4641541Srgrimes		if (memlock.sl_want) {
4651541Srgrimes			memlock.sl_want = 0;
4661541Srgrimes			wakeup((caddr_t)&memlock);
4671541Srgrimes		}
4681541Srgrimes	}
4691541Srgrimes	if (error)
4701541Srgrimes		return (error);
4711541Srgrimes	if (uap->oldlenp)
4721541Srgrimes		error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
4731541Srgrimes	*retval = oldlen;
4741541Srgrimes	return (0);
4751541Srgrimes}
4761541Srgrimes
4771541Srgrimes/*
4781541Srgrimes * Attributes stored in the kernel.
4791541Srgrimes */
4801541Srgrimeschar hostname[MAXHOSTNAMELEN];
4811541Srgrimesint hostnamelen;
4821925Swollmanchar domainname[MAXHOSTNAMELEN];
4831925Swollmanint domainnamelen;
4841541Srgrimeslong hostid;
4851995Swollmanint securelevel = -1;
4861541Srgrimes
4871541Srgrimes/*
4881541Srgrimes * kernel related system variables.
4891541Srgrimes */
4901549Srgrimesint
4911541Srgrimeskern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
4921541Srgrimes	int *name;
4931541Srgrimes	u_int namelen;
4941541Srgrimes	void *oldp;
4951541Srgrimes	size_t *oldlenp;
4961541Srgrimes	void *newp;
4971541Srgrimes	size_t newlen;
4981541Srgrimes	struct proc *p;
4991541Srgrimes{
5001541Srgrimes	int error, level, inthostid;
5018481Swollman	dev_t ndumpdev;
5021541Srgrimes
5031541Srgrimes	/* all sysctl names at this level are terminal */
5042858Swollman	if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF
5052858Swollman			      || name[0] == KERN_NTP_PLL))
5061541Srgrimes		return (ENOTDIR);		/* overloaded */
5071541Srgrimes
5081541Srgrimes	switch (name[0]) {
50911863Sphk
5101541Srgrimes	case KERN_SECURELVL:
5111541Srgrimes		level = securelevel;
5121541Srgrimes		if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
5131541Srgrimes		    newp == NULL)
5141541Srgrimes			return (error);
5151541Srgrimes		if (level < securelevel && p->p_pid != 1)
5161541Srgrimes			return (EPERM);
5171541Srgrimes		securelevel = level;
5181541Srgrimes		return (0);
5191541Srgrimes	case KERN_HOSTNAME:
5201541Srgrimes		error = sysctl_string(oldp, oldlenp, newp, newlen,
5211541Srgrimes		    hostname, sizeof(hostname));
5229816Smpp		if (newp)
5239816Smpp			if (error == 0 || error == ENOMEM)
5249816Smpp				hostnamelen = newlen;
5251541Srgrimes		return (error);
5261925Swollman	case KERN_DOMAINNAME:
5271925Swollman		error = sysctl_string(oldp, oldlenp, newp, newlen,
5281925Swollman		    domainname, sizeof(domainname));
5299816Smpp		if (newp)
5309816Smpp			if (error == 0 || error == ENOMEM)
5319816Smpp				domainnamelen = newlen;
5321925Swollman		return (error);
5331541Srgrimes	case KERN_HOSTID:
5341541Srgrimes		inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
5351541Srgrimes		error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
5361541Srgrimes		hostid = inthostid;
5371541Srgrimes		return (error);
5381541Srgrimes	case KERN_CLOCKRATE:
5391541Srgrimes		return (sysctl_clockrate(oldp, oldlenp));
5401541Srgrimes	case KERN_VNODE:
5411541Srgrimes		return (sysctl_vnode(oldp, oldlenp));
5421541Srgrimes	case KERN_PROC:
5431541Srgrimes		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
5441541Srgrimes	case KERN_FILE:
5451541Srgrimes		return (sysctl_file(oldp, oldlenp));
5461541Srgrimes#ifdef GPROF
5471541Srgrimes	case KERN_PROF:
5481541Srgrimes		return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
5491541Srgrimes		    newp, newlen));
5501541Srgrimes#endif
5512858Swollman	case KERN_NTP_PLL:
5522858Swollman		return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp,
5532858Swollman				   newp, newlen, p));
5548481Swollman	case KERN_DUMPDEV:
5558481Swollman		ndumpdev = dumpdev;
5568481Swollman		error = sysctl_struct(oldp, oldlenp, newp, newlen, &ndumpdev,
5578481Swollman				      sizeof ndumpdev);
5588481Swollman		if (!error && ndumpdev != dumpdev) {
5598481Swollman			error = setdumpdev(ndumpdev);
5608481Swollman		}
5618481Swollman		return error;
5621541Srgrimes	default:
5631541Srgrimes		return (EOPNOTSUPP);
5641541Srgrimes	}
5651541Srgrimes	/* NOTREACHED */
5661541Srgrimes}
5671541Srgrimes
5681541Srgrimes/*
5691541Srgrimes * hardware related system variables.
5701541Srgrimes */
5711549Srgrimesint
5721541Srgrimeshw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
5731541Srgrimes	int *name;
5741541Srgrimes	u_int namelen;
5751541Srgrimes	void *oldp;
5761541Srgrimes	size_t *oldlenp;
5771541Srgrimes	void *newp;
5781541Srgrimes	size_t newlen;
5791541Srgrimes	struct proc *p;
5801541Srgrimes{
5813640Swollman	/* almost all sysctl names at this level are terminal */
5823640Swollman	if (namelen != 1 && name[0] != HW_DEVCONF)
5831541Srgrimes		return (ENOTDIR);		/* overloaded */
5841541Srgrimes
5851541Srgrimes	switch (name[0]) {
5861541Srgrimes	case HW_PHYSMEM:
5871541Srgrimes		return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
5881541Srgrimes	case HW_USERMEM:
5891541Srgrimes		return (sysctl_rdint(oldp, oldlenp, newp,
5901541Srgrimes		    ctob(physmem - cnt.v_wire_count)));
5913640Swollman	case HW_DEVCONF:
5923640Swollman		return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp,
5933640Swollman				   newp, newlen, p));
5941541Srgrimes	default:
5951541Srgrimes		return (EOPNOTSUPP);
5961541Srgrimes	}
5971541Srgrimes	/* NOTREACHED */
5981541Srgrimes}
5991541Srgrimes
6001541Srgrimes#ifdef DEBUG
6011541Srgrimes/*
6021541Srgrimes * Debugging related system variables.
6031541Srgrimes */
6041541Srgrimesstruct ctldebug debug0, debug1, debug2, debug3, debug4;
6051541Srgrimesstruct ctldebug debug5, debug6, debug7, debug8, debug9;
6061541Srgrimesstruct ctldebug debug10, debug11, debug12, debug13, debug14;
6071541Srgrimesstruct ctldebug debug15, debug16, debug17, debug18, debug19;
6081541Srgrimesstatic struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
6091541Srgrimes	&debug0, &debug1, &debug2, &debug3, &debug4,
6101541Srgrimes	&debug5, &debug6, &debug7, &debug8, &debug9,
6111541Srgrimes	&debug10, &debug11, &debug12, &debug13, &debug14,
6121541Srgrimes	&debug15, &debug16, &debug17, &debug18, &debug19,
6131541Srgrimes};
6144467Sbdestatic int
6151541Srgrimesdebug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
6161541Srgrimes	int *name;
6171541Srgrimes	u_int namelen;
6181541Srgrimes	void *oldp;
6191541Srgrimes	size_t *oldlenp;
6201541Srgrimes	void *newp;
6211541Srgrimes	size_t newlen;
6221541Srgrimes	struct proc *p;
6231541Srgrimes{
6241541Srgrimes	struct ctldebug *cdp;
6251541Srgrimes
6261541Srgrimes	/* all sysctl names at this level are name and field */
6271541Srgrimes	if (namelen != 2)
6281541Srgrimes		return (ENOTDIR);		/* overloaded */
6291541Srgrimes	cdp = debugvars[name[0]];
6301541Srgrimes	if (cdp->debugname == 0)
6311541Srgrimes		return (EOPNOTSUPP);
6321541Srgrimes	switch (name[1]) {
6331541Srgrimes	case CTL_DEBUG_NAME:
6341541Srgrimes		return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
6351541Srgrimes	case CTL_DEBUG_VALUE:
6361541Srgrimes		return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
6371541Srgrimes	default:
6381541Srgrimes		return (EOPNOTSUPP);
6391541Srgrimes	}
6401541Srgrimes	/* NOTREACHED */
6411541Srgrimes}
6421541Srgrimes#endif /* DEBUG */
6431541Srgrimes
6441541Srgrimes/*
6451541Srgrimes * Validate parameters and get old / set new parameters
6461541Srgrimes * for an integer-valued sysctl function.
6471541Srgrimes */
6481549Srgrimesint
6491541Srgrimessysctl_int(oldp, oldlenp, newp, newlen, valp)
6501541Srgrimes	void *oldp;
6511541Srgrimes	size_t *oldlenp;
6521541Srgrimes	void *newp;
6531541Srgrimes	size_t newlen;
6541541Srgrimes	int *valp;
6551541Srgrimes{
6561541Srgrimes	int error = 0;
6571541Srgrimes
6581541Srgrimes	if (oldp && *oldlenp < sizeof(int))
6591541Srgrimes		return (ENOMEM);
6601541Srgrimes	if (newp && newlen != sizeof(int))
6611541Srgrimes		return (EINVAL);
6621541Srgrimes	*oldlenp = sizeof(int);
6631541Srgrimes	if (oldp)
6641541Srgrimes		error = copyout(valp, oldp, sizeof(int));
6651541Srgrimes	if (error == 0 && newp)
6661541Srgrimes		error = copyin(newp, valp, sizeof(int));
6671541Srgrimes	return (error);
6681541Srgrimes}
6691541Srgrimes
6701541Srgrimes/*
6711541Srgrimes * As above, but read-only.
6721541Srgrimes */
6731549Srgrimesint
6741541Srgrimessysctl_rdint(oldp, oldlenp, newp, val)
6751541Srgrimes	void *oldp;
6761541Srgrimes	size_t *oldlenp;
6771541Srgrimes	void *newp;
6781541Srgrimes	int val;
6791541Srgrimes{
6801541Srgrimes	int error = 0;
6811541Srgrimes
6821541Srgrimes	if (oldp && *oldlenp < sizeof(int))
6831541Srgrimes		return (ENOMEM);
6841541Srgrimes	if (newp)
6851541Srgrimes		return (EPERM);
6861541Srgrimes	*oldlenp = sizeof(int);
6871541Srgrimes	if (oldp)
6881541Srgrimes		error = copyout((caddr_t)&val, oldp, sizeof(int));
6891541Srgrimes	return (error);
6901541Srgrimes}
6911541Srgrimes
6921541Srgrimes/*
6931541Srgrimes * Validate parameters and get old / set new parameters
6941541Srgrimes * for a string-valued sysctl function.
6951541Srgrimes */
6961549Srgrimesint
6971541Srgrimessysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
6981541Srgrimes	void *oldp;
6991541Srgrimes	size_t *oldlenp;
7001541Srgrimes	void *newp;
7011541Srgrimes	size_t newlen;
7021541Srgrimes	char *str;
7031541Srgrimes	int maxlen;
7041541Srgrimes{
7059816Smpp	int len, error = 0, rval = 0;
7061541Srgrimes
7071541Srgrimes	len = strlen(str) + 1;
7089816Smpp	if (oldp && *oldlenp < len) {
7095150Sguido		len = *oldlenp;
7109816Smpp		rval = ENOMEM;
7119816Smpp	}
7121541Srgrimes	if (newp && newlen >= maxlen)
7131541Srgrimes		return (EINVAL);
7141541Srgrimes	if (oldp) {
7151541Srgrimes		*oldlenp = len;
7161541Srgrimes		error = copyout(str, oldp, len);
7179816Smpp		if (error)
7189816Smpp			rval = error;
7191541Srgrimes	}
7209816Smpp	if ((error == 0 || error == ENOMEM) && newp) {
7211541Srgrimes		error = copyin(newp, str, newlen);
7229816Smpp		if (error)
7239816Smpp			rval = error;
7241541Srgrimes		str[newlen] = 0;
7251541Srgrimes	}
7269816Smpp	return (rval);
7271541Srgrimes}
7281541Srgrimes
7291541Srgrimes/*
7301541Srgrimes * As above, but read-only.
7311541Srgrimes */
7321549Srgrimesint
7331541Srgrimessysctl_rdstring(oldp, oldlenp, newp, str)
7341541Srgrimes	void *oldp;
7351541Srgrimes	size_t *oldlenp;
7361541Srgrimes	void *newp;
7371541Srgrimes	char *str;
7381541Srgrimes{
7399816Smpp	int len, error = 0, rval = 0;
7401541Srgrimes
7411541Srgrimes	len = strlen(str) + 1;
7429816Smpp	if (oldp && *oldlenp < len) {
7439816Smpp		len = *oldlenp;
7449816Smpp		rval = ENOMEM;
7459816Smpp	}
7461541Srgrimes	if (newp)
7471541Srgrimes		return (EPERM);
7481541Srgrimes	*oldlenp = len;
7491541Srgrimes	if (oldp)
7501541Srgrimes		error = copyout(str, oldp, len);
7519816Smpp		if (error)
7529816Smpp			rval = error;
7539816Smpp	return (rval);
7541541Srgrimes}
7551541Srgrimes
7561541Srgrimes/*
7571541Srgrimes * Validate parameters and get old / set new parameters
7581541Srgrimes * for a structure oriented sysctl function.
7591541Srgrimes */
7601549Srgrimesint
7611541Srgrimessysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
7621541Srgrimes	void *oldp;
7631541Srgrimes	size_t *oldlenp;
7641541Srgrimes	void *newp;
7651541Srgrimes	size_t newlen;
7661541Srgrimes	void *sp;
7671541Srgrimes	int len;
7681541Srgrimes{
7691541Srgrimes	int error = 0;
7701541Srgrimes
7711541Srgrimes	if (oldp && *oldlenp < len)
7721541Srgrimes		return (ENOMEM);
7731541Srgrimes	if (newp && newlen > len)
7741541Srgrimes		return (EINVAL);
7751541Srgrimes	if (oldp) {
7761541Srgrimes		*oldlenp = len;
7771541Srgrimes		error = copyout(sp, oldp, len);
7781541Srgrimes	}
7791541Srgrimes	if (error == 0 && newp)
7801541Srgrimes		error = copyin(newp, sp, len);
7811541Srgrimes	return (error);
7821541Srgrimes}
7831541Srgrimes
7841541Srgrimes/*
7851541Srgrimes * Validate parameters and get old parameters
7861541Srgrimes * for a structure oriented sysctl function.
7871541Srgrimes */
7881549Srgrimesint
7891541Srgrimessysctl_rdstruct(oldp, oldlenp, newp, sp, len)
7901541Srgrimes	void *oldp;
7911541Srgrimes	size_t *oldlenp;
7921541Srgrimes	void *newp, *sp;
7931541Srgrimes	int len;
7941541Srgrimes{
7951541Srgrimes	int error = 0;
7961541Srgrimes
7971541Srgrimes	if (oldp && *oldlenp < len)
7981541Srgrimes		return (ENOMEM);
7991541Srgrimes	if (newp)
8001541Srgrimes		return (EPERM);
8011541Srgrimes	*oldlenp = len;
8021541Srgrimes	if (oldp)
8031541Srgrimes		error = copyout(sp, oldp, len);
8041541Srgrimes	return (error);
8051541Srgrimes}
8061541Srgrimes
8071541Srgrimes/*
8081541Srgrimes * Get file structures.
8091541Srgrimes */
8101549Srgrimesint
8111541Srgrimessysctl_file(where, sizep)
8121541Srgrimes	char *where;
8131541Srgrimes	size_t *sizep;
8141541Srgrimes{
8151541Srgrimes	int buflen, error;
8161541Srgrimes	struct file *fp;
8171541Srgrimes	char *start = where;
8181541Srgrimes
8191541Srgrimes	buflen = *sizep;
8201541Srgrimes	if (where == NULL) {
8211541Srgrimes		/*
8221541Srgrimes		 * overestimate by 10 files
8231541Srgrimes		 */
8241541Srgrimes		*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
8251541Srgrimes		return (0);
8261541Srgrimes	}
8271541Srgrimes
8281541Srgrimes	/*
8291541Srgrimes	 * first copyout filehead
8301541Srgrimes	 */
8311541Srgrimes	if (buflen < sizeof(filehead)) {
8321541Srgrimes		*sizep = 0;
8331541Srgrimes		return (0);
8341541Srgrimes	}
8353308Sphk	error = copyout((caddr_t)&filehead, where, sizeof(filehead));
8363308Sphk	if (error)
8371541Srgrimes		return (error);
8381541Srgrimes	buflen -= sizeof(filehead);
8391541Srgrimes	where += sizeof(filehead);
8401541Srgrimes
8411541Srgrimes	/*
8421541Srgrimes	 * followed by an array of file structures
8431541Srgrimes	 */
8441541Srgrimes	for (fp = filehead; fp != NULL; fp = fp->f_filef) {
8451541Srgrimes		if (buflen < sizeof(struct file)) {
8461541Srgrimes			*sizep = where - start;
8471541Srgrimes			return (ENOMEM);
8481541Srgrimes		}
8493308Sphk		error = copyout((caddr_t)fp, where, sizeof (struct file));
8503308Sphk		if (error)
8511541Srgrimes			return (error);
8521541Srgrimes		buflen -= sizeof(struct file);
8531541Srgrimes		where += sizeof(struct file);
8541541Srgrimes	}
8551541Srgrimes	*sizep = where - start;
8561541Srgrimes	return (0);
8571541Srgrimes}
8581541Srgrimes
8591541Srgrimes/*
8601541Srgrimes * try over estimating by 5 procs
8611541Srgrimes */
8621541Srgrimes#define KERN_PROCSLOP	(5 * sizeof (struct kinfo_proc))
8631541Srgrimes
8641549Srgrimesint
8651541Srgrimessysctl_doproc(name, namelen, where, sizep)
8661541Srgrimes	int *name;
8671541Srgrimes	u_int namelen;
8681541Srgrimes	char *where;
8691541Srgrimes	size_t *sizep;
8701541Srgrimes{
8711541Srgrimes	register struct proc *p;
8721541Srgrimes	register struct kinfo_proc *dp = (struct kinfo_proc *)where;
8731541Srgrimes	register int needed = 0;
8741541Srgrimes	int buflen = where != NULL ? *sizep : 0;
8751541Srgrimes	int doingzomb;
8761541Srgrimes	struct eproc eproc;
8771541Srgrimes	int error = 0;
8781541Srgrimes
8791541Srgrimes	if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
8801541Srgrimes		return (EINVAL);
8811541Srgrimes	p = (struct proc *)allproc;
8821541Srgrimes	doingzomb = 0;
8831541Srgrimesagain:
8841541Srgrimes	for (; p != NULL; p = p->p_next) {
8851541Srgrimes		/*
8861541Srgrimes		 * Skip embryonic processes.
8871541Srgrimes		 */
8881541Srgrimes		if (p->p_stat == SIDL)
8891541Srgrimes			continue;
8901541Srgrimes		/*
8911541Srgrimes		 * TODO - make more efficient (see notes below).
8921541Srgrimes		 * do by session.
8931541Srgrimes		 */
8941541Srgrimes		switch (name[0]) {
8951541Srgrimes
8961541Srgrimes		case KERN_PROC_PID:
8971541Srgrimes			/* could do this with just a lookup */
8981541Srgrimes			if (p->p_pid != (pid_t)name[1])
8991541Srgrimes				continue;
9001541Srgrimes			break;
9011541Srgrimes
9021541Srgrimes		case KERN_PROC_PGRP:
9031541Srgrimes			/* could do this by traversing pgrp */
9045260Sdg			if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1])
9051541Srgrimes				continue;
9061541Srgrimes			break;
9071541Srgrimes
9081541Srgrimes		case KERN_PROC_TTY:
9091541Srgrimes			if ((p->p_flag & P_CONTROLT) == 0 ||
9105260Sdg			    p->p_session == NULL ||
9111541Srgrimes			    p->p_session->s_ttyp == NULL ||
9121541Srgrimes			    p->p_session->s_ttyp->t_dev != (dev_t)name[1])
9131541Srgrimes				continue;
9141541Srgrimes			break;
9151541Srgrimes
9161541Srgrimes		case KERN_PROC_UID:
9175260Sdg			if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1])
9181541Srgrimes				continue;
9191541Srgrimes			break;
9201541Srgrimes
9211541Srgrimes		case KERN_PROC_RUID:
9225260Sdg			if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1])
9231541Srgrimes				continue;
9241541Srgrimes			break;
9251541Srgrimes		}
9261541Srgrimes		if (buflen >= sizeof(struct kinfo_proc)) {
9271541Srgrimes			fill_eproc(p, &eproc);
9288876Srgrimes			error = copyout((caddr_t)p, &dp->kp_proc,
9293308Sphk			    sizeof(struct proc));
9303308Sphk			if (error)
9311541Srgrimes				return (error);
9323308Sphk			error = copyout((caddr_t)&eproc, &dp->kp_eproc,
9333308Sphk			    sizeof(eproc));
9343308Sphk			if (error)
9351541Srgrimes				return (error);
9361541Srgrimes			dp++;
9371541Srgrimes			buflen -= sizeof(struct kinfo_proc);
9381541Srgrimes		}
9391541Srgrimes		needed += sizeof(struct kinfo_proc);
9401541Srgrimes	}
9411541Srgrimes	if (doingzomb == 0) {
9421541Srgrimes		p = zombproc;
9431541Srgrimes		doingzomb++;
9441541Srgrimes		goto again;
9451541Srgrimes	}
9461541Srgrimes	if (where != NULL) {
9471541Srgrimes		*sizep = (caddr_t)dp - where;
9481541Srgrimes		if (needed > *sizep)
9491541Srgrimes			return (ENOMEM);
9501541Srgrimes	} else {
9511541Srgrimes		needed += KERN_PROCSLOP;
9521541Srgrimes		*sizep = needed;
9531541Srgrimes	}
9541541Srgrimes	return (0);
9551541Srgrimes}
9561541Srgrimes
9571541Srgrimes/*
9581541Srgrimes * Fill in an eproc structure for the specified process.
9591541Srgrimes */
9601541Srgrimesvoid
9611541Srgrimesfill_eproc(p, ep)
9621541Srgrimes	register struct proc *p;
9631541Srgrimes	register struct eproc *ep;
9641541Srgrimes{
9651541Srgrimes	register struct tty *tp;
9661541Srgrimes
9675260Sdg	bzero(ep, sizeof(*ep));
9685260Sdg
9691541Srgrimes	ep->e_paddr = p;
9709747Sdg	if (p->p_cred) {
9715260Sdg		ep->e_pcred = *p->p_cred;
9729747Sdg		if (p->p_ucred)
9739747Sdg			ep->e_ucred = *p->p_ucred;
9749747Sdg	}
9759747Sdg	if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) {
9761541Srgrimes		register struct vmspace *vm = p->p_vmspace;
9771541Srgrimes
9781541Srgrimes#ifdef pmap_resident_count
9791541Srgrimes		ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/
9801541Srgrimes#else
9811541Srgrimes		ep->e_vm.vm_rssize = vm->vm_rssize;
9821541Srgrimes#endif
9831541Srgrimes		ep->e_vm.vm_tsize = vm->vm_tsize;
9841541Srgrimes		ep->e_vm.vm_dsize = vm->vm_dsize;
9851541Srgrimes		ep->e_vm.vm_ssize = vm->vm_ssize;
9861541Srgrimes#ifndef sparc
9871541Srgrimes		ep->e_vm.vm_pmap = vm->vm_pmap;
9881541Srgrimes#endif
9891541Srgrimes	}
9901541Srgrimes	if (p->p_pptr)
9911541Srgrimes		ep->e_ppid = p->p_pptr->p_pid;
9925260Sdg	if (p->p_pgrp) {
9935260Sdg		ep->e_sess = p->p_pgrp->pg_session;
9945260Sdg		ep->e_pgid = p->p_pgrp->pg_id;
9955260Sdg		ep->e_jobc = p->p_pgrp->pg_jobc;
9965260Sdg	}
9971541Srgrimes	if ((p->p_flag & P_CONTROLT) &&
9985260Sdg	    (ep->e_sess != NULL) &&
9995260Sdg	    ((tp = ep->e_sess->s_ttyp) != NULL)) {
10001541Srgrimes		ep->e_tdev = tp->t_dev;
10011541Srgrimes		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
10021541Srgrimes		ep->e_tsess = tp->t_session;
10031541Srgrimes	} else
10041541Srgrimes		ep->e_tdev = NODEV;
10058876Srgrimes	if (ep->e_sess && ep->e_sess->s_ttyvp)
10065260Sdg		ep->e_flag = EPROC_CTTY;
10071541Srgrimes	if (SESS_LEADER(p))
10081541Srgrimes		ep->e_flag |= EPROC_SLEADER;
10095260Sdg	if (p->p_wmesg) {
10101541Srgrimes		strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
10115260Sdg		ep->e_wmesg[WMESGLEN] = 0;
10125260Sdg	}
10131541Srgrimes}
10141541Srgrimes
10151541Srgrimes#ifdef COMPAT_43
10161541Srgrimes#include <sys/socket.h>
10171541Srgrimes#define	KINFO_PROC		(0<<8)
10181541Srgrimes#define	KINFO_RT		(1<<8)
10191541Srgrimes#define	KINFO_VNODE		(2<<8)
10201541Srgrimes#define	KINFO_FILE		(3<<8)
10211541Srgrimes#define	KINFO_METER		(4<<8)
10221541Srgrimes#define	KINFO_LOADAVG		(5<<8)
10231541Srgrimes#define	KINFO_CLOCKRATE		(6<<8)
10241541Srgrimes
10259455Speter/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
10269455Speter#define	KINFO_BSDI_SYSINFO	(101<<8)
10279455Speter
10289455Speter/*
10299455Speter * XXX this is bloat, but I hope it's better here than on the potentially
10309455Speter * limited kernel stack...  -Peter
10319455Speter */
10329455Speter
10339455Speterstruct {
10349455Speter	int	bsdi_machine;		/* "i386" on BSD/386 */
10359455Speter/*      ^^^ this is an offset to the string, relative to the struct start */
10369455Speter	char	*pad0;
10379455Speter	long	pad1;
10389455Speter	long	pad2;
10399455Speter	long	pad3;
10409455Speter	u_long	pad4;
10419455Speter	u_long	pad5;
10429455Speter	u_long	pad6;
10439455Speter
10449455Speter	int	bsdi_ostype;		/* "BSD/386" on BSD/386 */
10459455Speter	int	bsdi_osrelease;		/* "1.1" on BSD/386 */
10469455Speter	long	pad7;
10479455Speter	long	pad8;
10489455Speter	char	*pad9;
10499455Speter
10509455Speter	long	pad10;
10519455Speter	long	pad11;
10529455Speter	int	pad12;
10539455Speter	long	pad13;
10549455Speter	quad_t	pad14;
10559455Speter	long	pad15;
10569455Speter
10579455Speter	struct	timeval pad16;
10589455Speter	/* we dont set this, because BSDI's uname used gethostname() instead */
10599455Speter	int	bsdi_hostname;		/* hostname on BSD/386 */
10609455Speter
10619455Speter	/* the actual string data is appended here */
10629455Speter
10639455Speter} bsdi_si;
10649455Speter/*
10659455Speter * this data is appended to the end of the bsdi_si structure during copyout.
10669455Speter * The "char *" offsets are relative to the base of the bsdi_si struct.
10679455Speter * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
10689455Speter * should not exceed the length of the buffer here... (or else!! :-)
10699455Speter */
10709455Speterchar bsdi_strings[80];	/* It had better be less than this! */
10719455Speter
10721541Srgrimesstruct getkerninfo_args {
10731541Srgrimes	int	op;
10741541Srgrimes	char	*where;
10751541Srgrimes	int	*size;
10761541Srgrimes	int	arg;
10771541Srgrimes};
10781541Srgrimes
10791549Srgrimesint
10801541Srgrimesogetkerninfo(p, uap, retval)
10811541Srgrimes	struct proc *p;
10821541Srgrimes	register struct getkerninfo_args *uap;
10831541Srgrimes	int *retval;
10841541Srgrimes{
10851541Srgrimes	int error, name[5];
10861541Srgrimes	u_int size;
10871541Srgrimes
10881541Srgrimes	if (uap->size &&
10891541Srgrimes	    (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size))))
10901541Srgrimes		return (error);
10911541Srgrimes
10921541Srgrimes	switch (uap->op & 0xff00) {
10931541Srgrimes
10941541Srgrimes	case KINFO_RT:
10951541Srgrimes		name[0] = PF_ROUTE;
10961541Srgrimes		name[1] = 0;
10971541Srgrimes		name[2] = (uap->op & 0xff0000) >> 16;
10981541Srgrimes		name[3] = uap->op & 0xff;
10991541Srgrimes		name[4] = uap->arg;
11001541Srgrimes		error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p);
11011541Srgrimes		break;
11021541Srgrimes
11031541Srgrimes	case KINFO_VNODE:
11041541Srgrimes		name[0] = KERN_VNODE;
11051541Srgrimes		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
11061541Srgrimes		break;
11071541Srgrimes
11081541Srgrimes	case KINFO_PROC:
11091541Srgrimes		name[0] = KERN_PROC;
11101541Srgrimes		name[1] = uap->op & 0xff;
11111541Srgrimes		name[2] = uap->arg;
11121541Srgrimes		error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p);
11131541Srgrimes		break;
11141541Srgrimes
11151541Srgrimes	case KINFO_FILE:
11161541Srgrimes		name[0] = KERN_FILE;
11171541Srgrimes		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
11181541Srgrimes		break;
11191541Srgrimes
11201541Srgrimes	case KINFO_METER:
11211541Srgrimes		name[0] = VM_METER;
11221541Srgrimes		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
11231541Srgrimes		break;
11241541Srgrimes
11251541Srgrimes	case KINFO_LOADAVG:
11261541Srgrimes		name[0] = VM_LOADAVG;
11271541Srgrimes		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
11281541Srgrimes		break;
11291541Srgrimes
11301541Srgrimes	case KINFO_CLOCKRATE:
11311541Srgrimes		name[0] = KERN_CLOCKRATE;
11321541Srgrimes		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
11331541Srgrimes		break;
11341541Srgrimes
11359455Speter	case KINFO_BSDI_SYSINFO: {
11369455Speter		/*
11379455Speter		 * this is pretty crude, but it's just enough for uname()
11389455Speter		 * from BSDI's 1.x libc to work.
11399455Speter		 *
11409455Speter		 * In particular, it doesn't return the same results when
11419455Speter		 * the supplied buffer is too small.  BSDI's version apparently
11429455Speter		 * will return the amount copied, and set the *size to how
11439455Speter		 * much was needed.  The emulation framework here isn't capable
11449455Speter		 * of that, so we just set both to the amount copied.
11459455Speter		 * BSDI's 2.x product apparently fails with ENOMEM in this
11469455Speter		 * scenario.
11479455Speter		 */
11489455Speter
11499455Speter		u_int needed;
11509455Speter		u_int left;
11519455Speter		char *s;
11529455Speter
11539455Speter		bzero((char *)&bsdi_si, sizeof(bsdi_si));
11549455Speter		bzero(bsdi_strings, sizeof(bsdi_strings));
11559455Speter
11569455Speter		s = bsdi_strings;
11579455Speter
11589455Speter		bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
11599455Speter		strcpy(s, ostype);
11609455Speter		s += strlen(s) + 1;
11619455Speter
11629455Speter		bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
11639455Speter		strcpy(s, osrelease);
11649455Speter		s += strlen(s) + 1;
11659455Speter
11669455Speter		bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
11679455Speter		strcpy(s, machine);
11689455Speter		s += strlen(s) + 1;
11699455Speter
11709455Speter		needed = sizeof(bsdi_si) + (s - bsdi_strings);
11719455Speter
11729455Speter		if (uap->where == NULL) {
11739455Speter			/* process is asking how much buffer to supply.. */
11749455Speter			size = needed;
11759455Speter			error = 0;
11769455Speter			break;
11779455Speter		}
11789455Speter
11799455Speter
11809455Speter		/* if too much buffer supplied, trim it down */
11819455Speter		if (size > needed)
11829455Speter			size = needed;
11839455Speter
11849455Speter		/* how much of the buffer is remaining */
11859455Speter		left = size;
11869455Speter
11879455Speter		if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
11889455Speter			break;
11899455Speter
11909455Speter		/* is there any point in continuing? */
11919455Speter		if (left > sizeof(bsdi_si)) {
11929455Speter			left -= sizeof(bsdi_si);
11939455Speter			error = copyout(&bsdi_strings,
11949455Speter					uap->where + sizeof(bsdi_si), left);
11959455Speter		}
11969455Speter		break;
11979455Speter	}
11989455Speter
11991541Srgrimes	default:
12001541Srgrimes		return (EOPNOTSUPP);
12011541Srgrimes	}
12021541Srgrimes	if (error)
12031541Srgrimes		return (error);
12041541Srgrimes	*retval = size;
12051541Srgrimes	if (uap->size)
12061541Srgrimes		error = copyout((caddr_t)&size, (caddr_t)uap->size,
12071541Srgrimes		    sizeof(size));
12081541Srgrimes	return (error);
12091541Srgrimes}
12101541Srgrimes#endif /* COMPAT_43 */
1211