setgroups check int > NGROUPS, so negative would fail; minor cleanup
[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 *
dbf0c423 7 * @(#)kern_sysctl.c 7.11 (Berkeley) %G%
4a24f1b0
MT
8 */
9
9fbbcc07
KM
10#include "param.h"
11#include "user.h"
12#include "proc.h"
2ed8b3ea 13#include "text.h"
4a24f1b0
MT
14#include "kinfo.h"
15#include "vm.h"
16#include "ioctl.h"
17#include "tty.h"
18#include "buf.h"
19
0a4df682
MT
20
21#define snderr(e) { error = (e); goto release;}
452737be 22extern int kinfo_doproc(), kinfo_rtable(), kinfo_vnode();
0a4df682
MT
23struct kinfo_lock kinfo_lock;
24
8b24ca5d
KM
25/* ARGSUSED */
26getkerninfo(p, uap, retval)
27 struct proc *p;
28 register struct args {
4a24f1b0
MT
29 int op;
30 char *where;
31 int *size;
32 int arg;
8b24ca5d
KM
33 } *uap;
34 int *retval;
35{
2ed8b3ea 36
0a4df682 37 int bufsize, /* max size of users buffer */
2ed8b3ea 38 needed, locked, (*server)(), error = 0;
0a4df682 39
2ed8b3ea
MT
40 if (error = copyin((caddr_t)uap->size,
41 (caddr_t)&bufsize, sizeof (bufsize)))
7acc8d38 42 goto done;
4a24f1b0
MT
43
44 switch (ki_type(uap->op)) {
45
46 case KINFO_PROC:
0a4df682
MT
47 server = kinfo_doproc;
48 break;
49
50 case KINFO_RT:
51 server = kinfo_rtable;
4a24f1b0
MT
52 break;
53
452737be
MT
54 case KINFO_VNODE:
55 server = kinfo_vnode;
56 break;
57
4a24f1b0 58 default:
2ed8b3ea 59 error = EINVAL;
7acc8d38
MT
60 goto done;
61 }
62 if (uap->where == NULL || uap->size == NULL) {
63 error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
64 goto done;
2ed8b3ea
MT
65 }
66 while (kinfo_lock.kl_lock) {
67 kinfo_lock.kl_want++;
68 sleep(&kinfo_lock, PRIBIO+1);
69 kinfo_lock.kl_want--;
70 kinfo_lock.kl_locked++;
4a24f1b0 71 }
2ed8b3ea
MT
72 kinfo_lock.kl_lock++;
73
7acc8d38 74 if (!useracc(uap->where, bufsize, B_WRITE))
0a4df682
MT
75 snderr(EFAULT);
76 /*
77 * lock down target pages - NEED DEADLOCK AVOIDANCE
78 */
7acc8d38 79 if (bufsize > ((int)ptob(freemem) - (20 * 1024))) /* XXX */
0a4df682 80 snderr(ENOMEM);
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:
150 if (p->p_uid != (uid_t)arg)
151 continue;
152 break;
153
154 case KINFO_PROC_RUID:
155 if (p->p_ruid != (uid_t)arg)
156 continue;
157 break;
158 }
159 if (where != NULL && buflen >= sizeof (struct kinfo_proc)) {
2ed8b3ea 160 register struct text *txt;
a65b44f0 161 register struct tty *tp;
2ed8b3ea 162
a65b44f0 163 if (error = copyout((caddr_t)p, &dp->kp_proc,
4a24f1b0
MT
164 sizeof (struct proc)))
165 return (error);
2ed8b3ea
MT
166 eproc.e_paddr = p;
167 eproc.e_sess = p->p_pgrp->pg_session;
168 eproc.e_pgid = p->p_pgrp->pg_id;
169 eproc.e_jobc = p->p_pgrp->pg_jobc;
a65b44f0
MT
170 if ((p->p_flag&SCTTY) &&
171 (tp = eproc.e_sess->s_ttyp)) {
2ed8b3ea
MT
172 eproc.e_tdev = tp->t_dev;
173 eproc.e_tpgid = tp->t_pgrp ?
4a24f1b0 174 tp->t_pgrp->pg_id : -1;
2ed8b3ea 175 eproc.e_tsess = tp->t_session;
4a24f1b0 176 } else
2ed8b3ea 177 eproc.e_tdev = NODEV;
a65b44f0
MT
178 eproc.e_flag = eproc.e_sess->s_ttyvp ? EPROC_CTTY : 0;
179 if (SESS_LEADER(p))
180 eproc.e_flag |= EPROC_SLEADER;
2ed8b3ea
MT
181 if (p->p_wmesg)
182 strncpy(eproc.e_wmesg, p->p_wmesg, WMESGLEN);
183 if (txt = p->p_textp) {
184 eproc.e_xsize = txt->x_size;
185 eproc.e_xrssize = txt->x_rssize;
186 eproc.e_xccount = txt->x_ccount;
187 eproc.e_xswrss = txt->x_swrss;
188 } else {
189 eproc.e_xsize = eproc.e_xrssize =
190 eproc.e_xccount = eproc.e_xswrss = 0;
191 }
a65b44f0 192 if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
7747bd3b 193 sizeof (eproc)))
4a24f1b0 194 return (error);
a65b44f0 195 dp++;
4a24f1b0
MT
196 buflen -= sizeof (struct kinfo_proc);
197 }
198 needed += sizeof (struct kinfo_proc);
199 }
200 if (doingzomb == 0) {
201 p = zombproc;
202 doingzomb++;
203 goto again;
204 }
205 if (where != NULL)
a65b44f0 206 *acopysize = (caddr_t)dp - where;
0a4df682
MT
207 else
208 needed += KINFO_PROCSLOP;
4a24f1b0
MT
209 *aneeded = needed;
210
211 return (0);
212}