+ if (SCARG(uap, oldlenp) &&
+ (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
+ return (error);
+ if (SCARG(uap, old) != NULL) {
+ if (!useracc(SCARG(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(SCARG(uap, old), oldlen);
+ savelen = oldlen;
+ }
+ error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old),
+ &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
+ if (SCARG(uap, old) != NULL) {
+ if (dolock)
+ vsunlock(SCARG(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 (SCARG(uap, oldlenp))
+ error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
+ *retval = oldlen;
+ return (0);
+}
+
+/*
+ * Attributes stored in the kernel.
+ */
+char hostname[MAXHOSTNAMELEN];
+int hostnamelen;
+long hostid;
+int securelevel;
+
+/*
+ * kernel related system variables.
+ */
+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_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_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_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