kern_sysctl.c revision 1.21 1 /* $NetBSD: kern_sysctl.c,v 1.21 1997/01/15 01:37:52 perry 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 <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #include <sys/proc.h>
50 #include <sys/file.h>
51 #include <sys/vnode.h>
52 #include <sys/unistd.h>
53 #include <sys/buf.h>
54 #include <sys/ioctl.h>
55 #include <sys/tty.h>
56 #include <sys/disklabel.h>
57 #include <vm/vm.h>
58 #include <sys/sysctl.h>
59
60 #include <sys/mount.h>
61 #include <sys/syscallargs.h>
62
63 /*
64 * Locking and stats
65 */
66 static struct sysctl_lock {
67 int sl_lock;
68 int sl_want;
69 int sl_locked;
70 } memlock;
71
72 int
73 sys___sysctl(p, v, retval)
74 struct proc *p;
75 void *v;
76 register_t *retval;
77 {
78 register struct sys___sysctl_args /* {
79 syscallarg(int *) name;
80 syscallarg(u_int) namelen;
81 syscallarg(void *) old;
82 syscallarg(size_t *) oldlenp;
83 syscallarg(void *) new;
84 syscallarg(size_t) newlen;
85 } */ *uap = v;
86 int error, dolock = 1;
87 size_t savelen = 0, oldlen = 0;
88 sysctlfn *fn;
89 int name[CTL_MAXNAME];
90
91 if (SCARG(uap, new) != NULL &&
92 (error = suser(p->p_ucred, &p->p_acflag)))
93 return (error);
94 /*
95 * all top-level sysctl names are non-terminal
96 */
97 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
98 return (EINVAL);
99 error = copyin(SCARG(uap, name), &name,
100 SCARG(uap, namelen) * sizeof(int));
101 if (error)
102 return (error);
103
104 switch (name[0]) {
105 case CTL_KERN:
106 fn = kern_sysctl;
107 if (name[2] != KERN_VNODE) /* XXX */
108 dolock = 0;
109 break;
110 case CTL_HW:
111 fn = hw_sysctl;
112 break;
113 case CTL_VM:
114 fn = vm_sysctl;
115 break;
116 case CTL_NET:
117 fn = net_sysctl;
118 break;
119 #ifdef notyet
120 case CTL_FS:
121 fn = fs_sysctl;
122 break;
123 #endif
124 case CTL_MACHDEP:
125 fn = cpu_sysctl;
126 break;
127 #ifdef DEBUG
128 case CTL_DEBUG:
129 fn = debug_sysctl;
130 break;
131 #endif
132 #ifdef DDB
133 case CTL_DDB:
134 fn = ddb_sysctl;
135 break;
136 #endif
137 default:
138 return (EOPNOTSUPP);
139 }
140
141 if (SCARG(uap, oldlenp) &&
142 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
143 return (error);
144 if (SCARG(uap, old) != NULL) {
145 if (!useracc(SCARG(uap, old), oldlen, B_WRITE))
146 return (EFAULT);
147 while (memlock.sl_lock) {
148 memlock.sl_want = 1;
149 sleep((caddr_t)&memlock, PRIBIO+1);
150 memlock.sl_locked++;
151 }
152 memlock.sl_lock = 1;
153 if (dolock)
154 vslock(SCARG(uap, old), oldlen);
155 savelen = oldlen;
156 }
157 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old),
158 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
159 if (SCARG(uap, old) != NULL) {
160 if (dolock)
161 vsunlock(SCARG(uap, old), savelen);
162 memlock.sl_lock = 0;
163 if (memlock.sl_want) {
164 memlock.sl_want = 0;
165 wakeup((caddr_t)&memlock);
166 }
167 }
168 if (error)
169 return (error);
170 if (SCARG(uap, oldlenp))
171 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
172 return (error);
173 }
174
175 /*
176 * Attributes stored in the kernel.
177 */
178 char hostname[MAXHOSTNAMELEN];
179 int hostnamelen;
180 char domainname[MAXHOSTNAMELEN];
181 int domainnamelen;
182 long hostid;
183 #ifdef INSECURE
184 int securelevel = -1;
185 #else
186 int securelevel = 0;
187 #endif
188
189 /*
190 * kernel related system variables.
191 */
192 int
193 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
194 int *name;
195 u_int namelen;
196 void *oldp;
197 size_t *oldlenp;
198 void *newp;
199 size_t newlen;
200 struct proc *p;
201 {
202 int error, level, inthostid;
203 int old_autonicetime;
204 extern char ostype[], osrelease[], version[];
205
206 /* all sysctl names at this level are terminal */
207 if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
208 return (ENOTDIR); /* overloaded */
209
210 switch (name[0]) {
211 case KERN_OSTYPE:
212 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
213 case KERN_OSRELEASE:
214 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
215 case KERN_OSREV:
216 return (sysctl_rdint(oldp, oldlenp, newp, BSD));
217 case KERN_VERSION:
218 return (sysctl_rdstring(oldp, oldlenp, newp, version));
219 case KERN_MAXVNODES:
220 return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
221 case KERN_MAXPROC:
222 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
223 case KERN_MAXFILES:
224 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
225 case KERN_ARGMAX:
226 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
227 case KERN_SECURELVL:
228 level = securelevel;
229 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
230 newp == NULL)
231 return (error);
232 if (level < securelevel && p->p_pid != 1)
233 return (EPERM);
234 securelevel = level;
235 return (0);
236 case KERN_HOSTNAME:
237 error = sysctl_string(oldp, oldlenp, newp, newlen,
238 hostname, sizeof(hostname));
239 if (newp && !error)
240 hostnamelen = newlen;
241 return (error);
242 case KERN_DOMAINNAME:
243 error = sysctl_string(oldp, oldlenp, newp, newlen,
244 domainname, sizeof(domainname));
245 if (newp && !error)
246 domainnamelen = newlen;
247 return (error);
248 case KERN_HOSTID:
249 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
250 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
251 hostid = inthostid;
252 return (error);
253 case KERN_CLOCKRATE:
254 return (sysctl_clockrate(oldp, oldlenp));
255 case KERN_BOOTTIME:
256 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
257 sizeof(struct timeval)));
258 case KERN_VNODE:
259 return (sysctl_vnode(oldp, oldlenp));
260 case KERN_PROC:
261 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
262 case KERN_FILE:
263 return (sysctl_file(oldp, oldlenp));
264 #ifdef GPROF
265 case KERN_PROF:
266 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
267 newp, newlen));
268 #endif
269 case KERN_POSIX1:
270 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
271 case KERN_NGROUPS:
272 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
273 case KERN_JOB_CONTROL:
274 return (sysctl_rdint(oldp, oldlenp, newp, 1));
275 case KERN_SAVED_IDS:
276 #ifdef _POSIX_SAVED_IDS
277 return (sysctl_rdint(oldp, oldlenp, newp, 1));
278 #else
279 return (sysctl_rdint(oldp, oldlenp, newp, 0));
280 #endif
281 case KERN_MAXPARTITIONS:
282 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
283 case KERN_RAWPARTITION:
284 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
285 #ifdef NTP
286 case KERN_NTPTIME:
287 return (sysctl_ntptime(oldp, oldlenp));
288 #endif
289 case KERN_AUTONICETIME:
290 old_autonicetime = autonicetime;
291 error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime);
292 if (autonicetime < 0)
293 autonicetime = old_autonicetime;
294 return (error);
295 case KERN_AUTONICEVAL:
296 error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval);
297 if (autoniceval < PRIO_MIN)
298 autoniceval = PRIO_MIN;
299 if (autoniceval > PRIO_MAX)
300 autoniceval = PRIO_MAX;
301 return (error);
302 case KERN_RTC_OFFSET:
303 return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset));
304 default:
305 return (EOPNOTSUPP);
306 }
307 /* NOTREACHED */
308 }
309
310 /*
311 * hardware related system variables.
312 */
313 int
314 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
315 int *name;
316 u_int namelen;
317 void *oldp;
318 size_t *oldlenp;
319 void *newp;
320 size_t newlen;
321 struct proc *p;
322 {
323 extern char machine[], cpu_model[];
324
325 /* all sysctl names at this level are terminal */
326 if (namelen != 1)
327 return (ENOTDIR); /* overloaded */
328
329 switch (name[0]) {
330 case HW_MACHINE:
331 return (sysctl_rdstring(oldp, oldlenp, newp, machine));
332 case HW_MODEL:
333 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
334 case HW_NCPU:
335 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */
336 case HW_BYTEORDER:
337 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
338 case HW_PHYSMEM:
339 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
340 case HW_USERMEM:
341 return (sysctl_rdint(oldp, oldlenp, newp,
342 ctob(physmem - cnt.v_wire_count)));
343 case HW_PAGESIZE:
344 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
345 default:
346 return (EOPNOTSUPP);
347 }
348 /* NOTREACHED */
349 }
350
351 #ifdef DEBUG
352 /*
353 * Debugging related system variables.
354 */
355 struct ctldebug debug0, debug1, debug2, debug3, debug4;
356 struct ctldebug debug5, debug6, debug7, debug8, debug9;
357 struct ctldebug debug10, debug11, debug12, debug13, debug14;
358 struct ctldebug debug15, debug16, debug17, debug18, debug19;
359 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
360 &debug0, &debug1, &debug2, &debug3, &debug4,
361 &debug5, &debug6, &debug7, &debug8, &debug9,
362 &debug10, &debug11, &debug12, &debug13, &debug14,
363 &debug15, &debug16, &debug17, &debug18, &debug19,
364 };
365 int
366 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
367 int *name;
368 u_int namelen;
369 void *oldp;
370 size_t *oldlenp;
371 void *newp;
372 size_t newlen;
373 struct proc *p;
374 {
375 struct ctldebug *cdp;
376
377 /* all sysctl names at this level are name and field */
378 if (namelen != 2)
379 return (ENOTDIR); /* overloaded */
380 cdp = debugvars[name[0]];
381 if (cdp->debugname == 0)
382 return (EOPNOTSUPP);
383 switch (name[1]) {
384 case CTL_DEBUG_NAME:
385 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
386 case CTL_DEBUG_VALUE:
387 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
388 default:
389 return (EOPNOTSUPP);
390 }
391 /* NOTREACHED */
392 }
393 #endif /* DEBUG */
394
395 /*
396 * Validate parameters and get old / set new parameters
397 * for an integer-valued sysctl function.
398 */
399 int
400 sysctl_int(oldp, oldlenp, newp, newlen, valp)
401 void *oldp;
402 size_t *oldlenp;
403 void *newp;
404 size_t newlen;
405 int *valp;
406 {
407 int error = 0;
408
409 if (oldp && *oldlenp < sizeof(int))
410 return (ENOMEM);
411 if (newp && newlen != sizeof(int))
412 return (EINVAL);
413 *oldlenp = sizeof(int);
414 if (oldp)
415 error = copyout(valp, oldp, sizeof(int));
416 if (error == 0 && newp)
417 error = copyin(newp, valp, sizeof(int));
418 return (error);
419 }
420
421 /*
422 * As above, but read-only.
423 */
424 int
425 sysctl_rdint(oldp, oldlenp, newp, val)
426 void *oldp;
427 size_t *oldlenp;
428 void *newp;
429 int val;
430 {
431 int error = 0;
432
433 if (oldp && *oldlenp < sizeof(int))
434 return (ENOMEM);
435 if (newp)
436 return (EPERM);
437 *oldlenp = sizeof(int);
438 if (oldp)
439 error = copyout((caddr_t)&val, oldp, sizeof(int));
440 return (error);
441 }
442
443 /*
444 * Validate parameters and get old / set new parameters
445 * for a string-valued sysctl function.
446 */
447 int
448 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
449 void *oldp;
450 size_t *oldlenp;
451 void *newp;
452 size_t newlen;
453 char *str;
454 int maxlen;
455 {
456 int len, error = 0;
457
458 len = strlen(str) + 1;
459 if (oldp && *oldlenp < len)
460 return (ENOMEM);
461 if (newp && newlen >= maxlen)
462 return (EINVAL);
463 if (oldp) {
464 *oldlenp = len;
465 error = copyout(str, oldp, len);
466 }
467 if (error == 0 && newp) {
468 error = copyin(newp, str, newlen);
469 str[newlen] = 0;
470 }
471 return (error);
472 }
473
474 /*
475 * As above, but read-only.
476 */
477 int
478 sysctl_rdstring(oldp, oldlenp, newp, str)
479 void *oldp;
480 size_t *oldlenp;
481 void *newp;
482 char *str;
483 {
484 int len, error = 0;
485
486 len = strlen(str) + 1;
487 if (oldp && *oldlenp < len)
488 return (ENOMEM);
489 if (newp)
490 return (EPERM);
491 *oldlenp = len;
492 if (oldp)
493 error = copyout(str, oldp, len);
494 return (error);
495 }
496
497 /*
498 * Validate parameters and get old / set new parameters
499 * for a structure oriented sysctl function.
500 */
501 int
502 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
503 void *oldp;
504 size_t *oldlenp;
505 void *newp;
506 size_t newlen;
507 void *sp;
508 int len;
509 {
510 int error = 0;
511
512 if (oldp && *oldlenp < len)
513 return (ENOMEM);
514 if (newp && newlen > len)
515 return (EINVAL);
516 if (oldp) {
517 *oldlenp = len;
518 error = copyout(sp, oldp, len);
519 }
520 if (error == 0 && newp)
521 error = copyin(newp, sp, len);
522 return (error);
523 }
524
525 /*
526 * Validate parameters and get old parameters
527 * for a structure oriented sysctl function.
528 */
529 int
530 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
531 void *oldp;
532 size_t *oldlenp;
533 void *newp, *sp;
534 int len;
535 {
536 int error = 0;
537
538 if (oldp && *oldlenp < len)
539 return (ENOMEM);
540 if (newp)
541 return (EPERM);
542 *oldlenp = len;
543 if (oldp)
544 error = copyout(sp, oldp, len);
545 return (error);
546 }
547
548 /*
549 * Get file structures.
550 */
551 int
552 sysctl_file(where, sizep)
553 char *where;
554 size_t *sizep;
555 {
556 int buflen, error;
557 struct file *fp;
558 char *start = where;
559
560 buflen = *sizep;
561 if (where == NULL) {
562 /*
563 * overestimate by 10 files
564 */
565 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
566 return (0);
567 }
568
569 /*
570 * first copyout filehead
571 */
572 if (buflen < sizeof(filehead)) {
573 *sizep = 0;
574 return (0);
575 }
576 error = copyout((caddr_t)&filehead, where, sizeof(filehead));
577 if (error)
578 return (error);
579 buflen -= sizeof(filehead);
580 where += sizeof(filehead);
581
582 /*
583 * followed by an array of file structures
584 */
585 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
586 if (buflen < sizeof(struct file)) {
587 *sizep = where - start;
588 return (ENOMEM);
589 }
590 error = copyout((caddr_t)fp, where, sizeof (struct file));
591 if (error)
592 return (error);
593 buflen -= sizeof(struct file);
594 where += sizeof(struct file);
595 }
596 *sizep = where - start;
597 return (0);
598 }
599
600 /*
601 * try over estimating by 5 procs
602 */
603 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
604
605 int
606 sysctl_doproc(name, namelen, where, sizep)
607 int *name;
608 u_int namelen;
609 char *where;
610 size_t *sizep;
611 {
612 register struct proc *p;
613 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
614 register int needed = 0;
615 int buflen = where != NULL ? *sizep : 0;
616 int doingzomb;
617 struct eproc eproc;
618 int error = 0;
619
620 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
621 return (EINVAL);
622 p = allproc.lh_first;
623 doingzomb = 0;
624 again:
625 for (; p != 0; p = p->p_list.le_next) {
626 /*
627 * Skip embryonic processes.
628 */
629 if (p->p_stat == SIDL)
630 continue;
631 /*
632 * TODO - make more efficient (see notes below).
633 * do by session.
634 */
635 switch (name[0]) {
636
637 case KERN_PROC_PID:
638 /* could do this with just a lookup */
639 if (p->p_pid != (pid_t)name[1])
640 continue;
641 break;
642
643 case KERN_PROC_PGRP:
644 /* could do this by traversing pgrp */
645 if (p->p_pgrp->pg_id != (pid_t)name[1])
646 continue;
647 break;
648
649 case KERN_PROC_TTY:
650 if ((p->p_flag & P_CONTROLT) == 0 ||
651 p->p_session->s_ttyp == NULL ||
652 p->p_session->s_ttyp->t_dev != (dev_t)name[1])
653 continue;
654 break;
655
656 case KERN_PROC_UID:
657 if (p->p_ucred->cr_uid != (uid_t)name[1])
658 continue;
659 break;
660
661 case KERN_PROC_RUID:
662 if (p->p_cred->p_ruid != (uid_t)name[1])
663 continue;
664 break;
665 }
666 if (buflen >= sizeof(struct kinfo_proc)) {
667 fill_eproc(p, &eproc);
668 error = copyout((caddr_t)p, &dp->kp_proc,
669 sizeof(struct proc));
670 if (error)
671 return (error);
672 error = copyout((caddr_t)&eproc, &dp->kp_eproc,
673 sizeof(eproc));
674 if (error)
675 return (error);
676 dp++;
677 buflen -= sizeof(struct kinfo_proc);
678 }
679 needed += sizeof(struct kinfo_proc);
680 }
681 if (doingzomb == 0) {
682 p = zombproc.lh_first;
683 doingzomb++;
684 goto again;
685 }
686 if (where != NULL) {
687 *sizep = (caddr_t)dp - where;
688 if (needed > *sizep)
689 return (ENOMEM);
690 } else {
691 needed += KERN_PROCSLOP;
692 *sizep = needed;
693 }
694 return (0);
695 }
696
697 /*
698 * Fill in an eproc structure for the specified process.
699 */
700 void
701 fill_eproc(p, ep)
702 register struct proc *p;
703 register struct eproc *ep;
704 {
705 register struct tty *tp;
706
707 ep->e_paddr = p;
708 ep->e_sess = p->p_pgrp->pg_session;
709 ep->e_pcred = *p->p_cred;
710 ep->e_ucred = *p->p_ucred;
711 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
712 ep->e_vm.vm_rssize = 0;
713 ep->e_vm.vm_tsize = 0;
714 ep->e_vm.vm_dsize = 0;
715 ep->e_vm.vm_ssize = 0;
716 /* ep->e_vm.vm_pmap = XXX; */
717 } else {
718 register struct vmspace *vm = p->p_vmspace;
719
720 #ifdef pmap_resident_count
721 ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/
722 #else
723 ep->e_vm.vm_rssize = vm->vm_rssize;
724 #endif
725 ep->e_vm.vm_tsize = vm->vm_tsize;
726 ep->e_vm.vm_dsize = vm->vm_dsize;
727 ep->e_vm.vm_ssize = vm->vm_ssize;
728 ep->e_vm.vm_pmap = vm->vm_pmap;
729 }
730 if (p->p_pptr)
731 ep->e_ppid = p->p_pptr->p_pid;
732 else
733 ep->e_ppid = 0;
734 ep->e_pgid = p->p_pgrp->pg_id;
735 ep->e_jobc = p->p_pgrp->pg_jobc;
736 if ((p->p_flag & P_CONTROLT) &&
737 (tp = ep->e_sess->s_ttyp)) {
738 ep->e_tdev = tp->t_dev;
739 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
740 ep->e_tsess = tp->t_session;
741 } else
742 ep->e_tdev = NODEV;
743 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
744 if (SESS_LEADER(p))
745 ep->e_flag |= EPROC_SLEADER;
746 if (p->p_wmesg)
747 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
748 ep->e_xsize = ep->e_xrssize = 0;
749 ep->e_xccount = ep->e_xswrss = 0;
750 }
751
752