From 1c346c709215b42b13b762c12a256d333b98f1bc Mon Sep 17 00:00:00 2001 From: Nate Williams Date: Mon, 10 Jun 1996 16:23:42 +0000 Subject: Implemented 'kern_sysctl', which differs from 'userland_sysctl' in that it assumes all of the data exists in the kernel. Also, fix sysctl_new-kernel (unused until now) which had reversed operands to bcopy(). Reviewed by: phk Poul writes: ... actually the lock/sleep/wakeup cruft shouldn't be needed in the kernel version I think, but just leave it there for now. --- sys/kern/kern_sysctl.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++---- sys/sys/sysctl.h | 3 ++- 2 files changed, 65 insertions(+), 6 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 51c78b9a1cc2..1d26922369d5 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 - * $Id: kern_sysctl.c,v 1.62 1996/04/13 13:28:54 phk Exp $ + * $Id: kern_sysctl.c,v 1.63 1996/06/06 17:17:54 phk Exp $ */ #include @@ -571,24 +571,82 @@ sysctl_old_kernel(struct sysctl_req *req, const void *p, int l) bcopy(p, req->oldptr + req->oldidx, i); } req->oldidx += l; - if (i != l) + if (req->oldptr && i != l) return (ENOMEM); return (0); - } static int -sysctl_new_kernel(struct sysctl_req *req, const void *p, int l) +sysctl_new_kernel(struct sysctl_req *req, void *p, int l) { if (!req->newptr) return 0; if (req->newlen - req->newidx < l) return (EINVAL); - bcopy(p, req->newptr + req->newidx, l); + bcopy(req->newptr + req->newidx, p, l); req->newidx += l; return (0); } +int +kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, int *retval) +{ + int error = 0; + struct sysctl_req req; + + bzero(&req, sizeof req); + + req.p = p; + + if (oldlenp) { + req.oldlen = *oldlenp; + } + + if (old) { + req.oldptr= old; + } + + if (newlen) { + req.newlen = newlen; + req.newptr = new; + } + + req.oldfunc = sysctl_old_kernel; + req.newfunc = sysctl_new_kernel; + req.lock = 1; + + /* XXX this should probably be done in a general way */ + while (memlock.sl_lock) { + memlock.sl_want = 1; + (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); + memlock.sl_locked++; + } + memlock.sl_lock = 1; + + error = sysctl_root(0, name, namelen, &req); + + if (req.lock == 2) + vsunlock(req.oldptr, req.oldlen, B_WRITE); + + memlock.sl_lock = 0; + + if (memlock.sl_want) { + memlock.sl_want = 0; + wakeup((caddr_t)&memlock); + } + + if (error && error != ENOMEM) + return (error); + + if (retval) { + if (req.oldptr && req.oldidx > req.oldlen) + *retval = req.oldlen; + else + *retval = req.oldidx; + } + return (error); +} + /* * Transfer function to/from user space. */ diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 90b9f61a894e..f69f26d9a306 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)sysctl.h 8.1 (Berkeley) 6/2/93 - * $Id: sysctl.h,v 1.40 1996/02/24 14:32:53 peter Exp $ + * $Id: sysctl.h,v 1.41 1996/03/11 02:17:53 hsu Exp $ */ #ifndef _SYS_SYSCTL_H_ @@ -370,6 +370,7 @@ extern char machine[]; extern char osrelease[]; extern char ostype[]; +int kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, int *retval); int userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval); /* int sysctl_clockrate __P((char *, size_t*)); -- cgit v1.2.3