minor wording updates
[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 *
9e97623a 7 * @(#)kern_sysctl.c 7.24 (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();
61ece7fc 24extern int kinfo_meter(), kinfo_loadavg(), kinfo_clockrate();
0a4df682
MT
25struct kinfo_lock kinfo_lock;
26
9e97623a
CT
27struct getkerninfo_args {
28 int op;
29 char *where;
30 int *size;
31 int arg;
32};
8b24ca5d
KM
33/* ARGSUSED */
34getkerninfo(p, uap, retval)
35 struct proc *p;
9e97623a 36 register struct getkerninfo_args *uap;
8b24ca5d
KM
37 int *retval;
38{
3789a403
MK
39 int bufsize; /* max size of users buffer */
40 int needed, locked, (*server)(), error = 0;
0a4df682 41
4a24f1b0
MT
42 switch (ki_type(uap->op)) {
43
44 case KINFO_PROC:
0a4df682
MT
45 server = kinfo_doproc;
46 break;
47
48 case KINFO_RT:
49 server = kinfo_rtable;
4a24f1b0
MT
50 break;
51
452737be
MT
52 case KINFO_VNODE:
53 server = kinfo_vnode;
54 break;
55
318784c4
MT
56 case KINFO_FILE:
57 server = kinfo_file;
58 break;
59
15415c71
KM
60 case KINFO_METER:
61 server = kinfo_meter;
62 break;
63
61ece7fc
KM
64 case KINFO_LOADAVG:
65 server = kinfo_loadavg;
66 break;
67
68 case KINFO_CLOCKRATE:
69 server = kinfo_clockrate;
70 break;
71
4a24f1b0 72 default:
2ed8b3ea 73 error = EINVAL;
7acc8d38
MT
74 goto done;
75 }
76 if (uap->where == NULL || uap->size == NULL) {
77 error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
78 goto done;
2ed8b3ea 79 }
aae5c50c
RC
80 if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize,
81 sizeof (bufsize)))
82 goto done;
2ed8b3ea 83 while (kinfo_lock.kl_lock) {
13bbbe63
CT
84 kinfo_lock.kl_want = 1;
85 sleep((caddr_t)&kinfo_lock, PRIBIO+1);
2ed8b3ea 86 kinfo_lock.kl_locked++;
4a24f1b0 87 }
13bbbe63 88 kinfo_lock.kl_lock = 1;
2ed8b3ea 89
7acc8d38 90 if (!useracc(uap->where, bufsize, B_WRITE))
0a4df682 91 snderr(EFAULT);
452737be
MT
92 if (server != kinfo_vnode) /* XXX */
93 vslock(uap->where, bufsize);
7acc8d38
MT
94 locked = bufsize;
95 error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed);
452737be
MT
96 if (server != kinfo_vnode) /* XXX */
97 vsunlock(uap->where, locked, B_WRITE);
7acc8d38
MT
98 if (error == 0)
99 error = copyout((caddr_t)&bufsize,
100 (caddr_t)uap->size, sizeof (bufsize));
0a4df682 101release:
13bbbe63
CT
102 kinfo_lock.kl_lock = 0;
103 if (kinfo_lock.kl_want) {
104 kinfo_lock.kl_want = 0;
105 wakeup((caddr_t)&kinfo_lock);
106 }
7acc8d38 107done:
8b24ca5d
KM
108 if (!error)
109 *retval = needed;
110 return (error);
4a24f1b0
MT
111}
112
113/*
114 * try over estimating by 5 procs
115 */
116#define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc))
117
2ed8b3ea 118kinfo_doproc(op, where, acopysize, arg, aneeded)
13bbbe63 119 int op;
4a24f1b0 120 char *where;
13bbbe63 121 int *acopysize, arg, *aneeded;
4a24f1b0
MT
122{
123 register struct proc *p;
a65b44f0 124 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
4a24f1b0 125 register needed = 0;
13bbbe63 126 int buflen = where != NULL ? *acopysize : 0;
4a24f1b0 127 int doingzomb;
7747bd3b 128 struct eproc eproc;
4a24f1b0
MT
129 int error = 0;
130
80a8e5e6 131 p = (struct proc *)allproc;
4a24f1b0
MT
132 doingzomb = 0;
133again:
134 for (; p != NULL; p = p->p_nxt) {
02ea4076
KM
135 /*
136 * Skip embryonic processes.
137 */
138 if (p->p_stat == SIDL)
139 continue;
4a24f1b0
MT
140 /*
141 * TODO - make more efficient (see notes below).
142 * do by session.
143 */
144 switch (ki_op(op)) {
145
146 case KINFO_PROC_PID:
147 /* could do this with just a lookup */
148 if (p->p_pid != (pid_t)arg)
149 continue;
150 break;
151
152 case KINFO_PROC_PGRP:
153 /* could do this by traversing pgrp */
154 if (p->p_pgrp->pg_id != (pid_t)arg)
155 continue;
156 break;
157
158 case KINFO_PROC_TTY:
159 if ((p->p_flag&SCTTY) == 0 ||
160 p->p_session->s_ttyp == NULL ||
161 p->p_session->s_ttyp->t_dev != (dev_t)arg)
162 continue;
163 break;
164
165 case KINFO_PROC_UID:
3789a403 166 if (p->p_ucred->cr_uid != (uid_t)arg)
4a24f1b0
MT
167 continue;
168 break;
169
170 case KINFO_PROC_RUID:
3789a403 171 if (p->p_cred->p_ruid != (uid_t)arg)
4a24f1b0
MT
172 continue;
173 break;
174 }
13bbbe63 175 if (buflen >= sizeof (struct kinfo_proc)) {
32041eb1 176 fill_eproc(p, &eproc);
a65b44f0 177 if (error = copyout((caddr_t)p, &dp->kp_proc,
4a24f1b0
MT
178 sizeof (struct proc)))
179 return (error);
a65b44f0 180 if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
7747bd3b 181 sizeof (eproc)))
4a24f1b0 182 return (error);
a65b44f0 183 dp++;
4a24f1b0
MT
184 buflen -= sizeof (struct kinfo_proc);
185 }
186 needed += sizeof (struct kinfo_proc);
187 }
188 if (doingzomb == 0) {
189 p = zombproc;
190 doingzomb++;
191 goto again;
192 }
193 if (where != NULL)
a65b44f0 194 *acopysize = (caddr_t)dp - where;
0a4df682
MT
195 else
196 needed += KINFO_PROCSLOP;
4a24f1b0
MT
197 *aneeded = needed;
198
199 return (0);
200}
32041eb1
MK
201
202/*
203 * Fill in an eproc structure for the specified process.
204 */
205void
206fill_eproc(p, ep)
207 register struct proc *p;
208 register struct eproc *ep;
209{
210 register struct tty *tp;
211
212 ep->e_paddr = p;
213 ep->e_sess = p->p_pgrp->pg_session;
214 ep->e_pcred = *p->p_cred;
215 ep->e_ucred = *p->p_ucred;
13bbbe63
CT
216 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
217 ep->e_vm.vm_rssize = 0;
218 ep->e_vm.vm_tsize = 0;
219 ep->e_vm.vm_dsize = 0;
220 ep->e_vm.vm_ssize = 0;
221#ifndef sparc
222 /* ep->e_vm.vm_pmap = XXX; */
223#endif
224 } else {
225 register struct vmspace *vm = p->p_vmspace;
226
227 ep->e_vm.vm_rssize = vm->vm_rssize;
228 ep->e_vm.vm_tsize = vm->vm_tsize;
229 ep->e_vm.vm_dsize = vm->vm_dsize;
230 ep->e_vm.vm_ssize = vm->vm_ssize;
231#ifndef sparc
232 ep->e_vm.vm_pmap = vm->vm_pmap;
233#endif
234 }
31c481fa
MK
235 if (p->p_pptr)
236 ep->e_ppid = p->p_pptr->p_pid;
237 else
238 ep->e_ppid = 0;
32041eb1
MK
239 ep->e_pgid = p->p_pgrp->pg_id;
240 ep->e_jobc = p->p_pgrp->pg_jobc;
241 if ((p->p_flag&SCTTY) &&
242 (tp = ep->e_sess->s_ttyp)) {
243 ep->e_tdev = tp->t_dev;
51d82109 244 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
32041eb1
MK
245 ep->e_tsess = tp->t_session;
246 } else
247 ep->e_tdev = NODEV;
248 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
249 if (SESS_LEADER(p))
250 ep->e_flag |= EPROC_SLEADER;
251 if (p->p_wmesg)
252 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
253 ep->e_xsize = ep->e_xrssize = 0;
254 ep->e_xccount = ep->e_xswrss = 0;
255}
318784c4
MT
256
257/*
258 * Get file structures.
259 */
260kinfo_file(op, where, acopysize, arg, aneeded)
13bbbe63 261 int op;
318784c4 262 register char *where;
13bbbe63 263 int *acopysize, arg, *aneeded;
318784c4
MT
264{
265 int buflen, needed, error;
266 struct file *fp;
267 char *start = where;
268
269 if (where == NULL) {
270 /*
271 * overestimate by 10 files
272 */
273 *aneeded = sizeof (filehead) +
274 (nfiles + 10) * sizeof (struct file);
275 return (0);
276 }
277 buflen = *acopysize;
278 needed = 0;
279
280 /*
281 * first copyout filehead
282 */
283 if (buflen > sizeof (filehead)) {
284 if (error = copyout((caddr_t)&filehead, where,
285 sizeof (filehead)))
286 return (error);
287 buflen -= sizeof (filehead);
288 where += sizeof (filehead);
289 }
290 needed += sizeof (filehead);
291
292 /*
293 * followed by an array of file structures
294 */
295 for (fp = filehead; fp != NULL; fp = fp->f_filef) {
296 if (buflen > sizeof (struct file)) {
297 if (error = copyout((caddr_t)fp, where,
298 sizeof (struct file)))
299 return (error);
300 buflen -= sizeof (struct file);
301 where += sizeof (struct file);
302 }
303 needed += sizeof (struct file);
304 }
305 *acopysize = where - start;
306 *aneeded = needed;
307
308 return (0);
309}