added my responsibility for the `cpm' port
[unix-history] / sys / kern / kern_kinfo.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
600f7f07 33 * from: @(#)kern_kinfo.c 7.17 (Berkeley) 6/26/91
fde1aeb2 34 * $Id: kern_kinfo.c,v 1.8 1993/12/09 09:11:00 davidg Exp $
15637ed4
RG
35 */
36
37#include "param.h"
fde1aeb2 38#include "systm.h"
15637ed4
RG
39#include "proc.h"
40#include "kinfo.h"
41#include "ioctl.h"
42#include "tty.h"
43#include "buf.h"
44#include "file.h"
45
46#include "vm/vm.h"
47
48#include "kinfo_proc.h"
49
50#define snderr(e) { error = (e); goto release;}
51extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode(), kinfo_file();
52struct kinfo_lock kinfo_lock;
53
3c7eb27c
DG
54struct getkerninfo_args {
55 int op;
56 char *where;
57 int *size;
58 int arg;
59};
60
15637ed4 61/* ARGSUSED */
4c45483e 62int
15637ed4
RG
63getkerninfo(p, uap, retval)
64 struct proc *p;
3c7eb27c 65 register struct getkerninfo_args *uap;
15637ed4
RG
66 int *retval;
67{
68
69 int bufsize; /* max size of users buffer */
70 int needed, locked, (*server)(), error = 0;
71
15637ed4
RG
72 switch (ki_type(uap->op)) {
73
74 case KINFO_PROC:
75 server = kinfo_doproc;
76 break;
77
78 case KINFO_RT:
79 server = kinfo_rtable;
80 break;
81
82 case KINFO_VNODE:
83 server = kinfo_vnode;
84 break;
85
86 case KINFO_FILE:
87 server = kinfo_file;
88 break;
89
90 default:
91 error = EINVAL;
92 goto done;
93 }
94 if (uap->where == NULL || uap->size == NULL) {
95 error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
96 goto done;
97 }
74b16b21
DG
98
99 if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize,
100 sizeof (bufsize)))
101 goto done;
102
15637ed4
RG
103 while (kinfo_lock.kl_lock) {
104 kinfo_lock.kl_want++;
fde1aeb2 105 tsleep((caddr_t)&kinfo_lock, PRIBIO+1, "kinflck", 0);
15637ed4
RG
106 kinfo_lock.kl_want--;
107 kinfo_lock.kl_locked++;
108 }
109 kinfo_lock.kl_lock++;
110
111 if (!useracc(uap->where, bufsize, B_WRITE))
112 snderr(EFAULT);
113 if (server != kinfo_vnode) /* XXX */
114 vslock(uap->where, bufsize);
115 locked = bufsize;
116 error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed);
117 if (server != kinfo_vnode) /* XXX */
118 vsunlock(uap->where, locked, B_WRITE);
119 if (error == 0)
120 error = copyout((caddr_t)&bufsize,
121 (caddr_t)uap->size, sizeof (bufsize));
122release:
123 kinfo_lock.kl_lock--;
124 if (kinfo_lock.kl_want)
fde1aeb2 125 wakeup((caddr_t)&kinfo_lock);
15637ed4
RG
126done:
127 if (!error)
128 *retval = needed;
129 return (error);
130}
131
132/*
133 * try over estimating by 5 procs
134 */
135#define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc))
136
4c45483e 137int
15637ed4 138kinfo_doproc(op, where, acopysize, arg, aneeded)
4c45483e 139 int op;
15637ed4 140 char *where;
4c45483e
GW
141 int *acopysize;
142 int arg;
143 int *aneeded;
15637ed4
RG
144{
145 register struct proc *p;
146 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
4c45483e
GW
147 register int needed = 0;
148 int buflen = 0;
15637ed4
RG
149 int doingzomb;
150 struct eproc eproc;
151 int error = 0;
152
153 if (where != NULL)
154 buflen = *acopysize;
155
156 p = allproc;
157 doingzomb = 0;
158again:
159 for (; p != NULL; p = p->p_nxt) {
160 /*
161 * TODO - make more efficient (see notes below).
162 * do by session.
163 */
164 switch (ki_op(op)) {
165
166 case KINFO_PROC_PID:
167 /* could do this with just a lookup */
168 if (p->p_pid != (pid_t)arg)
169 continue;
170 break;
171
172 case KINFO_PROC_PGRP:
173 /* could do this by traversing pgrp */
174 if (p->p_pgrp->pg_id != (pid_t)arg)
175 continue;
176 break;
177
178 case KINFO_PROC_TTY:
179 if ((p->p_flag&SCTTY) == 0 ||
180 p->p_session->s_ttyp == NULL ||
181 p->p_session->s_ttyp->t_dev != (dev_t)arg)
182 continue;
183 break;
184
185 case KINFO_PROC_UID:
186 if (p->p_ucred->cr_uid != (uid_t)arg)
187 continue;
188 break;
189
190 case KINFO_PROC_RUID:
191 if (p->p_cred->p_ruid != (uid_t)arg)
192 continue;
193 break;
194 }
195 if (where != NULL && buflen >= sizeof (struct kinfo_proc)) {
196 fill_eproc(p, &eproc);
197 if (error = copyout((caddr_t)p, &dp->kp_proc,
198 sizeof (struct proc)))
199 return (error);
200 if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
201 sizeof (eproc)))
202 return (error);
203 dp++;
204 buflen -= sizeof (struct kinfo_proc);
205 }
206 needed += sizeof (struct kinfo_proc);
207 }
208 if (doingzomb == 0) {
209 p = zombproc;
210 doingzomb++;
211 goto again;
212 }
213 if (where != NULL)
214 *acopysize = (caddr_t)dp - where;
215 else
216 needed += KINFO_PROCSLOP;
217 *aneeded = needed;
218
219 return (0);
220}
221
222/*
223 * Fill in an eproc structure for the specified process.
224 */
225void
226fill_eproc(p, ep)
227 register struct proc *p;
228 register struct eproc *ep;
229{
230 register struct tty *tp;
231
232 ep->e_paddr = p;
233 ep->e_sess = p->p_pgrp->pg_session;
234 ep->e_pcred = *p->p_cred;
235 ep->e_ucred = *p->p_ucred;
236 ep->e_vm = *p->p_vmspace;
237 if (p->p_pptr)
238 ep->e_ppid = p->p_pptr->p_pid;
239 else
240 ep->e_ppid = 0;
241 ep->e_pgid = p->p_pgrp->pg_id;
242 ep->e_jobc = p->p_pgrp->pg_jobc;
243 if ((p->p_flag&SCTTY) &&
244 (tp = ep->e_sess->s_ttyp)) {
245 ep->e_tdev = tp->t_dev;
246 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
247 ep->e_tsess = tp->t_session;
248 } else
249 ep->e_tdev = NODEV;
250 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
251 if (SESS_LEADER(p))
252 ep->e_flag |= EPROC_SLEADER;
444869a8 253 if (p->p_wmesg) {
15637ed4 254 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
444869a8
AC
255 ep->e_wmesg[WMESGLEN] = 0; /* prevents fault on long wmesg */
256 }
15637ed4
RG
257 ep->e_xsize = ep->e_xrssize = 0;
258 ep->e_xccount = ep->e_xswrss = 0;
259}
260
261/*
262 * Get file structures.
263 */
4c45483e 264int
15637ed4 265kinfo_file(op, where, acopysize, arg, aneeded)
4c45483e 266 int op;
15637ed4 267 register char *where;
4c45483e
GW
268 int *acopysize;
269 int arg;
270 int *aneeded;
15637ed4
RG
271{
272 int buflen, needed, error;
273 struct file *fp;
274 char *start = where;
275
276 if (where == NULL) {
277 /*
278 * overestimate by 10 files
279 */
280 *aneeded = sizeof (filehead) +
281 (nfiles + 10) * sizeof (struct file);
282 return (0);
283 }
284 buflen = *acopysize;
285 needed = 0;
286
287 /*
288 * first copyout filehead
289 */
290 if (buflen > sizeof (filehead)) {
291 if (error = copyout((caddr_t)&filehead, where,
292 sizeof (filehead)))
293 return (error);
294 buflen -= sizeof (filehead);
295 where += sizeof (filehead);
296 }
297 needed += sizeof (filehead);
298
299 /*
300 * followed by an array of file structures
301 */
302 for (fp = filehead; fp != NULL; fp = fp->f_filef) {
303 if (buflen > sizeof (struct file)) {
304 if (error = copyout((caddr_t)fp, where,
305 sizeof (struct file)))
306 return (error);
307 buflen -= sizeof (struct file);
308 where += sizeof (struct file);
309 }
310 needed += sizeof (struct file);
311 }
312 *acopysize = where - start;
313 *aneeded = needed;
314
315 return (0);
316}