merge in vm_stat structure from vm_statistics.h
[unix-history] / usr / src / sys / kern / kern_sysctl.c
CommitLineData
4a24f1b0
MT
1/*
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
4 *
dbf0c423 5 * %sccs.include.redist.c%
4a24f1b0 6 *
318784c4 7 * @(#)kern_sysctl.c 7.17 (Berkeley) %G%
4a24f1b0
MT
8 */
9
9fbbcc07 10#include "param.h"
9fbbcc07 11#include "proc.h"
4a24f1b0 12#include "kinfo.h"
4a24f1b0
MT
13#include "ioctl.h"
14#include "tty.h"
15#include "buf.h"
318784c4 16#include "file.h"
4a24f1b0 17
32041eb1
MK
18#include "vm/vm.h"
19
20#include "kinfo_proc.h"
21
0a4df682 22#define snderr(e) { error = (e); goto release;}
318784c4 23extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode(), kinfo_file();
0a4df682
MT
24struct kinfo_lock kinfo_lock;
25
8b24ca5d
KM
26/* ARGSUSED */
27getkerninfo(p, uap, retval)
28 struct proc *p;
29 register struct args {
4a24f1b0
MT
30 int op;
31 char *where;
32 int *size;
33 int arg;
8b24ca5d
KM
34 } *uap;
35 int *retval;
36{
2ed8b3ea 37
3789a403
MK
38 int bufsize; /* max size of users buffer */
39 int needed, locked, (*server)(), error = 0;
0a4df682 40
3789a403
MK
41 if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize,
42 sizeof (bufsize)))
7acc8d38 43 goto done;
4a24f1b0
MT
44
45 switch (ki_type(uap->op)) {
46
47 case KINFO_PROC:
0a4df682
MT
48 server = kinfo_doproc;
49 break;
50
51 case KINFO_RT:
52 server = kinfo_rtable;
4a24f1b0
MT
53 break;
54
452737be
MT
55 case KINFO_VNODE:
56 server = kinfo_vnode;
57 break;
58
318784c4
MT
59 case KINFO_FILE:
60 server = kinfo_file;
61 break;
62
4a24f1b0 63 default:
2ed8b3ea 64 error = EINVAL;
7acc8d38
MT
65 goto done;
66 }
67 if (uap->where == NULL || uap->size == NULL) {
68 error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
69 goto done;
2ed8b3ea
MT
70 }
71 while (kinfo_lock.kl_lock) {
72 kinfo_lock.kl_want++;
73 sleep(&kinfo_lock, PRIBIO+1);
74 kinfo_lock.kl_want--;
75 kinfo_lock.kl_locked++;
4a24f1b0 76 }
2ed8b3ea
MT
77 kinfo_lock.kl_lock++;
78
7acc8d38 79 if (!useracc(uap->where, bufsize, B_WRITE))
0a4df682 80 snderr(EFAULT);
452737be
MT
81 if (server != kinfo_vnode) /* XXX */
82 vslock(uap->where, bufsize);
7acc8d38
MT
83 locked = bufsize;
84 error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed);
452737be
MT
85 if (server != kinfo_vnode) /* XXX */
86 vsunlock(uap->where, locked, B_WRITE);
7acc8d38
MT
87 if (error == 0)
88 error = copyout((caddr_t)&bufsize,
89 (caddr_t)uap->size, sizeof (bufsize));
0a4df682
MT
90release:
91 kinfo_lock.kl_lock--;
92 if (kinfo_lock.kl_want)
93 wakeup(&kinfo_lock);
7acc8d38 94done:
8b24ca5d
KM
95 if (!error)
96 *retval = needed;
97 return (error);
4a24f1b0
MT
98}
99
100/*
101 * try over estimating by 5 procs
102 */
103#define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc))
104
2ed8b3ea 105kinfo_doproc(op, where, acopysize, arg, aneeded)
4a24f1b0
MT
106 char *where;
107 int *acopysize, *aneeded;
108{
109 register struct proc *p;
a65b44f0 110 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
4a24f1b0
MT
111 register needed = 0;
112 int buflen;
113 int doingzomb;
7747bd3b 114 struct eproc eproc;
4a24f1b0
MT
115 int error = 0;
116
117 if (where != NULL)
118 buflen = *acopysize;
119
120 p = allproc;
121 doingzomb = 0;
122again:
123 for (; p != NULL; p = p->p_nxt) {
124 /*
125 * TODO - make more efficient (see notes below).
126 * do by session.
127 */
128 switch (ki_op(op)) {
129
130 case KINFO_PROC_PID:
131 /* could do this with just a lookup */
132 if (p->p_pid != (pid_t)arg)
133 continue;
134 break;
135
136 case KINFO_PROC_PGRP:
137 /* could do this by traversing pgrp */
138 if (p->p_pgrp->pg_id != (pid_t)arg)
139 continue;
140 break;
141
142 case KINFO_PROC_TTY:
143 if ((p->p_flag&SCTTY) == 0 ||
144 p->p_session->s_ttyp == NULL ||
145 p->p_session->s_ttyp->t_dev != (dev_t)arg)
146 continue;
147 break;
148
149 case KINFO_PROC_UID:
3789a403 150 if (p->p_ucred->cr_uid != (uid_t)arg)
4a24f1b0
MT
151 continue;
152 break;
153
154 case KINFO_PROC_RUID:
3789a403 155 if (p->p_cred->p_ruid != (uid_t)arg)
4a24f1b0
MT
156 continue;
157 break;
158 }
159 if (where != NULL && buflen >= sizeof (struct kinfo_proc)) {
32041eb1 160 fill_eproc(p, &eproc);
a65b44f0 161 if (error = copyout((caddr_t)p, &dp->kp_proc,
4a24f1b0
MT
162 sizeof (struct proc)))
163 return (error);
a65b44f0 164 if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
7747bd3b 165 sizeof (eproc)))
4a24f1b0 166 return (error);
a65b44f0 167 dp++;
4a24f1b0
MT
168 buflen -= sizeof (struct kinfo_proc);
169 }
170 needed += sizeof (struct kinfo_proc);
171 }
172 if (doingzomb == 0) {
173 p = zombproc;
174 doingzomb++;
175 goto again;
176 }
177 if (where != NULL)
a65b44f0 178 *acopysize = (caddr_t)dp - where;
0a4df682
MT
179 else
180 needed += KINFO_PROCSLOP;
4a24f1b0
MT
181 *aneeded = needed;
182
183 return (0);
184}
32041eb1
MK
185
186/*
187 * Fill in an eproc structure for the specified process.
188 */
189void
190fill_eproc(p, ep)
191 register struct proc *p;
192 register struct eproc *ep;
193{
194 register struct tty *tp;
195
196 ep->e_paddr = p;
197 ep->e_sess = p->p_pgrp->pg_session;
198 ep->e_pcred = *p->p_cred;
199 ep->e_ucred = *p->p_ucred;
200 ep->e_vm = *p->p_vmspace;
31c481fa
MK
201 if (p->p_pptr)
202 ep->e_ppid = p->p_pptr->p_pid;
203 else
204 ep->e_ppid = 0;
32041eb1
MK
205 ep->e_pgid = p->p_pgrp->pg_id;
206 ep->e_jobc = p->p_pgrp->pg_jobc;
207 if ((p->p_flag&SCTTY) &&
208 (tp = ep->e_sess->s_ttyp)) {
209 ep->e_tdev = tp->t_dev;
51d82109 210 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
32041eb1
MK
211 ep->e_tsess = tp->t_session;
212 } else
213 ep->e_tdev = NODEV;
214 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
215 if (SESS_LEADER(p))
216 ep->e_flag |= EPROC_SLEADER;
217 if (p->p_wmesg)
218 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
219 ep->e_xsize = ep->e_xrssize = 0;
220 ep->e_xccount = ep->e_xswrss = 0;
221}
318784c4
MT
222
223/*
224 * Get file structures.
225 */
226kinfo_file(op, where, acopysize, arg, aneeded)
227 register char *where;
228 int *acopysize, *aneeded;
229{
230 int buflen, needed, error;
231 struct file *fp;
232 char *start = where;
233
234 if (where == NULL) {
235 /*
236 * overestimate by 10 files
237 */
238 *aneeded = sizeof (filehead) +
239 (nfiles + 10) * sizeof (struct file);
240 return (0);
241 }
242 buflen = *acopysize;
243 needed = 0;
244
245 /*
246 * first copyout filehead
247 */
248 if (buflen > sizeof (filehead)) {
249 if (error = copyout((caddr_t)&filehead, where,
250 sizeof (filehead)))
251 return (error);
252 buflen -= sizeof (filehead);
253 where += sizeof (filehead);
254 }
255 needed += sizeof (filehead);
256
257 /*
258 * followed by an array of file structures
259 */
260 for (fp = filehead; fp != NULL; fp = fp->f_filef) {
261 if (buflen > sizeof (struct file)) {
262 if (error = copyout((caddr_t)fp, where,
263 sizeof (struct file)))
264 return (error);
265 buflen -= sizeof (struct file);
266 where += sizeof (struct file);
267 }
268 needed += sizeof (struct file);
269 }
270 *acopysize = where - start;
271 *aneeded = needed;
272
273 return (0);
274}