|
|
1.1 root 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: *
1.1.1.2 ! root 33: * from: @(#)kern_kinfo.c 7.17 (Berkeley) 6/26/91
! 34: * kern_kinfo.c,v 1.6.2.4 1993/08/06 08:11:23 cgd Exp
1.1 root 35: */
36:
37: #include "param.h"
1.1.1.2 ! root 38: #include "systm.h"
1.1 root 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;}
51: extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode(), kinfo_file();
52: struct kinfo_lock kinfo_lock;
53:
54: /* ARGSUSED */
1.1.1.2 ! root 55: struct getkerninfo_args {
! 56: int op;
! 57: char *where;
! 58: int *size;
! 59: int arg;
! 60: };
! 61:
! 62: int
1.1 root 63: getkerninfo(p, uap, retval)
64: struct proc *p;
1.1.1.2 ! root 65: register struct getkerninfo_args *uap;
1.1 root 66: int *retval;
67: {
68:
69: int bufsize; /* max size of users buffer */
70: int needed, locked, (*server)(), error = 0;
71:
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: }
1.1.1.2 ! root 94:
1.1 root 95: if (uap->where == NULL || uap->size == NULL) {
96: error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
97: goto done;
98: }
1.1.1.2 ! root 99:
! 100: if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize,
! 101: sizeof (bufsize)))
! 102: goto done;
! 103:
1.1 root 104: while (kinfo_lock.kl_lock) {
105: kinfo_lock.kl_want++;
1.1.1.2 ! root 106: tsleep((caddr_t)&kinfo_lock, PRIBIO+1, "ki_lock", 0);
1.1 root 107: kinfo_lock.kl_want--;
108: kinfo_lock.kl_locked++;
109: }
110: kinfo_lock.kl_lock++;
111:
112: if (!useracc(uap->where, bufsize, B_WRITE))
113: snderr(EFAULT);
114: if (server != kinfo_vnode) /* XXX */
115: vslock(uap->where, bufsize);
116: locked = bufsize;
117: error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed);
118: if (server != kinfo_vnode) /* XXX */
119: vsunlock(uap->where, locked, B_WRITE);
120: if (error == 0)
121: error = copyout((caddr_t)&bufsize,
122: (caddr_t)uap->size, sizeof (bufsize));
123: release:
124: kinfo_lock.kl_lock--;
125: if (kinfo_lock.kl_want)
1.1.1.2 ! root 126: wakeup((caddr_t)&kinfo_lock);
1.1 root 127: done:
128: if (!error)
129: *retval = needed;
130: return (error);
131: }
132:
133: /*
134: * try over estimating by 5 procs
135: */
136: #define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc))
137:
1.1.1.2 ! root 138: int
1.1 root 139: kinfo_doproc(op, where, acopysize, arg, aneeded)
1.1.1.2 ! root 140: int op;
1.1 root 141: char *where;
142: int *acopysize, *aneeded;
1.1.1.2 ! root 143: int arg;
1.1 root 144: {
145: register struct proc *p;
146: register struct kinfo_proc *dp = (struct kinfo_proc *)where;
147: register needed = 0;
148: int buflen;
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;
158: again:
159: for (; p != NULL; p = p->p_nxt) {
1.1.1.2 ! root 160: /*
! 161: * If process not yet fully-formed, skip it.
! 162: */
! 163: if (p->p_stat == SIDL)
! 164: continue;
1.1 root 165: /*
166: * TODO - make more efficient (see notes below).
167: * do by session.
168: */
169: switch (ki_op(op)) {
170:
171: case KINFO_PROC_PID:
172: /* could do this with just a lookup */
173: if (p->p_pid != (pid_t)arg)
174: continue;
175: break;
176:
177: case KINFO_PROC_PGRP:
178: /* could do this by traversing pgrp */
179: if (p->p_pgrp->pg_id != (pid_t)arg)
180: continue;
181: break;
182:
183: case KINFO_PROC_TTY:
184: if ((p->p_flag&SCTTY) == 0 ||
185: p->p_session->s_ttyp == NULL ||
186: p->p_session->s_ttyp->t_dev != (dev_t)arg)
187: continue;
188: break;
189:
190: case KINFO_PROC_UID:
191: if (p->p_ucred->cr_uid != (uid_t)arg)
192: continue;
193: break;
194:
195: case KINFO_PROC_RUID:
196: if (p->p_cred->p_ruid != (uid_t)arg)
197: continue;
198: break;
199: }
200: if (where != NULL && buflen >= sizeof (struct kinfo_proc)) {
201: fill_eproc(p, &eproc);
202: if (error = copyout((caddr_t)p, &dp->kp_proc,
203: sizeof (struct proc)))
204: return (error);
205: if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
206: sizeof (eproc)))
207: return (error);
208: dp++;
209: buflen -= sizeof (struct kinfo_proc);
210: }
211: needed += sizeof (struct kinfo_proc);
212: }
213: if (doingzomb == 0) {
214: p = zombproc;
215: doingzomb++;
216: goto again;
217: }
218: if (where != NULL)
219: *acopysize = (caddr_t)dp - where;
220: else
221: needed += KINFO_PROCSLOP;
222: *aneeded = needed;
223:
224: return (0);
225: }
226:
227: /*
228: * Fill in an eproc structure for the specified process.
229: */
230: void
231: fill_eproc(p, ep)
232: register struct proc *p;
233: register struct eproc *ep;
234: {
235: register struct tty *tp;
236:
237: ep->e_paddr = p;
238: ep->e_sess = p->p_pgrp->pg_session;
239: ep->e_pcred = *p->p_cred;
240: ep->e_ucred = *p->p_ucred;
1.1.1.2 ! root 241: if (p->p_stat == SIDL || p->p_stat == SZOMB)
! 242: bzero(&ep->e_vm, sizeof(ep->e_vm));
! 243: else
! 244: ep->e_vm = *p->p_vmspace;
1.1 root 245: if (p->p_pptr)
246: ep->e_ppid = p->p_pptr->p_pid;
247: else
248: ep->e_ppid = 0;
249: ep->e_pgid = p->p_pgrp->pg_id;
250: ep->e_jobc = p->p_pgrp->pg_jobc;
251: if ((p->p_flag&SCTTY) &&
252: (tp = ep->e_sess->s_ttyp)) {
253: ep->e_tdev = tp->t_dev;
254: ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
255: ep->e_tsess = tp->t_session;
256: } else
257: ep->e_tdev = NODEV;
258: ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
259: if (SESS_LEADER(p))
260: ep->e_flag |= EPROC_SLEADER;
261: if (p->p_wmesg)
262: strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
263: ep->e_xsize = ep->e_xrssize = 0;
264: ep->e_xccount = ep->e_xswrss = 0;
265: }
266:
267: /*
268: * Get file structures.
269: */
1.1.1.2 ! root 270: int
1.1 root 271: kinfo_file(op, where, acopysize, arg, aneeded)
1.1.1.2 ! root 272: int op;
1.1 root 273: register char *where;
274: int *acopysize, *aneeded;
1.1.1.2 ! root 275: int arg;
1.1 root 276: {
277: int buflen, needed, error;
278: struct file *fp;
279: char *start = where;
280:
281: if (where == NULL) {
282: /*
283: * overestimate by 10 files
284: */
285: *aneeded = sizeof (filehead) +
286: (nfiles + 10) * sizeof (struct file);
287: return (0);
288: }
289: buflen = *acopysize;
290: needed = 0;
291:
292: /*
293: * first copyout filehead
294: */
295: if (buflen > sizeof (filehead)) {
296: if (error = copyout((caddr_t)&filehead, where,
297: sizeof (filehead)))
298: return (error);
299: buflen -= sizeof (filehead);
300: where += sizeof (filehead);
301: }
302: needed += sizeof (filehead);
303:
304: /*
305: * followed by an array of file structures
306: */
307: for (fp = filehead; fp != NULL; fp = fp->f_filef) {
308: if (buflen > sizeof (struct file)) {
309: if (error = copyout((caddr_t)fp, where,
310: sizeof (struct file)))
311: return (error);
312: buflen -= sizeof (struct file);
313: where += sizeof (struct file);
314: }
315: needed += sizeof (struct file);
316: }
317: *acopysize = where - start;
318: *aneeded = needed;
319:
320: return (0);
321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.