xref: /openbsd-src/sys/kern/kern_sysctl.c (revision 8500990981f885cbe5e6a4958549cacc238b5ae6)
1 /*	$OpenBSD: kern_sysctl.c,v 1.92 2003/11/23 20:17:14 millert Exp $	*/
2 /*	$NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $	*/
3 
4 /*-
5  * Copyright (c) 1982, 1986, 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Mike Karels at Berkeley Software Design, Inc.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
36  */
37 
38 /*
39  * sysctl system call.
40  */
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/proc.h>
47 #include <sys/resourcevar.h>
48 #include <sys/file.h>
49 #include <sys/vnode.h>
50 #include <sys/unistd.h>
51 #include <sys/buf.h>
52 #include <sys/ioctl.h>
53 #include <sys/tty.h>
54 #include <sys/disklabel.h>
55 #include <sys/disk.h>
56 #include <uvm/uvm_extern.h>
57 #include <sys/sysctl.h>
58 #include <sys/msgbuf.h>
59 #include <sys/dkstat.h>
60 #include <sys/vmmeter.h>
61 #include <sys/namei.h>
62 #include <sys/exec.h>
63 #include <sys/mbuf.h>
64 #include <sys/sensors.h>
65 
66 #include <sys/mount.h>
67 #include <sys/syscallargs.h>
68 #include <dev/rndvar.h>
69 
70 #ifdef DDB
71 #include <ddb/db_var.h>
72 #endif
73 
74 #ifdef SYSVMSG
75 #include <sys/msg.h>
76 #endif
77 #ifdef SYSVSEM
78 #include <sys/sem.h>
79 #endif
80 #ifdef SYSVSHM
81 #include <sys/shm.h>
82 #endif
83 
84 extern struct forkstat forkstat;
85 extern struct nchstats nchstats;
86 extern int nselcoll, fscale;
87 extern struct disklist_head disklist;
88 extern fixpt_t ccpu;
89 extern  long numvnodes;
90 
91 int sysctl_diskinit(int, struct proc *);
92 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
93 int sysctl_intrcnt(int *, u_int, void *, size_t *);
94 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
95 int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t);
96 
97 /*
98  * Lock to avoid too many processes vslocking a large amount of memory
99  * at the same time.
100  */
101 struct lock sysctl_lock, sysctl_disklock;
102 
103 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
104 struct lock sysctl_kmemlock;
105 #endif
106 
107 void
108 sysctl_init()
109 {
110 	lockinit(&sysctl_lock, PLOCK|PCATCH, "sysctl", 0, 0);
111 	lockinit(&sysctl_disklock, PLOCK|PCATCH, "sysctl_disklock", 0, 0);
112 
113 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
114 	lockinit(&sysctl_kmemlock, PLOCK|PCATCH, "sysctl_kmemlock", 0, 0);
115 #endif
116 }
117 
118 int
119 sys___sysctl(p, v, retval)
120 	struct proc *p;
121 	void *v;
122 	register_t *retval;
123 {
124 	register struct sys___sysctl_args /* {
125 		syscallarg(int *) name;
126 		syscallarg(u_int) namelen;
127 		syscallarg(void *) old;
128 		syscallarg(size_t *) oldlenp;
129 		syscallarg(void *) new;
130 		syscallarg(size_t) newlen;
131 	} */ *uap = v;
132 	int error, dolock = 1;
133 	size_t savelen = 0, oldlen = 0;
134 	sysctlfn *fn;
135 	int name[CTL_MAXNAME];
136 
137 	if (SCARG(uap, new) != NULL &&
138 	    (error = suser(p, 0)))
139 		return (error);
140 	/*
141 	 * all top-level sysctl names are non-terminal
142 	 */
143 	if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
144 		return (EINVAL);
145 	error = copyin(SCARG(uap, name), name,
146 		       SCARG(uap, namelen) * sizeof(int));
147 	if (error)
148 		return (error);
149 
150 	switch (name[0]) {
151 	case CTL_KERN:
152 		fn = kern_sysctl;
153 		if (name[1] == KERN_VNODE)	/* XXX */
154 			dolock = 0;
155 		break;
156 	case CTL_HW:
157 		fn = hw_sysctl;
158 		break;
159 	case CTL_VM:
160 		fn = uvm_sysctl;
161 		break;
162 	case CTL_NET:
163 		fn = net_sysctl;
164 		break;
165 	case CTL_FS:
166 		fn = fs_sysctl;
167 		break;
168 	case CTL_VFS:
169 		fn = vfs_sysctl;
170 		break;
171 	case CTL_MACHDEP:
172 		fn = cpu_sysctl;
173 		break;
174 #ifdef DEBUG
175 	case CTL_DEBUG:
176 		fn = debug_sysctl;
177 		break;
178 #endif
179 #ifdef DDB
180 	case CTL_DDB:
181 		fn = ddb_sysctl;
182 		break;
183 #endif
184 	default:
185 		return (EOPNOTSUPP);
186 	}
187 
188 	if (SCARG(uap, oldlenp) &&
189 	    (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
190 		return (error);
191 	if (SCARG(uap, old) != NULL) {
192 		if ((error = lockmgr(&sysctl_lock, LK_EXCLUSIVE, NULL, p)) != 0)
193 			return (error);
194 		if (dolock) {
195 			error = uvm_vslock(p, SCARG(uap, old), oldlen,
196 			    VM_PROT_READ|VM_PROT_WRITE);
197 			if (error) {
198 				lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
199 				return (error);
200 			}
201 		}
202 		savelen = oldlen;
203 	}
204 	error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
205 	    &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
206 	if (SCARG(uap, old) != NULL) {
207 		if (dolock)
208 			uvm_vsunlock(p, SCARG(uap, old), savelen);
209 		lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
210 	}
211 	if (error)
212 		return (error);
213 	if (SCARG(uap, oldlenp))
214 		error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
215 	return (error);
216 }
217 
218 /*
219  * Attributes stored in the kernel.
220  */
221 char hostname[MAXHOSTNAMELEN];
222 int hostnamelen;
223 char domainname[MAXHOSTNAMELEN];
224 int domainnamelen;
225 long hostid;
226 char *disknames = NULL;
227 struct diskstats *diskstats = NULL;
228 #ifdef INSECURE
229 int securelevel = -1;
230 #else
231 int securelevel;
232 #endif
233 
234 /*
235  * kernel related system variables.
236  */
237 int
238 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
239 	int *name;
240 	u_int namelen;
241 	void *oldp;
242 	size_t *oldlenp;
243 	void *newp;
244 	size_t newlen;
245 	struct proc *p;
246 {
247 	int error, level, inthostid, stackgap;
248 	extern int somaxconn, sominconn;
249 	extern int usermount, nosuidcoredump;
250 	extern long cp_time[CPUSTATES];
251 	extern int stackgap_random;
252 #ifdef CRYPTO
253 	extern int usercrypto;
254 	extern int userasymcrypto;
255 	extern int cryptodevallowsoft;
256 #endif
257 
258 	/* all sysctl names at this level are terminal except a ton of them */
259 	if (namelen != 1) {
260 		switch (name[0]) {
261 		case KERN_PROC:
262 		case KERN_PROF:
263 		case KERN_MALLOCSTATS:
264 		case KERN_TTY:
265 		case KERN_POOL:
266 		case KERN_PROC_ARGS:
267 		case KERN_SYSVIPC_INFO:
268 		case KERN_SEMINFO:
269 		case KERN_SHMINFO:
270 		case KERN_INTRCNT:
271 		case KERN_WATCHDOG:
272 		case KERN_EMUL:
273 			break;
274 		default:
275 			return (ENOTDIR);	/* overloaded */
276 		}
277 	}
278 
279 	switch (name[0]) {
280 	case KERN_OSTYPE:
281 		return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
282 	case KERN_OSRELEASE:
283 		return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
284 	case KERN_OSREV:
285 		return (sysctl_rdint(oldp, oldlenp, newp, OpenBSD));
286 	case KERN_OSVERSION:
287 		return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
288 	case KERN_VERSION:
289 		return (sysctl_rdstring(oldp, oldlenp, newp, version));
290 	case KERN_MAXVNODES:
291 		return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
292 	case KERN_MAXPROC:
293 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
294 	case KERN_MAXFILES:
295 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
296 	case KERN_NFILES:
297 		return (sysctl_rdint(oldp, oldlenp, newp, nfiles));
298 	case KERN_TTYCOUNT:
299 		return (sysctl_rdint(oldp, oldlenp, newp, tty_count));
300 	case KERN_NUMVNODES:
301 		return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
302 	case KERN_ARGMAX:
303 		return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
304 	case KERN_NSELCOLL:
305 		return (sysctl_rdint(oldp, oldlenp, newp, nselcoll));
306 	case KERN_SECURELVL:
307 		level = securelevel;
308 		if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
309 		    newp == NULL)
310 			return (error);
311 		if ((securelevel > 0 || level < -1) &&
312 		    level < securelevel && p->p_pid != 1)
313 			return (EPERM);
314 		securelevel = level;
315 		return (0);
316 	case KERN_HOSTNAME:
317 		error = sysctl_tstring(oldp, oldlenp, newp, newlen,
318 		    hostname, sizeof(hostname));
319 		if (newp && !error)
320 			hostnamelen = newlen;
321 		return (error);
322 	case KERN_DOMAINNAME:
323 		error = sysctl_tstring(oldp, oldlenp, newp, newlen,
324 		    domainname, sizeof(domainname));
325 		if (newp && !error)
326 			domainnamelen = newlen;
327 		return (error);
328 	case KERN_HOSTID:
329 		inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
330 		error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
331 		hostid = inthostid;
332 		return (error);
333 	case KERN_CLOCKRATE:
334 		return (sysctl_clockrate(oldp, oldlenp));
335 	case KERN_BOOTTIME:
336 		return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
337 		    sizeof(struct timeval)));
338 	case KERN_VNODE:
339 		return (sysctl_vnode(oldp, oldlenp, p));
340 	case KERN_PROC:
341 		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
342 	case KERN_PROC_ARGS:
343 		return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
344 		     p));
345 	case KERN_FILE:
346 		return (sysctl_file(oldp, oldlenp));
347 	case KERN_MBSTAT:
348 		return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat,
349 		    sizeof(mbstat)));
350 #ifdef GPROF
351 	case KERN_PROF:
352 		return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
353 		    newp, newlen));
354 #endif
355 	case KERN_POSIX1:
356 		return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
357 	case KERN_NGROUPS:
358 		return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
359 	case KERN_JOB_CONTROL:
360 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
361 	case KERN_SAVED_IDS:
362 #ifdef _POSIX_SAVED_IDS
363 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
364 #else
365 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
366 #endif
367 	case KERN_MAXPARTITIONS:
368 		return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
369 	case KERN_RAWPARTITION:
370 		return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
371 	case KERN_SOMAXCONN:
372 		return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn));
373 	case KERN_SOMINCONN:
374 		return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn));
375 	case KERN_USERMOUNT:
376 		return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount));
377 	case KERN_RND:
378 		return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats,
379 		    sizeof(rndstats)));
380 	case KERN_ARND:
381 		return (sysctl_rdint(oldp, oldlenp, newp, arc4random()));
382 	case KERN_NOSUIDCOREDUMP:
383 		return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump));
384 	case KERN_FSYNC:
385 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
386 	case KERN_SYSVMSG:
387 #ifdef SYSVMSG
388 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
389 #else
390 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
391 #endif
392 	case KERN_SYSVSEM:
393 #ifdef SYSVSEM
394 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
395 #else
396 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
397 #endif
398 	case KERN_SYSVSHM:
399 #ifdef SYSVSHM
400 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
401 #else
402 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
403 #endif
404 	case KERN_MSGBUFSIZE:
405 		/*
406 		 * deal with cases where the message buffer has
407 		 * become corrupted.
408 		 */
409 		if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
410 			return (ENXIO);
411 		return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
412 	case KERN_MSGBUF:
413 		/* see note above */
414 		if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
415 			return (ENXIO);
416 		return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp,
417 		    msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
418 	case KERN_MALLOCSTATS:
419 		return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp,
420 		    newp, newlen, p));
421 	case KERN_CPTIME:
422 		return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
423 		    sizeof(cp_time)));
424 	case KERN_NCHSTATS:
425 		return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
426 		    sizeof(struct nchstats)));
427 	case KERN_FORKSTAT:
428 		return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
429 		    sizeof(struct forkstat)));
430 	case KERN_TTY:
431 		return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp,
432 		    newp, newlen));
433 	case KERN_FSCALE:
434 		return (sysctl_rdint(oldp, oldlenp, newp, fscale));
435 	case KERN_CCPU:
436 		return (sysctl_rdint(oldp, oldlenp, newp, ccpu));
437 	case KERN_NPROCS:
438 		return (sysctl_rdint(oldp, oldlenp, newp, nprocs));
439 	case KERN_POOL:
440 		return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp));
441 	case KERN_STACKGAPRANDOM:
442 		stackgap = stackgap_random;
443 		error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap);
444 		if (error)
445 			return (error);
446 		/*
447 		 * Safety harness.
448 		 */
449 		if ((stackgap < ALIGNBYTES && stackgap != 0) ||
450 		    !powerof2(stackgap) || stackgap >= 256 * 1024 * 1024)
451 			return (EINVAL);
452 		stackgap_random = stackgap;
453 		return (0);
454 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
455 	case KERN_SYSVIPC_INFO:
456 		return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp));
457 #endif
458 #ifdef CRYPTO
459 	case KERN_USERCRYPTO:
460 		return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto));
461 	case KERN_USERASYMCRYPTO:
462 		return (sysctl_int(oldp, oldlenp, newp, newlen,
463 			    &userasymcrypto));
464 	case KERN_CRYPTODEVALLOWSOFT:
465 		return (sysctl_int(oldp, oldlenp, newp, newlen,
466 			    &cryptodevallowsoft));
467 #endif
468 	case KERN_SPLASSERT:
469 		return (sysctl_int(oldp, oldlenp, newp, newlen,
470 		    &splassert_ctl));
471 #ifdef SYSVSEM
472 	case KERN_SEMINFO:
473 		return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp,
474 		    newp, newlen));
475 #endif
476 #ifdef SYSVSHM
477 	case KERN_SHMINFO:
478 		return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp,
479 		    newp, newlen));
480 #endif
481 	case KERN_INTRCNT:
482 		return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp));
483 	case KERN_WATCHDOG:
484 		return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
485 		    newp, newlen));
486 	case KERN_EMUL:
487 		return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp,
488 		    newp, newlen));
489 	default:
490 		return (EOPNOTSUPP);
491 	}
492 	/* NOTREACHED */
493 }
494 
495 /*
496  * hardware related system variables.
497  */
498 int
499 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
500 	int *name;
501 	u_int namelen;
502 	void *oldp;
503 	size_t *oldlenp;
504 	void *newp;
505 	size_t newlen;
506 	struct proc *p;
507 {
508 	extern char machine[], cpu_model[];
509 	int err;
510 
511 	/* all sysctl names at this level except sensors are terminal */
512 	if (name[0] != HW_SENSORS && namelen != 1)
513 		return (ENOTDIR);		/* overloaded */
514 
515 	switch (name[0]) {
516 	case HW_MACHINE:
517 		return (sysctl_rdstring(oldp, oldlenp, newp, machine));
518 	case HW_MODEL:
519 		return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
520 	case HW_NCPU:
521 		return (sysctl_rdint(oldp, oldlenp, newp, 1));	/* XXX */
522 	case HW_BYTEORDER:
523 		return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
524 	case HW_PHYSMEM:
525 		return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
526 	case HW_USERMEM:
527 		return (sysctl_rdint(oldp, oldlenp, newp,
528 		    ctob(physmem - uvmexp.wired)));
529 	case HW_PAGESIZE:
530 		return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
531 	case HW_DISKNAMES:
532 		err = sysctl_diskinit(0, p);
533 		if (err)
534 			return err;
535 		if (disknames)
536 			return (sysctl_rdstring(oldp, oldlenp, newp,
537 			    disknames));
538 		else
539 			return (sysctl_rdstring(oldp, oldlenp, newp, ""));
540 	case HW_DISKSTATS:
541 		err = sysctl_diskinit(1, p);
542 		if (err)
543 			return err;
544 		return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
545 		    disk_count * sizeof(struct diskstats)));
546 	case HW_DISKCOUNT:
547 		return (sysctl_rdint(oldp, oldlenp, newp, disk_count));
548 	case HW_SENSORS:
549 		return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
550 		    newp, newlen));
551 	default:
552 		return (EOPNOTSUPP);
553 	}
554 	/* NOTREACHED */
555 }
556 
557 #ifdef DEBUG
558 /*
559  * Debugging related system variables.
560  */
561 extern struct ctldebug debug0, debug1;
562 struct ctldebug debug2, debug3, debug4;
563 struct ctldebug debug5, debug6, debug7, debug8, debug9;
564 struct ctldebug debug10, debug11, debug12, debug13, debug14;
565 struct ctldebug debug15, debug16, debug17, debug18, debug19;
566 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
567 	&debug0, &debug1, &debug2, &debug3, &debug4,
568 	&debug5, &debug6, &debug7, &debug8, &debug9,
569 	&debug10, &debug11, &debug12, &debug13, &debug14,
570 	&debug15, &debug16, &debug17, &debug18, &debug19,
571 };
572 int
573 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
574 	int *name;
575 	u_int namelen;
576 	void *oldp;
577 	size_t *oldlenp;
578 	void *newp;
579 	size_t newlen;
580 	struct proc *p;
581 {
582 	struct ctldebug *cdp;
583 
584 	/* all sysctl names at this level are name and field */
585 	if (namelen != 2)
586 		return (ENOTDIR);		/* overloaded */
587 	cdp = debugvars[name[0]];
588 	if (cdp->debugname == 0)
589 		return (EOPNOTSUPP);
590 	switch (name[1]) {
591 	case CTL_DEBUG_NAME:
592 		return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
593 	case CTL_DEBUG_VALUE:
594 		return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
595 	default:
596 		return (EOPNOTSUPP);
597 	}
598 	/* NOTREACHED */
599 }
600 #endif /* DEBUG */
601 
602 /*
603  * Validate parameters and get old / set new parameters
604  * for an integer-valued sysctl function.
605  */
606 int
607 sysctl_int(oldp, oldlenp, newp, newlen, valp)
608 	void *oldp;
609 	size_t *oldlenp;
610 	void *newp;
611 	size_t newlen;
612 	int *valp;
613 {
614 	int error = 0;
615 
616 	if (oldp && *oldlenp < sizeof(int))
617 		return (ENOMEM);
618 	if (newp && newlen != sizeof(int))
619 		return (EINVAL);
620 	*oldlenp = sizeof(int);
621 	if (oldp)
622 		error = copyout(valp, oldp, sizeof(int));
623 	if (error == 0 && newp)
624 		error = copyin(newp, valp, sizeof(int));
625 	return (error);
626 }
627 
628 /*
629  * As above, but read-only.
630  */
631 int
632 sysctl_rdint(oldp, oldlenp, newp, val)
633 	void *oldp;
634 	size_t *oldlenp;
635 	void *newp;
636 	int val;
637 {
638 	int error = 0;
639 
640 	if (oldp && *oldlenp < sizeof(int))
641 		return (ENOMEM);
642 	if (newp)
643 		return (EPERM);
644 	*oldlenp = sizeof(int);
645 	if (oldp)
646 		error = copyout((caddr_t)&val, oldp, sizeof(int));
647 	return (error);
648 }
649 
650 /*
651  * Validate parameters and get old / set new parameters
652  * for an integer-valued sysctl function.
653  */
654 int
655 sysctl_quad(oldp, oldlenp, newp, newlen, valp)
656 	void *oldp;
657 	size_t *oldlenp;
658 	void *newp;
659 	size_t newlen;
660 	int64_t *valp;
661 {
662 	int error = 0;
663 
664 	if (oldp && *oldlenp < sizeof(int64_t))
665 		return (ENOMEM);
666 	if (newp && newlen != sizeof(int64_t))
667 		return (EINVAL);
668 	*oldlenp = sizeof(int64_t);
669 	if (oldp)
670 		error = copyout(valp, oldp, sizeof(int64_t));
671 	if (error == 0 && newp)
672 		error = copyin(newp, valp, sizeof(int64_t));
673 	return (error);
674 }
675 
676 /*
677  * As above, but read-only.
678  */
679 int
680 sysctl_rdquad(oldp, oldlenp, newp, val)
681 	void *oldp;
682 	size_t *oldlenp;
683 	void *newp;
684 	int64_t val;
685 {
686 	int error = 0;
687 
688 	if (oldp && *oldlenp < sizeof(int64_t))
689 		return (ENOMEM);
690 	if (newp)
691 		return (EPERM);
692 	*oldlenp = sizeof(int64_t);
693 	if (oldp)
694 		error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
695 	return (error);
696 }
697 
698 /*
699  * Validate parameters and get old / set new parameters
700  * for a string-valued sysctl function.
701  */
702 int
703 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
704 	void *oldp;
705 	size_t *oldlenp;
706 	void *newp;
707 	size_t newlen;
708 	char *str;
709 	int maxlen;
710 {
711 	return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
712 }
713 
714 int
715 sysctl_tstring(oldp, oldlenp, newp, newlen, str, maxlen)
716 	void *oldp;
717 	size_t *oldlenp;
718 	void *newp;
719 	size_t newlen;
720 	char *str;
721 	int maxlen;
722 {
723 	return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
724 }
725 
726 int
727 sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, trunc)
728 	void *oldp;
729 	size_t *oldlenp;
730 	void *newp;
731 	size_t newlen;
732 	char *str;
733 	int maxlen;
734 	int trunc;
735 {
736 	int len, error = 0;
737 	char c;
738 
739 	len = strlen(str) + 1;
740 	if (oldp && *oldlenp < len) {
741 		if (trunc == 0 || *oldlenp == 0)
742 			return (ENOMEM);
743 	}
744 	if (newp && newlen >= maxlen)
745 		return (EINVAL);
746 	if (oldp) {
747 		if (trunc && *oldlenp < len) {
748 			/* save & zap NUL terminator while copying */
749 			c = str[*oldlenp-1];
750 			str[*oldlenp-1] = '\0';
751 			error = copyout(str, oldp, *oldlenp);
752 			str[*oldlenp-1] = c;
753 		} else {
754 			*oldlenp = len;
755 			error = copyout(str, oldp, len);
756 		}
757 	}
758 	if (error == 0 && newp) {
759 		error = copyin(newp, str, newlen);
760 		str[newlen] = 0;
761 	}
762 	return (error);
763 }
764 
765 /*
766  * As above, but read-only.
767  */
768 int
769 sysctl_rdstring(oldp, oldlenp, newp, str)
770 	void *oldp;
771 	size_t *oldlenp;
772 	void *newp;
773 	const char *str;
774 {
775 	int len, error = 0;
776 
777 	len = strlen(str) + 1;
778 	if (oldp && *oldlenp < len)
779 		return (ENOMEM);
780 	if (newp)
781 		return (EPERM);
782 	*oldlenp = len;
783 	if (oldp)
784 		error = copyout(str, oldp, len);
785 	return (error);
786 }
787 
788 /*
789  * Validate parameters and get old / set new parameters
790  * for a structure oriented sysctl function.
791  */
792 int
793 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
794 	void *oldp;
795 	size_t *oldlenp;
796 	void *newp;
797 	size_t newlen;
798 	void *sp;
799 	int len;
800 {
801 	int error = 0;
802 
803 	if (oldp && *oldlenp < len)
804 		return (ENOMEM);
805 	if (newp && newlen > len)
806 		return (EINVAL);
807 	if (oldp) {
808 		*oldlenp = len;
809 		error = copyout(sp, oldp, len);
810 	}
811 	if (error == 0 && newp)
812 		error = copyin(newp, sp, len);
813 	return (error);
814 }
815 
816 /*
817  * Validate parameters and get old parameters
818  * for a structure oriented sysctl function.
819  */
820 int
821 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
822 	void *oldp;
823 	size_t *oldlenp;
824 	void *newp;
825 	const void *sp;
826 	int len;
827 {
828 	int error = 0;
829 
830 	if (oldp && *oldlenp < len)
831 		return (ENOMEM);
832 	if (newp)
833 		return (EPERM);
834 	*oldlenp = len;
835 	if (oldp)
836 		error = copyout(sp, oldp, len);
837 	return (error);
838 }
839 
840 /*
841  * Get file structures.
842  */
843 int
844 sysctl_file(where, sizep)
845 	char *where;
846 	size_t *sizep;
847 {
848 	int buflen, error;
849 	struct file *fp;
850 	char *start = where;
851 
852 	buflen = *sizep;
853 	if (where == NULL) {
854 		/*
855 		 * overestimate by 10 files
856 		 */
857 		*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
858 		return (0);
859 	}
860 
861 	/*
862 	 * first copyout filehead
863 	 */
864 	if (buflen < sizeof(filehead)) {
865 		*sizep = 0;
866 		return (0);
867 	}
868 	error = copyout((caddr_t)&filehead, where, sizeof(filehead));
869 	if (error)
870 		return (error);
871 	buflen -= sizeof(filehead);
872 	where += sizeof(filehead);
873 
874 	/*
875 	 * followed by an array of file structures
876 	 */
877 	LIST_FOREACH(fp, &filehead, f_list) {
878 		if (buflen < sizeof(struct file)) {
879 			*sizep = where - start;
880 			return (ENOMEM);
881 		}
882 		error = copyout((caddr_t)fp, where, sizeof (struct file));
883 		if (error)
884 			return (error);
885 		buflen -= sizeof(struct file);
886 		where += sizeof(struct file);
887 	}
888 	*sizep = where - start;
889 	return (0);
890 }
891 
892 /*
893  * try over estimating by 5 procs
894  */
895 #define KERN_PROCSLOP	(5 * sizeof (struct kinfo_proc))
896 
897 int
898 sysctl_doproc(name, namelen, where, sizep)
899 	int *name;
900 	u_int namelen;
901 	char *where;
902 	size_t *sizep;
903 {
904 	register struct proc *p;
905 	register struct kinfo_proc *dp = (struct kinfo_proc *)where;
906 	register int needed = 0;
907 	int buflen = where != NULL ? *sizep : 0;
908 	int doingzomb;
909 	struct eproc eproc;
910 	int error = 0;
911 
912 	if (namelen != 2 && !(namelen == 1 &&
913 	    (name[0] == KERN_PROC_ALL || name[0] == KERN_PROC_KTHREAD)))
914 		return (EINVAL);
915 	p = LIST_FIRST(&allproc);
916 	doingzomb = 0;
917 again:
918 	for (; p != 0; p = LIST_NEXT(p, p_list)) {
919 		/*
920 		 * Skip embryonic processes.
921 		 */
922 		if (p->p_stat == SIDL)
923 			continue;
924 		/*
925 		 * TODO - make more efficient (see notes below).
926 		 * do by session.
927 		 */
928 		switch (name[0]) {
929 
930 		case KERN_PROC_PID:
931 			/* could do this with just a lookup */
932 			if (p->p_pid != (pid_t)name[1])
933 				continue;
934 			break;
935 
936 		case KERN_PROC_PGRP:
937 			/* could do this by traversing pgrp */
938 			if (p->p_pgrp->pg_id != (pid_t)name[1])
939 				continue;
940 			break;
941 
942 		case KERN_PROC_TTY:
943 			if ((p->p_flag & P_CONTROLT) == 0 ||
944 			    p->p_session->s_ttyp == NULL ||
945 			    p->p_session->s_ttyp->t_dev != (dev_t)name[1])
946 				continue;
947 			break;
948 
949 		case KERN_PROC_UID:
950 			if (p->p_ucred->cr_uid != (uid_t)name[1])
951 				continue;
952 			break;
953 
954 		case KERN_PROC_RUID:
955 			if (p->p_cred->p_ruid != (uid_t)name[1])
956 				continue;
957 			break;
958 
959 		case KERN_PROC_ALL:
960 			if (p->p_flag & P_SYSTEM)
961 				continue;
962 			break;
963 		}
964 		if (buflen >= sizeof(struct kinfo_proc)) {
965 			fill_eproc(p, &eproc);
966 			error = copyout((caddr_t)p, &dp->kp_proc,
967 					sizeof(struct proc));
968 			if (error)
969 				return (error);
970 			error = copyout((caddr_t)&eproc, &dp->kp_eproc,
971 					sizeof(eproc));
972 			if (error)
973 				return (error);
974 			dp++;
975 			buflen -= sizeof(struct kinfo_proc);
976 		}
977 		needed += sizeof(struct kinfo_proc);
978 	}
979 	if (doingzomb == 0) {
980 		p = LIST_FIRST(&zombproc);
981 		doingzomb++;
982 		goto again;
983 	}
984 	if (where != NULL) {
985 		*sizep = (caddr_t)dp - where;
986 		if (needed > *sizep)
987 			return (ENOMEM);
988 	} else {
989 		needed += KERN_PROCSLOP;
990 		*sizep = needed;
991 	}
992 	return (0);
993 }
994 
995 /*
996  * Fill in an eproc structure for the specified process.
997  */
998 void
999 fill_eproc(struct proc *p, struct eproc *ep)
1000 {
1001 	struct tty *tp;
1002 
1003 	ep->e_paddr = p;
1004 	ep->e_sess = p->p_pgrp->pg_session;
1005 	ep->e_pcred = *p->p_cred;
1006 	ep->e_ucred = *p->p_ucred;
1007 	if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1008 		ep->e_vm.vm_rssize = 0;
1009 		ep->e_vm.vm_tsize = 0;
1010 		ep->e_vm.vm_dsize = 0;
1011 		ep->e_vm.vm_ssize = 0;
1012 		bzero(&ep->e_pstats, sizeof(ep->e_pstats));
1013 		ep->e_pstats_valid = 0;
1014 	} else {
1015 		struct vmspace *vm = p->p_vmspace;
1016 
1017 		PHOLD(p);	/* need for pstats */
1018 		ep->e_vm.vm_rssize = vm_resident_count(vm);
1019 		ep->e_vm.vm_tsize = vm->vm_tsize;
1020 		ep->e_vm.vm_dsize = vm->vm_dsize;
1021 		ep->e_vm.vm_ssize = vm->vm_ssize;
1022 		ep->e_pstats = *p->p_stats;
1023 		ep->e_pstats_valid = 1;
1024 		PRELE(p);
1025 	}
1026 	if (p->p_pptr)
1027 		ep->e_ppid = p->p_pptr->p_pid;
1028 	else
1029 		ep->e_ppid = 0;
1030 	ep->e_pgid = p->p_pgrp->pg_id;
1031 	ep->e_jobc = p->p_pgrp->pg_jobc;
1032 	if ((p->p_flag & P_CONTROLT) &&
1033 	     (tp = ep->e_sess->s_ttyp)) {
1034 		ep->e_tdev = tp->t_dev;
1035 		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1036 		ep->e_tsess = tp->t_session;
1037 	} else
1038 		ep->e_tdev = NODEV;
1039 	ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
1040 	if (SESS_LEADER(p))
1041 		ep->e_flag |= EPROC_SLEADER;
1042 	strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN);
1043 	ep->e_wmesg[WMESGLEN] = '\0';
1044 	ep->e_xsize = ep->e_xrssize = 0;
1045 	ep->e_xccount = ep->e_xswrss = 0;
1046 	strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1);
1047 	ep->e_login[MAXLOGNAME-1] = '\0';
1048 	strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN);
1049 	ep->e_emul[EMULNAMELEN] = '\0';
1050 	ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0;
1051 }
1052 
1053 int
1054 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1055     struct proc *cp)
1056 {
1057 	struct proc *vp;
1058 	pid_t pid;
1059 	int op;
1060 	struct ps_strings pss;
1061 	struct iovec iov;
1062 	struct uio uio;
1063 	int error;
1064 	size_t limit;
1065 	int cnt;
1066 	char **rargv, **vargv;		/* reader vs. victim */
1067 	char *rarg, *varg;
1068 	char *buf;
1069 
1070 	if (namelen > 2)
1071 		return (ENOTDIR);
1072 	if (namelen < 2)
1073 		return (EINVAL);
1074 
1075 	pid = name[0];
1076 	op = name[1];
1077 
1078 	switch (op) {
1079 	case KERN_PROC_ARGV:
1080 	case KERN_PROC_NARGV:
1081 	case KERN_PROC_ENV:
1082 	case KERN_PROC_NENV:
1083 		break;
1084 	default:
1085 		return (EOPNOTSUPP);
1086 	}
1087 
1088 	if ((vp = pfind(pid)) == NULL)
1089 		return (ESRCH);
1090 
1091 	if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM))
1092 		return (EINVAL);
1093 
1094 	/* Exiting - don't bother, it will be gone soon anyway */
1095 	if ((vp->p_flag & P_WEXIT))
1096 		return (ESRCH);
1097 
1098 	/* Execing - danger. */
1099 	if ((vp->p_flag & P_INEXEC))
1100 		return (EBUSY);
1101 
1102 	vp->p_vmspace->vm_refcnt++;	/* XXX */
1103 	buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
1104 
1105 	iov.iov_base = &pss;
1106 	iov.iov_len = sizeof(pss);
1107 	uio.uio_iov = &iov;
1108 	uio.uio_iovcnt = 1;
1109 	uio.uio_offset = (off_t)PS_STRINGS;
1110 	uio.uio_resid = sizeof(pss);
1111 	uio.uio_segflg = UIO_SYSSPACE;
1112 	uio.uio_rw = UIO_READ;
1113 	uio.uio_procp = cp;
1114 
1115 	if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1116 		goto out;
1117 
1118 	if (op == KERN_PROC_NARGV) {
1119 		error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
1120 		goto out;
1121 	}
1122 	if (op == KERN_PROC_NENV) {
1123 		error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
1124 		goto out;
1125 	}
1126 
1127 	if (op == KERN_PROC_ARGV) {
1128 		cnt = pss.ps_nargvstr;
1129 		vargv = pss.ps_argvstr;
1130 	} else {
1131 		cnt = pss.ps_nenvstr;
1132 		vargv = pss.ps_envstr;
1133 	}
1134 
1135 	/* -1 to have space for a terminating NUL */
1136 	limit = *oldlenp - 1;
1137 	*oldlenp = 0;
1138 
1139 	if (limit > 8 * PAGE_SIZE) {
1140 		/* Don't allow a denial of service. */
1141 		error = E2BIG;
1142 		goto out;
1143 	}
1144 
1145 	rargv = oldp;
1146 
1147 	/*
1148 	 * *oldlenp - number of bytes copied out into readers buffer.
1149 	 * limit - maximal number of bytes allowed into readers buffer.
1150 	 * rarg - pointer into readers buffer where next arg will be stored.
1151 	 * rargv - pointer into readers buffer where the next rarg pointer
1152 	 *  will be stored.
1153 	 * vargv - pointer into victim address space where the next argument
1154 	 *  will be read.
1155 	 */
1156 
1157 	/* space for cnt pointers and a NULL */
1158 	rarg = (char *)(rargv + cnt + 1);
1159 	*oldlenp += (cnt + 1) * sizeof(char **);
1160 
1161 	while (cnt > 0 && *oldlenp < limit) {
1162 		size_t len, vstrlen;
1163 
1164 		/* Write to readers argv */
1165 		if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
1166 			goto out;
1167 
1168 		/* read the victim argv */
1169 		iov.iov_base = &varg;
1170 		iov.iov_len = sizeof(varg);
1171 		uio.uio_iov = &iov;
1172 		uio.uio_iovcnt = 1;
1173 		uio.uio_offset = (off_t)(vaddr_t)vargv;
1174 		uio.uio_resid = sizeof(varg);
1175 		uio.uio_segflg = UIO_SYSSPACE;
1176 		uio.uio_rw = UIO_READ;
1177 		uio.uio_procp = cp;
1178 		if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1179 			goto out;
1180 
1181 		if (varg == NULL)
1182 			break;
1183 
1184 		/*
1185 		 * read the victim arg. We must jump through hoops to avoid
1186 		 * crossing a page boundary too much and returning an error.
1187 		 */
1188 more:
1189 		len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
1190 		/* leave space for the terminating NUL */
1191 		iov.iov_base = buf;
1192 		iov.iov_len = len;
1193 		uio.uio_iov = &iov;
1194 		uio.uio_iovcnt = 1;
1195 		uio.uio_offset = (off_t)(vaddr_t)varg;
1196 		uio.uio_resid = len;
1197 		uio.uio_segflg = UIO_SYSSPACE;
1198 		uio.uio_rw = UIO_READ;
1199 		uio.uio_procp = cp;
1200 		if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1201 			goto out;
1202 
1203 		for (vstrlen = 0; vstrlen < len; vstrlen++) {
1204 			if (buf[vstrlen] == '\0')
1205 				break;
1206 		}
1207 
1208 		/* Don't overflow readers buffer. */
1209 		if (*oldlenp + vstrlen + 1 >= limit) {
1210 			error = ENOMEM;
1211 			goto out;
1212 		}
1213 
1214 		if ((error = copyout(buf, rarg, vstrlen)) != 0)
1215 			goto out;
1216 
1217 		*oldlenp += vstrlen;
1218 		rarg += vstrlen;
1219 
1220 		/* The string didn't end in this page? */
1221 		if (vstrlen == len) {
1222 			varg += vstrlen;
1223 			goto more;
1224 		}
1225 
1226 		/* End of string. Terminate it with a NUL */
1227 		buf[0] = '\0';
1228 		if ((error = copyout(buf, rarg, 1)) != 0)
1229 			goto out;
1230 		*oldlenp += 1;
1231 		rarg += 1;
1232 
1233 		vargv++;
1234 		rargv++;
1235 		cnt--;
1236 	}
1237 
1238 	if (*oldlenp >= limit) {
1239 		error = ENOMEM;
1240 		goto out;
1241 	}
1242 
1243 	/* Write the terminating null */
1244 	rarg = NULL;
1245 	error = copyout(&rarg, rargv, sizeof(rarg));
1246 
1247 out:
1248 	uvmspace_free(vp->p_vmspace);
1249 	free(buf, M_TEMP);
1250 	return (error);
1251 }
1252 
1253 /*
1254  * Initialize disknames/diskstats for export by sysctl. If update is set,
1255  * then we simply update the disk statistics information.
1256  */
1257 int
1258 sysctl_diskinit(update, p)
1259 	int update;
1260 	struct proc *p;
1261 {
1262 	struct diskstats *sdk;
1263 	struct disk *dk;
1264 	int i, tlen, l;
1265 
1266 	if ((i = lockmgr(&sysctl_disklock, LK_EXCLUSIVE, NULL, p)) != 0)
1267 		return i;
1268 
1269 	if (disk_change) {
1270 		for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk;
1271 		    dk = TAILQ_NEXT(dk, dk_link))
1272 			tlen += strlen(dk->dk_name) + 1;
1273 		tlen++;
1274 
1275 		if (disknames)
1276 			free(disknames, M_SYSCTL);
1277 		if (diskstats)
1278 			free(diskstats, M_SYSCTL);
1279 		diskstats = NULL;
1280 		disknames = NULL;
1281 		diskstats = malloc(disk_count * sizeof(struct diskstats),
1282 		    M_SYSCTL, M_WAITOK);
1283 		disknames = malloc(tlen, M_SYSCTL, M_WAITOK);
1284 		disknames[0] = '\0';
1285 
1286 		for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk;
1287 		    dk = TAILQ_NEXT(dk, dk_link), i++) {
1288 			snprintf(disknames + l, tlen - l, "%s,",
1289 			    dk->dk_name ? dk->dk_name : "");
1290 			l += strlen(disknames + l);
1291 			sdk = diskstats + i;
1292 			sdk->ds_busy = dk->dk_busy;
1293 			sdk->ds_xfer = dk->dk_xfer;
1294 			sdk->ds_seek = dk->dk_seek;
1295 			sdk->ds_bytes = dk->dk_bytes;
1296 			sdk->ds_attachtime = dk->dk_attachtime;
1297 			sdk->ds_timestamp = dk->dk_timestamp;
1298 			sdk->ds_time = dk->dk_time;
1299 		}
1300 
1301 		/* Eliminate trailing comma */
1302 		if (l != 0)
1303 			disknames[l - 1] = '\0';
1304 		disk_change = 0;
1305 	} else if (update) {
1306 		/* Just update, number of drives hasn't changed */
1307 		for (dk = TAILQ_FIRST(&disklist), i = 0; dk;
1308 		    dk = TAILQ_NEXT(dk, dk_link), i++) {
1309 			sdk = diskstats + i;
1310 			sdk->ds_busy = dk->dk_busy;
1311 			sdk->ds_xfer = dk->dk_xfer;
1312 			sdk->ds_seek = dk->dk_seek;
1313 			sdk->ds_bytes = dk->dk_bytes;
1314 			sdk->ds_attachtime = dk->dk_attachtime;
1315 			sdk->ds_timestamp = dk->dk_timestamp;
1316 			sdk->ds_time = dk->dk_time;
1317 		}
1318 	}
1319 	lockmgr(&sysctl_disklock, LK_RELEASE, NULL, p);
1320 	return 0;
1321 }
1322 
1323 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
1324 int
1325 sysctl_sysvipc(name, namelen, where, sizep)
1326 	int *name;
1327 	u_int namelen;
1328 	void *where;
1329 	size_t *sizep;
1330 {
1331 #ifdef SYSVMSG
1332 	struct msg_sysctl_info *msgsi;
1333 #endif
1334 #ifdef SYSVSEM
1335 	struct sem_sysctl_info *semsi;
1336 #endif
1337 #ifdef SYSVSHM
1338 	struct shm_sysctl_info *shmsi;
1339 #endif
1340 	size_t infosize, dssize, tsize, buflen;
1341 	int i, nds, error, ret;
1342 	void *buf;
1343 
1344 	if (namelen != 1)
1345 		return (EINVAL);
1346 
1347 	buflen = *sizep;
1348 
1349 	switch (*name) {
1350 	case KERN_SYSVIPC_MSG_INFO:
1351 #ifdef SYSVMSG
1352 		infosize = sizeof(msgsi->msginfo);
1353 		nds = msginfo.msgmni;
1354 		dssize = sizeof(msgsi->msgids[0]);
1355 		break;
1356 #else
1357 		return (EOPNOTSUPP);
1358 #endif
1359 	case KERN_SYSVIPC_SEM_INFO:
1360 #ifdef SYSVSEM
1361 		infosize = sizeof(semsi->seminfo);
1362 		nds = seminfo.semmni;
1363 		dssize = sizeof(semsi->semids[0]);
1364 		break;
1365 #else
1366 		return (EOPNOTSUPP);
1367 #endif
1368 	case KERN_SYSVIPC_SHM_INFO:
1369 #ifdef SYSVSHM
1370 		infosize = sizeof(shmsi->shminfo);
1371 		nds = shminfo.shmmni;
1372 		dssize = sizeof(shmsi->shmids[0]);
1373 		break;
1374 #else
1375 		return (EOPNOTSUPP);
1376 #endif
1377 	default:
1378 		return (EINVAL);
1379 	}
1380 	tsize = infosize + (nds * dssize);
1381 
1382 	/* Return just the total size required. */
1383 	if (where == NULL) {
1384 		*sizep = tsize;
1385 		return (0);
1386 	}
1387 
1388 	/* Not enough room for even the info struct. */
1389 	if (buflen < infosize) {
1390 		*sizep = 0;
1391 		return (ENOMEM);
1392 	}
1393 	buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
1394 	bzero(buf, min(tsize, buflen));
1395 
1396 	switch (*name) {
1397 #ifdef SYSVMSG
1398 	case KERN_SYSVIPC_MSG_INFO:
1399 		msgsi = (struct msg_sysctl_info *)buf;
1400 		msgsi->msginfo = msginfo;
1401 		break;
1402 #endif
1403 #ifdef SYSVSEM
1404 	case KERN_SYSVIPC_SEM_INFO:
1405 		semsi = (struct sem_sysctl_info *)buf;
1406 		semsi->seminfo = seminfo;
1407 		break;
1408 #endif
1409 #ifdef SYSVSHM
1410 	case KERN_SYSVIPC_SHM_INFO:
1411 		shmsi = (struct shm_sysctl_info *)buf;
1412 		shmsi->shminfo = shminfo;
1413 		break;
1414 #endif
1415 	}
1416 	buflen -= infosize;
1417 
1418 	ret = 0;
1419 	if (buflen > 0) {
1420 		/* Fill in the IPC data structures.  */
1421 		for (i = 0; i < nds; i++) {
1422 			if (buflen < dssize) {
1423 				ret = ENOMEM;
1424 				break;
1425 			}
1426 			switch (*name) {
1427 #ifdef SYSVMSG
1428 			case KERN_SYSVIPC_MSG_INFO:
1429 				bcopy(&msqids[i], &msgsi->msgids[i], dssize);
1430 				break;
1431 #endif
1432 #ifdef SYSVSEM
1433 			case KERN_SYSVIPC_SEM_INFO:
1434 				if (sema[i] != NULL)
1435 					bcopy(sema[i], &semsi->semids[i],
1436 					    dssize);
1437 				else
1438 					bzero(&semsi->semids[i], dssize);
1439 				break;
1440 #endif
1441 #ifdef SYSVSHM
1442 			case KERN_SYSVIPC_SHM_INFO:
1443 				if (shmsegs[i] != NULL)
1444 					bcopy(shmsegs[i], &shmsi->shmids[i],
1445 					    dssize);
1446 				else
1447 					bzero(&shmsi->shmids[i], dssize);
1448 				break;
1449 #endif
1450 			}
1451 			buflen -= dssize;
1452 		}
1453 	}
1454 	*sizep -= buflen;
1455 	error = copyout(buf, where, *sizep);
1456 	free(buf, M_TEMP);
1457 	/* If copyout succeeded, use return code set earlier. */
1458 	return (error ? error : ret);
1459 }
1460 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
1461 
1462 int
1463 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
1464 {
1465 	extern int intrcnt[], eintrcnt[];
1466 	extern char intrnames[], eintrnames[];
1467 	char *intrname;
1468 	int nintr, i;
1469 
1470 	nintr = (off_t)(eintrcnt - intrcnt);
1471 
1472 	if (name[0] != KERN_INTRCNT_NUM) {
1473 		if (namelen != 2)
1474 			return (ENOTDIR);
1475 		if (name[1] < 0 || name[1] >= nintr)
1476 			return (EINVAL);
1477 		i = name[1];
1478 	}
1479 
1480 	switch (name[0]) {
1481 	case KERN_INTRCNT_NUM:
1482 		return (sysctl_rdint(oldp, oldlenp, NULL, nintr));
1483 		break;
1484 	case KERN_INTRCNT_CNT:
1485 		return (sysctl_rdint(oldp, oldlenp, NULL, intrcnt[i]));
1486 	case KERN_INTRCNT_NAME:
1487 		intrname = intrnames;
1488 		while (i > 0) {
1489 			intrname += strlen(intrname) + 1;
1490 			i--;
1491 			if (intrname > eintrnames)
1492 				return (EINVAL);
1493 		}
1494 		return (sysctl_rdstring(oldp, oldlenp, NULL, intrname));
1495 	default:
1496 		return (EOPNOTSUPP);
1497 	}
1498 }
1499 
1500 int nsensors = 0;
1501 struct sensors_head sensors = SLIST_HEAD_INITIALIZER(&sensors);
1502 
1503 int
1504 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1505     void *newp, size_t newlen)
1506 {
1507 	struct sensor *s = NULL;
1508 	int num;
1509 
1510 	if (namelen != 1)
1511 		return (ENOTDIR);
1512 
1513 	num = name[0];
1514 	if (num >= nsensors)
1515 		return (ENXIO);
1516 
1517 	SLIST_FOREACH(s, &sensors, list)
1518 		if (s->num == num)
1519 			break;
1520 
1521 	return (sysctl_rdstruct(oldp, oldlenp, newp, s, sizeof(struct sensor)));
1522 }
1523 
1524 int
1525 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1526     void *newp, size_t newlen)
1527 {
1528 	int enabled, error;
1529 	struct emul *e;
1530 
1531 	if (name[0] == KERN_EMUL_NUM) {
1532 		if (namelen != 1)
1533 			return (ENOTDIR);
1534 		return (sysctl_rdint(oldp, oldlenp, newp, nemuls));
1535 	}
1536 
1537 	if (namelen != 2)
1538 		return (ENOTDIR);
1539 	if (name[0] > nemuls || name[0] < 0)
1540 		return (EINVAL);
1541 	e = emulsw[name[0] - 1];
1542 
1543 	switch (name[1]) {
1544 	case KERN_EMUL_NAME:
1545 		return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name));
1546 	case KERN_EMUL_ENABLED:
1547 		enabled = (e->e_flags & EMUL_ENABLED);
1548 		error = sysctl_int(oldp, oldlenp, newp, newlen,
1549 		    &enabled);
1550 		e->e_flags = (enabled & EMUL_ENABLED);
1551 		return (error);
1552 	default:
1553 		return (EINVAL);
1554 	}
1555 }
1556