kern_sysctl.c revision 1.31 1 /* $NetBSD: kern_sysctl.c,v 1.31 1998/02/05 07:59:56 mrg Exp $ */
2
3 /*-
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Mike Karels at Berkeley Software Design, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
39 */
40
41 /*
42 * sysctl system call.
43 */
44
45 #include "opt_insecure.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/malloc.h>
51 #include <sys/proc.h>
52 #include <sys/file.h>
53 #include <sys/vnode.h>
54 #include <sys/unistd.h>
55 #include <sys/buf.h>
56 #include <sys/ioctl.h>
57 #include <sys/tty.h>
58 #include <sys/disklabel.h>
59 #include <sys/device.h>
60 #include <vm/vm.h>
61 #include <sys/sysctl.h>
62 #include <sys/msgbuf.h>
63
64 #if defined(UVM)
65 #include <uvm/uvm_extern.h>
66 #endif
67
68 #include <sys/mount.h>
69 #include <sys/syscallargs.h>
70
71 #if defined(UVM)
72 #include <uvm/uvm_extern.h>
73 #endif
74
75 /*
76 * Locking and stats
77 */
78 static struct sysctl_lock {
79 int sl_lock;
80 int sl_want;
81 int sl_locked;
82 } memlock;
83
84 int
85 sys___sysctl(p, v, retval)
86 struct proc *p;
87 void *v;
88 register_t *retval;
89 {
90 register struct sys___sysctl_args /* {
91 syscallarg(int *) name;
92 syscallarg(u_int) namelen;
93 syscallarg(void *) old;
94 syscallarg(size_t *) oldlenp;
95 syscallarg(void *) new;
96 syscallarg(size_t) newlen;
97 } */ *uap = v;
98 int error, dolock = 1;
99 size_t savelen = 0, oldlen = 0;
100 sysctlfn *fn;
101 int name[CTL_MAXNAME];
102
103 if (SCARG(uap, new) != NULL &&
104 (error = suser(p->p_ucred, &p->p_acflag)))
105 return (error);
106 /*
107 * all top-level sysctl names are non-terminal
108 */
109 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
110 return (EINVAL);
111 error = copyin(SCARG(uap, name), &name,
112 SCARG(uap, namelen) * sizeof(int));
113 if (error)
114 return (error);
115
116 switch (name[0]) {
117 case CTL_KERN:
118 fn = kern_sysctl;
119 if (name[2] != KERN_VNODE) /* XXX */
120 dolock = 0;
121 break;
122 case CTL_HW:
123 fn = hw_sysctl;
124 break;
125 case CTL_VM:
126 #if defined(UVM)
127 fn = uvm_sysctl;
128 #else
129 fn = vm_sysctl;
130 #endif
131 break;
132 case CTL_NET:
133 fn = net_sysctl;
134 break;
135 #ifdef notyet
136 case CTL_FS:
137 fn = fs_sysctl;
138 break;
139 #endif
140 case CTL_MACHDEP:
141 fn = cpu_sysctl;
142 break;
143 #ifdef DEBUG
144 case CTL_DEBUG:
145 fn = debug_sysctl;
146 break;
147 #endif
148 #ifdef DDB
149 case CTL_DDB:
150 fn = ddb_sysctl;
151 break;
152 #endif
153 default:
154 return (EOPNOTSUPP);
155 }
156
157 if (SCARG(uap, oldlenp) &&
158 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
159 return (error);
160 if (SCARG(uap, old) != NULL) {
161 #if defined(UVM)
162 if (!uvm_useracc(SCARG(uap, old), oldlen, B_WRITE))
163 #else
164 if (!useracc(SCARG(uap, old), oldlen, B_WRITE))
165 #endif
166 return (EFAULT);
167 while (memlock.sl_lock) {
168 memlock.sl_want = 1;
169 sleep((caddr_t)&memlock, PRIBIO+1);
170 memlock.sl_locked++;
171 }
172 memlock.sl_lock = 1;
173 if (dolock)
174 #if defined(UVM)
175 uvm_vslock(SCARG(uap, old), oldlen);
176 #else
177 vslock(SCARG(uap, old), oldlen);
178 #endif
179 savelen = oldlen;
180 }
181 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old),
182 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
183 if (SCARG(uap, old) != NULL) {
184 if (dolock)
185 #if defined(UVM)
186 uvm_vsunlock(SCARG(uap, old), savelen);
187 #else
188 vsunlock(SCARG(uap, old), savelen);
189 #endif
190 memlock.sl_lock = 0;
191 if (memlock.sl_want) {
192 memlock.sl_want = 0;
193 wakeup((caddr_t)&memlock);
194 }
195 }
196 if (error)
197 return (error);
198 if (SCARG(uap, oldlenp))
199 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
200 return (error);
201 }
202
203 /*
204 * Attributes stored in the kernel.
205 */
206 char hostname[MAXHOSTNAMELEN];
207 int hostnamelen;
208 char domainname[MAXHOSTNAMELEN];
209 int domainnamelen;
210 long hostid;
211 #ifdef INSECURE
212 int securelevel = -1;
213 #else
214 int securelevel = 0;
215 #endif
216
217 /*
218 * kernel related system variables.
219 */
220 int
221 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
222 int *name;
223 u_int namelen;
224 void *oldp;
225 size_t *oldlenp;
226 void *newp;
227 size_t newlen;
228 struct proc *p;
229 {
230 int error, level, inthostid;
231 int old_autonicetime;
232 int old_vnodes;
233 extern char ostype[], osrelease[], version[];
234
235 /* all sysctl names at this level are terminal */
236 if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
237 return (ENOTDIR); /* overloaded */
238
239 switch (name[0]) {
240 case KERN_OSTYPE:
241 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
242 case KERN_OSRELEASE:
243 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
244 case KERN_OSREV:
245 return (sysctl_rdint(oldp, oldlenp, newp, NetBSD));
246 case KERN_VERSION:
247 return (sysctl_rdstring(oldp, oldlenp, newp, version));
248 case KERN_MAXVNODES:
249 old_vnodes = desiredvnodes;
250 error = sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes);
251 if (old_vnodes > desiredvnodes) {
252 desiredvnodes = old_vnodes;
253 return (EINVAL);
254 }
255 return (error);
256 case KERN_MAXPROC:
257 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
258 case KERN_MAXFILES:
259 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
260 case KERN_ARGMAX:
261 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
262 case KERN_SECURELVL:
263 level = securelevel;
264 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
265 newp == NULL)
266 return (error);
267 if (level < securelevel && p->p_pid != 1)
268 return (EPERM);
269 securelevel = level;
270 return (0);
271 case KERN_HOSTNAME:
272 error = sysctl_string(oldp, oldlenp, newp, newlen,
273 hostname, sizeof(hostname));
274 if (newp && !error)
275 hostnamelen = newlen;
276 return (error);
277 case KERN_DOMAINNAME:
278 error = sysctl_string(oldp, oldlenp, newp, newlen,
279 domainname, sizeof(domainname));
280 if (newp && !error)
281 domainnamelen = newlen;
282 return (error);
283 case KERN_HOSTID:
284 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
285 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
286 hostid = inthostid;
287 return (error);
288 case KERN_CLOCKRATE:
289 return (sysctl_clockrate(oldp, oldlenp));
290 case KERN_BOOTTIME:
291 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
292 sizeof(struct timeval)));
293 case KERN_VNODE:
294 return (sysctl_vnode(oldp, oldlenp));
295 case KERN_PROC:
296 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
297 case KERN_FILE:
298 return (sysctl_file(oldp, oldlenp));
299 #ifdef GPROF
300 case KERN_PROF:
301 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
302 newp, newlen));
303 #endif
304 case KERN_POSIX1:
305 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
306 case KERN_NGROUPS:
307 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
308 case KERN_JOB_CONTROL:
309 return (sysctl_rdint(oldp, oldlenp, newp, 1));
310 case KERN_SAVED_IDS:
311 #ifdef _POSIX_SAVED_IDS
312 return (sysctl_rdint(oldp, oldlenp, newp, 1));
313 #else
314 return (sysctl_rdint(oldp, oldlenp, newp, 0));
315 #endif
316 case KERN_MAXPARTITIONS:
317 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
318 case KERN_RAWPARTITION:
319 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
320 #ifdef NTP
321 case KERN_NTPTIME:
322 return (sysctl_ntptime(oldp, oldlenp));
323 #endif
324 case KERN_AUTONICETIME:
325 old_autonicetime = autonicetime;
326 error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime);
327 if (autonicetime < 0)
328 autonicetime = old_autonicetime;
329 return (error);
330 case KERN_AUTONICEVAL:
331 error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval);
332 if (autoniceval < PRIO_MIN)
333 autoniceval = PRIO_MIN;
334 if (autoniceval > PRIO_MAX)
335 autoniceval = PRIO_MAX;
336 return (error);
337 case KERN_RTC_OFFSET:
338 return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset));
339 case KERN_ROOT_DEVICE:
340 return (sysctl_rdstring(oldp, oldlenp, newp,
341 root_device->dv_xname));
342 case KERN_MSGBUFSIZE:
343 /*
344 * deal with cases where the message buffer has
345 * become corrupted.
346 */
347 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
348 msgbufenabled = 0;
349 return (ENXIO);
350 }
351 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
352 default:
353 return (EOPNOTSUPP);
354 }
355 /* NOTREACHED */
356 }
357
358 /*
359 * hardware related system variables.
360 */
361 int
362 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
363 int *name;
364 u_int namelen;
365 void *oldp;
366 size_t *oldlenp;
367 void *newp;
368 size_t newlen;
369 struct proc *p;
370 {
371 extern char machine[], machine_arch[], cpu_model[];
372
373 /* all sysctl names at this level are terminal */
374 if (namelen != 1)
375 return (ENOTDIR); /* overloaded */
376
377 switch (name[0]) {
378 case HW_MACHINE:
379 return (sysctl_rdstring(oldp, oldlenp, newp, machine));
380 case HW_MACHINE_ARCH:
381 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch));
382 case HW_MODEL:
383 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
384 case HW_NCPU:
385 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */
386 case HW_BYTEORDER:
387 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
388 case HW_PHYSMEM:
389 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
390 case HW_USERMEM:
391 #if defined(UVM)
392 return (sysctl_rdint(oldp, oldlenp, newp,
393 ctob(physmem - uvmexp.wired)));
394 #else
395 return (sysctl_rdint(oldp, oldlenp, newp,
396 ctob(physmem - cnt.v_wire_count)));
397 #endif
398 case HW_PAGESIZE:
399 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
400 default:
401 return (EOPNOTSUPP);
402 }
403 /* NOTREACHED */
404 }
405
406 #ifdef DEBUG
407 /*
408 * Debugging related system variables.
409 */
410 struct ctldebug debug0, debug1, debug2, debug3, debug4;
411 struct ctldebug debug5, debug6, debug7, debug8, debug9;
412 struct ctldebug debug10, debug11, debug12, debug13, debug14;
413 struct ctldebug debug15, debug16, debug17, debug18, debug19;
414 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
415 &debug0, &debug1, &debug2, &debug3, &debug4,
416 &debug5, &debug6, &debug7, &debug8, &debug9,
417 &debug10, &debug11, &debug12, &debug13, &debug14,
418 &debug15, &debug16, &debug17, &debug18, &debug19,
419 };
420 int
421 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
422 int *name;
423 u_int namelen;
424 void *oldp;
425 size_t *oldlenp;
426 void *newp;
427 size_t newlen;
428 struct proc *p;
429 {
430 struct ctldebug *cdp;
431
432 /* all sysctl names at this level are name and field */
433 if (namelen != 2)
434 return (ENOTDIR); /* overloaded */
435 cdp = debugvars[name[0]];
436 if (cdp->debugname == 0)
437 return (EOPNOTSUPP);
438 switch (name[1]) {
439 case CTL_DEBUG_NAME:
440 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
441 case CTL_DEBUG_VALUE:
442 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
443 default:
444 return (EOPNOTSUPP);
445 }
446 /* NOTREACHED */
447 }
448 #endif /* DEBUG */
449
450 /*
451 * Validate parameters and get old / set new parameters
452 * for an integer-valued sysctl function.
453 */
454 int
455 sysctl_int(oldp, oldlenp, newp, newlen, valp)
456 void *oldp;
457 size_t *oldlenp;
458 void *newp;
459 size_t newlen;
460 int *valp;
461 {
462 int error = 0;
463
464 if (oldp && *oldlenp < sizeof(int))
465 return (ENOMEM);
466 if (newp && newlen != sizeof(int))
467 return (EINVAL);
468 *oldlenp = sizeof(int);
469 if (oldp)
470 error = copyout(valp, oldp, sizeof(int));
471 if (error == 0 && newp)
472 error = copyin(newp, valp, sizeof(int));
473 return (error);
474 }
475
476 /*
477 * As above, but read-only.
478 */
479 int
480 sysctl_rdint(oldp, oldlenp, newp, val)
481 void *oldp;
482 size_t *oldlenp;
483 void *newp;
484 int val;
485 {
486 int error = 0;
487
488 if (oldp && *oldlenp < sizeof(int))
489 return (ENOMEM);
490 if (newp)
491 return (EPERM);
492 *oldlenp = sizeof(int);
493 if (oldp)
494 error = copyout((caddr_t)&val, oldp, sizeof(int));
495 return (error);
496 }
497
498 /*
499 * Validate parameters and get old / set new parameters
500 * for a string-valued sysctl function.
501 */
502 int
503 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
504 void *oldp;
505 size_t *oldlenp;
506 void *newp;
507 size_t newlen;
508 char *str;
509 int maxlen;
510 {
511 int len, error = 0;
512
513 len = strlen(str) + 1;
514 if (oldp && *oldlenp < len)
515 return (ENOMEM);
516 if (newp && newlen >= maxlen)
517 return (EINVAL);
518 if (oldp) {
519 *oldlenp = len;
520 error = copyout(str, oldp, len);
521 }
522 if (error == 0 && newp) {
523 error = copyin(newp, str, newlen);
524 str[newlen] = 0;
525 }
526 return (error);
527 }
528
529 /*
530 * As above, but read-only.
531 */
532 int
533 sysctl_rdstring(oldp, oldlenp, newp, str)
534 void *oldp;
535 size_t *oldlenp;
536 void *newp;
537 char *str;
538 {
539 int len, error = 0;
540
541 len = strlen(str) + 1;
542 if (oldp && *oldlenp < len)
543 return (ENOMEM);
544 if (newp)
545 return (EPERM);
546 *oldlenp = len;
547 if (oldp)
548 error = copyout(str, oldp, len);
549 return (error);
550 }
551
552 /*
553 * Validate parameters and get old / set new parameters
554 * for a structure oriented sysctl function.
555 */
556 int
557 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
558 void *oldp;
559 size_t *oldlenp;
560 void *newp;
561 size_t newlen;
562 void *sp;
563 int len;
564 {
565 int error = 0;
566
567 if (oldp && *oldlenp < len)
568 return (ENOMEM);
569 if (newp && newlen > len)
570 return (EINVAL);
571 if (oldp) {
572 *oldlenp = len;
573 error = copyout(sp, oldp, len);
574 }
575 if (error == 0 && newp)
576 error = copyin(newp, sp, len);
577 return (error);
578 }
579
580 /*
581 * Validate parameters and get old parameters
582 * for a structure oriented sysctl function.
583 */
584 int
585 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
586 void *oldp;
587 size_t *oldlenp;
588 void *newp, *sp;
589 int len;
590 {
591 int error = 0;
592
593 if (oldp && *oldlenp < len)
594 return (ENOMEM);
595 if (newp)
596 return (EPERM);
597 *oldlenp = len;
598 if (oldp)
599 error = copyout(sp, oldp, len);
600 return (error);
601 }
602
603 /*
604 * Get file structures.
605 */
606 int
607 sysctl_file(where, sizep)
608 char *where;
609 size_t *sizep;
610 {
611 int buflen, error;
612 struct file *fp;
613 char *start = where;
614
615 buflen = *sizep;
616 if (where == NULL) {
617 /*
618 * overestimate by 10 files
619 */
620 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
621 return (0);
622 }
623
624 /*
625 * first copyout filehead
626 */
627 if (buflen < sizeof(filehead)) {
628 *sizep = 0;
629 return (0);
630 }
631 error = copyout((caddr_t)&filehead, where, sizeof(filehead));
632 if (error)
633 return (error);
634 buflen -= sizeof(filehead);
635 where += sizeof(filehead);
636
637 /*
638 * followed by an array of file structures
639 */
640 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
641 if (buflen < sizeof(struct file)) {
642 *sizep = where - start;
643 return (ENOMEM);
644 }
645 error = copyout((caddr_t)fp, where, sizeof (struct file));
646 if (error)
647 return (error);
648 buflen -= sizeof(struct file);
649 where += sizeof(struct file);
650 }
651 *sizep = where - start;
652 return (0);
653 }
654
655 /*
656 * try over estimating by 5 procs
657 */
658 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
659
660 int
661 sysctl_doproc(name, namelen, where, sizep)
662 int *name;
663 u_int namelen;
664 char *where;
665 size_t *sizep;
666 {
667 register struct proc *p;
668 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
669 register int needed = 0;
670 int buflen = where != NULL ? *sizep : 0;
671 int doingzomb;
672 struct eproc eproc;
673 int error = 0;
674
675 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
676 return (EINVAL);
677 p = allproc.lh_first;
678 doingzomb = 0;
679 again:
680 for (; p != 0; p = p->p_list.le_next) {
681 /*
682 * Skip embryonic processes.
683 */
684 if (p->p_stat == SIDL)
685 continue;
686 /*
687 * TODO - make more efficient (see notes below).
688 * do by session.
689 */
690 switch (name[0]) {
691
692 case KERN_PROC_PID:
693 /* could do this with just a lookup */
694 if (p->p_pid != (pid_t)name[1])
695 continue;
696 break;
697
698 case KERN_PROC_PGRP:
699 /* could do this by traversing pgrp */
700 if (p->p_pgrp->pg_id != (pid_t)name[1])
701 continue;
702 break;
703
704 case KERN_PROC_TTY:
705 if ((p->p_flag & P_CONTROLT) == 0 ||
706 p->p_session->s_ttyp == NULL ||
707 p->p_session->s_ttyp->t_dev != (dev_t)name[1])
708 continue;
709 break;
710
711 case KERN_PROC_UID:
712 if (p->p_ucred->cr_uid != (uid_t)name[1])
713 continue;
714 break;
715
716 case KERN_PROC_RUID:
717 if (p->p_cred->p_ruid != (uid_t)name[1])
718 continue;
719 break;
720 }
721 if (buflen >= sizeof(struct kinfo_proc)) {
722 fill_eproc(p, &eproc);
723 error = copyout((caddr_t)p, &dp->kp_proc,
724 sizeof(struct proc));
725 if (error)
726 return (error);
727 error = copyout((caddr_t)&eproc, &dp->kp_eproc,
728 sizeof(eproc));
729 if (error)
730 return (error);
731 dp++;
732 buflen -= sizeof(struct kinfo_proc);
733 }
734 needed += sizeof(struct kinfo_proc);
735 }
736 if (doingzomb == 0) {
737 p = zombproc.lh_first;
738 doingzomb++;
739 goto again;
740 }
741 if (where != NULL) {
742 *sizep = (caddr_t)dp - where;
743 if (needed > *sizep)
744 return (ENOMEM);
745 } else {
746 needed += KERN_PROCSLOP;
747 *sizep = needed;
748 }
749 return (0);
750 }
751
752 /*
753 * Fill in an eproc structure for the specified process.
754 */
755 void
756 fill_eproc(p, ep)
757 register struct proc *p;
758 register struct eproc *ep;
759 {
760 register struct tty *tp;
761
762 ep->e_paddr = p;
763 ep->e_sess = p->p_pgrp->pg_session;
764 ep->e_pcred = *p->p_cred;
765 ep->e_ucred = *p->p_ucred;
766 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
767 ep->e_vm.vm_rssize = 0;
768 ep->e_vm.vm_tsize = 0;
769 ep->e_vm.vm_dsize = 0;
770 ep->e_vm.vm_ssize = 0;
771 /* ep->e_vm.vm_pmap = XXX; */
772 } else {
773 register struct vmspace *vm = p->p_vmspace;
774
775 ep->e_vm.vm_rssize = vm_resident_count(vm);
776 ep->e_vm.vm_tsize = vm->vm_tsize;
777 ep->e_vm.vm_dsize = vm->vm_dsize;
778 ep->e_vm.vm_ssize = vm->vm_ssize;
779 }
780 if (p->p_pptr)
781 ep->e_ppid = p->p_pptr->p_pid;
782 else
783 ep->e_ppid = 0;
784 ep->e_pgid = p->p_pgrp->pg_id;
785 ep->e_jobc = p->p_pgrp->pg_jobc;
786 if ((p->p_flag & P_CONTROLT) &&
787 (tp = ep->e_sess->s_ttyp)) {
788 ep->e_tdev = tp->t_dev;
789 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
790 ep->e_tsess = tp->t_session;
791 } else
792 ep->e_tdev = NODEV;
793 if (p->p_wmesg)
794 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
795 ep->e_xsize = ep->e_xrssize = 0;
796 ep->e_xccount = ep->e_xswrss = 0;
797 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
798 if (SESS_LEADER(p))
799 ep->e_flag |= EPROC_SLEADER;
800 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
801 }
802
803