* 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.
* %sccs.include.redist.c%
* @(#)kern_sysctl.c 8.6 (Berkeley) %G%
extern sysctlfn vm_sysctl
;
extern sysctlfn fs_sysctl
;
extern sysctlfn net_sysctl
;
extern sysctlfn cpu_sysctl
;
static struct sysctl_lock
{
register struct sysctl_args
*uap
;
u_int savelen
, oldlen
= 0;
if (uap
->new != NULL
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
* all top-level sysctl names are non-terminal
if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
if (error
= copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int)))
if (name
[2] == KERN_VNODE
) /* XXX */
(error
= copyin(uap
->oldlenp
, &oldlen
, sizeof(oldlen
))))
if (!useracc(uap
->old
, oldlen
, B_WRITE
))
while (memlock
.sl_lock
) {
sleep((caddr_t
)&memlock
, PRIBIO
+1);
vslock(uap
->old
, oldlen
);
error
= (*fn
)(name
+ 1, uap
->namelen
- 1, uap
->old
, &oldlen
,
uap
->new, uap
->newlen
, p
);
vsunlock(uap
->old
, savelen
, B_WRITE
);
wakeup((caddr_t
)&memlock
);
error
= copyout(&oldlen
, uap
->oldlenp
, sizeof(oldlen
));
* Attributes stored in the kernel.
char hostname
[MAXHOSTNAMELEN
];
* kernel related system variables.
kern_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, 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 */
return (sysctl_rdstring(oldp
, oldlenp
, newp
, ostype
));
return (sysctl_rdstring(oldp
, oldlenp
, newp
, osrelease
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, BSD
));
return (sysctl_rdstring(oldp
, oldlenp
, newp
, version
));
return(sysctl_int(oldp
, oldlenp
, newp
, newlen
, &desiredvnodes
));
return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &maxproc
));
return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &maxfiles
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, ARG_MAX
));
if ((error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &level
)) ||
if (level
< securelevel
&& p
->p_pid
!= 1)
error
= sysctl_string(oldp
, oldlenp
, newp
, newlen
,
hostname
, sizeof(hostname
));
inthostid
= hostid
; /* XXX assumes sizeof long <= sizeof int */
error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &inthostid
);
return (sysctl_clockrate(oldp
, oldlenp
));
return (sysctl_rdstruct(oldp
, oldlenp
, newp
, &boottime
,
sizeof(struct timeval
)));
return (sysctl_vnode(oldp
, oldlenp
));
return (sysctl_doproc(name
+ 1, namelen
- 1, oldp
, oldlenp
));
return (sysctl_file(oldp
, oldlenp
));
return (sysctl_doprof(name
+ 1, namelen
- 1, oldp
, oldlenp
,
return (sysctl_rdint(oldp
, oldlenp
, newp
, _POSIX_VERSION
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, NGROUPS_MAX
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 0));
* hardware related system variables.
hw_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
extern char machine
[], cpu_model
[];
/* all sysctl names at this level are terminal */
return (ENOTDIR
); /* overloaded */
return (sysctl_rdstring(oldp
, oldlenp
, newp
, machine
));
return (sysctl_rdstring(oldp
, oldlenp
, newp
, cpu_model
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, 1)); /* XXX */
return (sysctl_rdint(oldp
, oldlenp
, newp
, BYTE_ORDER
));
return (sysctl_rdint(oldp
, oldlenp
, newp
, ctob(physmem
)));
return (sysctl_rdint(oldp
, oldlenp
, newp
,
ctob(physmem
- cnt
.v_wire_count
)));
return (sysctl_rdint(oldp
, oldlenp
, newp
, PAGE_SIZE
));
* 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
,
debug_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
/* all sysctl names at this level are name and field */
return (ENOTDIR
); /* overloaded */
cdp
= debugvars
[name
[0]];
return (sysctl_rdstring(oldp
, oldlenp
, newp
, cdp
->debugname
));
return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, cdp
->debugvar
));
* Validate parameters and get old / set new parameters
* for an integer-valued sysctl function.
sysctl_int(oldp
, oldlenp
, newp
, newlen
, valp
)
if (oldp
&& *oldlenp
< sizeof(int))
if (newp
&& newlen
!= sizeof(int))
error
= copyout(valp
, oldp
, sizeof(int));
error
= copyin(newp
, valp
, sizeof(int));
* As above, but read-only.
sysctl_rdint(oldp
, oldlenp
, newp
, val
)
if (oldp
&& *oldlenp
< sizeof(int))
error
= copyout((caddr_t
)&val
, oldp
, sizeof(int));
* Validate parameters and get old / set new parameters
* for a string-valued sysctl function.
sysctl_string(oldp
, oldlenp
, newp
, newlen
, str
, maxlen
)
if (oldp
&& *oldlenp
< len
)
if (newp
&& newlen
>= maxlen
)
error
= copyout(str
, oldp
, len
);
if (error
== 0 && newp
) {
error
= copyin(newp
, str
, newlen
);
* As above, but read-only.
sysctl_rdstring(oldp
, oldlenp
, newp
, str
)
if (oldp
&& *oldlenp
< len
)
error
= copyout(str
, oldp
, len
);
* Validate parameters and get old / set new parameters
* for a structure oriented sysctl function.
sysctl_struct(oldp
, oldlenp
, newp
, newlen
, sp
, len
)
if (oldp
&& *oldlenp
< len
)
if (newp
&& newlen
> len
)
error
= copyout(sp
, oldp
, len
);
error
= copyin(newp
, sp
, len
);
* Validate parameters and get old parameters
* for a structure oriented sysctl function.
sysctl_rdstruct(oldp
, oldlenp
, newp
, sp
, len
)
if (oldp
&& *oldlenp
< len
)
error
= copyout(sp
, oldp
, len
);
sysctl_file(where
, sizep
)
* overestimate by 10 files
*sizep
= sizeof(filehead
) + (nfiles
+ 10) * sizeof(struct file
);
if (buflen
< sizeof(filehead
)) {
if (error
= copyout((caddr_t
)&filehead
, where
, sizeof(filehead
)))
buflen
-= sizeof(filehead
);
where
+= sizeof(filehead
);
* followed by an array of file structures
for (fp
= filehead
.lh_first
; fp
!= 0; fp
= fp
->f_list
.le_next
) {
if (buflen
< sizeof(struct file
)) {
if (error
= copyout((caddr_t
)fp
, where
, sizeof (struct file
)))
buflen
-= sizeof(struct file
);
where
+= sizeof(struct file
);
* try over estimating by 5 procs
#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
sysctl_doproc(name
, namelen
, where
, sizep
)
register struct kinfo_proc
*dp
= (struct kinfo_proc
*)where
;
int buflen
= where
!= NULL
? *sizep
: 0;
if (namelen
!= 2 && !(namelen
== 1 && name
[0] == KERN_PROC_ALL
))
for (; p
!= 0; p
= p
->p_list
.le_next
) {
* Skip embryonic processes.
* TODO - make more efficient (see notes below).
/* could do this with just a lookup */
if (p
->p_pid
!= (pid_t
)name
[1])
/* could do this by traversing pgrp */
if (p
->p_pgrp
->pg_id
!= (pid_t
)name
[1])
if ((p
->p_flag
& P_CONTROLT
) == 0 ||
p
->p_session
->s_ttyp
== NULL
||
p
->p_session
->s_ttyp
->t_dev
!= (dev_t
)name
[1])
if (p
->p_ucred
->cr_uid
!= (uid_t
)name
[1])
if (p
->p_cred
->p_ruid
!= (uid_t
)name
[1])
if (buflen
>= sizeof(struct kinfo_proc
)) {
if (error
= copyout((caddr_t
)p
, &dp
->kp_proc
,
if (error
= copyout((caddr_t
)&eproc
, &dp
->kp_eproc
,
buflen
-= sizeof(struct kinfo_proc
);
needed
+= sizeof(struct kinfo_proc
);
*sizep
= (caddr_t
)dp
- where
;
* Fill in an eproc structure for the specified process.
register struct eproc
*ep
;
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_pmap = XXX; */
register struct vmspace
*vm
= p
->p_vmspace
;
#ifdef pmap_resident_count
ep
->e_vm
.vm_rssize
= pmap_resident_count(&vm
->vm_pmap
); /*XXX*/
ep
->e_vm
.vm_rssize
= vm
->vm_rssize
;
ep
->e_vm
.vm_tsize
= vm
->vm_tsize
;
ep
->e_vm
.vm_dsize
= vm
->vm_dsize
;
ep
->e_vm
.vm_ssize
= vm
->vm_ssize
;
ep
->e_vm
.vm_pmap
= vm
->vm_pmap
;
ep
->e_ppid
= p
->p_pptr
->p_pid
;
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_tpgid
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: NO_PID
;
ep
->e_tsess
= tp
->t_session
;
ep
->e_flag
= ep
->e_sess
->s_ttyvp
? EPROC_CTTY
: 0;
ep
->e_flag
|= EPROC_SLEADER
;
strncpy(ep
->e_wmesg
, p
->p_wmesg
, WMESGLEN
);
ep
->e_xsize
= ep
->e_xrssize
= 0;
ep
->e_xccount
= ep
->e_xswrss
= 0;
#define KINFO_PROC (0<<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
{
ogetkerninfo(p
, uap
, retval
)
register struct getkerninfo_args
*uap
;
(error
= copyin((caddr_t
)uap
->size
, (caddr_t
)&size
, sizeof(size
))))
switch (uap
->op
& 0xff00) {
name
[2] = (uap
->op
& 0xff0000) >> 16;
name
[3] = uap
->op
& 0xff;
error
= net_sysctl(name
, 5, uap
->where
, &size
, NULL
, 0, p
);
error
= kern_sysctl(name
, 1, uap
->where
, &size
, NULL
, 0, p
);
name
[1] = uap
->op
& 0xff;
error
= kern_sysctl(name
, 3, uap
->where
, &size
, NULL
, 0, p
);
error
= kern_sysctl(name
, 1, uap
->where
, &size
, NULL
, 0, p
);
error
= vm_sysctl(name
, 1, uap
->where
, &size
, NULL
, 0, p
);
error
= vm_sysctl(name
, 1, uap
->where
, &size
, NULL
, 0, p
);
name
[0] = KERN_CLOCKRATE
;
error
= kern_sysctl(name
, 1, uap
->where
, &size
, NULL
, 0, p
);
error
= copyout((caddr_t
)&size
, (caddr_t
)uap
->size
,