|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)kern_kinfo.c 7.11 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "user.h"
25: #include "proc.h"
26: #include "text.h"
27: #include "kinfo.h"
28: #include "vm.h"
29: #include "ioctl.h"
30: #include "tty.h"
31: #include "buf.h"
32:
33:
34: #define snderr(e) { error = (e); goto release;}
35: extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode();
36: struct kinfo_lock kinfo_lock;
37:
38: /* ARGSUSED */
39: getkerninfo(p, uap, retval)
40: struct proc *p;
41: register struct args {
42: int op;
43: char *where;
44: int *size;
45: int arg;
46: } *uap;
47: int *retval;
48: {
49:
50: int bufsize, /* max size of users buffer */
51: needed, locked, (*server)(), error = 0;
52:
53: if (error = copyin((caddr_t)uap->size,
54: (caddr_t)&bufsize, sizeof (bufsize)))
55: goto done;
56:
57: switch (ki_type(uap->op)) {
58:
59: case KINFO_PROC:
60: server = kinfo_doproc;
61: break;
62:
63: case KINFO_RT:
64: server = kinfo_rtable;
65: break;
66:
67: case KINFO_VNODE:
68: server = kinfo_vnode;
69: break;
70:
71: default:
72: error = EINVAL;
73: goto done;
74: }
75: if (uap->where == NULL || uap->size == NULL) {
76: error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
77: goto done;
78: }
79: while (kinfo_lock.kl_lock) {
80: kinfo_lock.kl_want++;
81: sleep(&kinfo_lock, PRIBIO+1);
82: kinfo_lock.kl_want--;
83: kinfo_lock.kl_locked++;
84: }
85: kinfo_lock.kl_lock++;
86:
87: if (!useracc(uap->where, bufsize, B_WRITE))
88: snderr(EFAULT);
89: /*
90: * lock down target pages - NEED DEADLOCK AVOIDANCE
91: */
92: if (bufsize > ((int)ptob(freemem) - (20 * 1024))) /* XXX */
93: snderr(ENOMEM);
94: if (server != kinfo_vnode) /* XXX */
95: vslock(uap->where, bufsize);
96: locked = bufsize;
97: error = (*server)(uap->op, uap->where, &bufsize, uap->arg, &needed);
98: if (server != kinfo_vnode) /* XXX */
99: vsunlock(uap->where, locked, B_WRITE);
100: if (error == 0)
101: error = copyout((caddr_t)&bufsize,
102: (caddr_t)uap->size, sizeof (bufsize));
103: release:
104: kinfo_lock.kl_lock--;
105: if (kinfo_lock.kl_want)
106: wakeup(&kinfo_lock);
107: done:
108: if (!error)
109: *retval = needed;
110: return (error);
111: }
112:
113: /*
114: * try over estimating by 5 procs
115: */
116: #define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc))
117:
118: kinfo_doproc(op, where, acopysize, arg, aneeded)
119: char *where;
120: int *acopysize, *aneeded;
121: {
122: register struct proc *p;
123: register struct kinfo_proc *dp = (struct kinfo_proc *)where;
124: register needed = 0;
125: int buflen;
126: int doingzomb;
127: struct eproc eproc;
128: int error = 0;
129:
130: if (where != NULL)
131: buflen = *acopysize;
132:
133: p = allproc;
134: doingzomb = 0;
135: again:
136: for (; p != NULL; p = p->p_nxt) {
137: /*
138: * TODO - make more efficient (see notes below).
139: * do by session.
140: */
141: switch (ki_op(op)) {
142:
143: case KINFO_PROC_PID:
144: /* could do this with just a lookup */
145: if (p->p_pid != (pid_t)arg)
146: continue;
147: break;
148:
149: case KINFO_PROC_PGRP:
150: /* could do this by traversing pgrp */
151: if (p->p_pgrp->pg_id != (pid_t)arg)
152: continue;
153: break;
154:
155: case KINFO_PROC_TTY:
156: if ((p->p_flag&SCTTY) == 0 ||
157: p->p_session->s_ttyp == NULL ||
158: p->p_session->s_ttyp->t_dev != (dev_t)arg)
159: continue;
160: break;
161:
162: case KINFO_PROC_UID:
163: if (p->p_uid != (uid_t)arg)
164: continue;
165: break;
166:
167: case KINFO_PROC_RUID:
168: if (p->p_ruid != (uid_t)arg)
169: continue;
170: break;
171: }
172: if (where != NULL && buflen >= sizeof (struct kinfo_proc)) {
173: register struct text *txt;
174: register struct tty *tp;
175:
176: if (error = copyout((caddr_t)p, &dp->kp_proc,
177: sizeof (struct proc)))
178: return (error);
179: eproc.e_paddr = p;
180: eproc.e_sess = p->p_pgrp->pg_session;
181: eproc.e_pgid = p->p_pgrp->pg_id;
182: eproc.e_jobc = p->p_pgrp->pg_jobc;
183: if ((p->p_flag&SCTTY) &&
184: (tp = eproc.e_sess->s_ttyp)) {
185: eproc.e_tdev = tp->t_dev;
186: eproc.e_tpgid = tp->t_pgrp ?
187: tp->t_pgrp->pg_id : -1;
188: eproc.e_tsess = tp->t_session;
189: } else
190: eproc.e_tdev = NODEV;
191: eproc.e_flag = eproc.e_sess->s_ttyvp ? EPROC_CTTY : 0;
192: if (SESS_LEADER(p))
193: eproc.e_flag |= EPROC_SLEADER;
194: if (p->p_wmesg)
195: strncpy(eproc.e_wmesg, p->p_wmesg, WMESGLEN);
196: if (txt = p->p_textp) {
197: eproc.e_xsize = txt->x_size;
198: eproc.e_xrssize = txt->x_rssize;
199: eproc.e_xccount = txt->x_ccount;
200: eproc.e_xswrss = txt->x_swrss;
201: } else {
202: eproc.e_xsize = eproc.e_xrssize =
203: eproc.e_xccount = eproc.e_xswrss = 0;
204: }
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.