Commit | Line | Data |
---|---|---|
780d91b3 | 1 | /*- |
49286d48 KB |
2 | * Copyright (c) 1982, 1986, 1989, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
4a24f1b0 | 4 | * |
780d91b3 KM |
5 | * This code is derived from software contributed to Berkeley by |
6 | * Mike Karels at Berkeley Software Design, Inc. | |
7 | * | |
dbf0c423 | 8 | * %sccs.include.redist.c% |
4a24f1b0 | 9 | * |
49286d48 | 10 | * @(#)kern_sysctl.c 8.1 (Berkeley) %G% |
780d91b3 KM |
11 | */ |
12 | ||
13 | /* | |
14 | * sysctl system call. | |
4a24f1b0 MT |
15 | */ |
16 | ||
38a01dbe | 17 | #include <sys/param.h> |
780d91b3 | 18 | #include <sys/systm.h> |
7d1ac353 | 19 | #include <sys/kernel.h> |
780d91b3 | 20 | #include <sys/malloc.h> |
38a01dbe | 21 | #include <sys/proc.h> |
780d91b3 | 22 | #include <sys/file.h> |
a563bb07 | 23 | #include <sys/vnode.h> |
780d91b3 KM |
24 | #include <sys/unistd.h> |
25 | #include <sys/buf.h> | |
38a01dbe KB |
26 | #include <sys/ioctl.h> |
27 | #include <sys/tty.h> | |
38a01dbe | 28 | #include <vm/vm.h> |
9461524d | 29 | #include <sys/sysctl.h> |
32041eb1 | 30 | |
780d91b3 KM |
31 | sysctlfn kern_sysctl; |
32 | sysctlfn hw_sysctl; | |
5da5c832 KM |
33 | #ifdef DEBUG |
34 | sysctlfn debug_sysctl; | |
35 | #endif | |
780d91b3 KM |
36 | extern sysctlfn vm_sysctl; |
37 | extern sysctlfn fs_sysctl; | |
38 | extern sysctlfn net_sysctl; | |
39 | extern sysctlfn cpu_sysctl; | |
0a4df682 | 40 | |
780d91b3 KM |
41 | /* |
42 | * Locking and stats | |
43 | */ | |
44 | static struct sysctl_lock { | |
45 | int sl_lock; | |
46 | int sl_want; | |
47 | int sl_locked; | |
48 | } memlock; | |
49 | ||
50 | struct sysctl_args { | |
51 | int *name; | |
52 | u_int namelen; | |
53 | void *old; | |
b48024b7 | 54 | size_t *oldlenp; |
780d91b3 | 55 | void *new; |
b48024b7 | 56 | size_t newlen; |
9e97623a | 57 | }; |
780d91b3 | 58 | |
7de147d6 KB |
59 | int |
60 | __sysctl(p, uap, retval) | |
8b24ca5d | 61 | struct proc *p; |
780d91b3 | 62 | register struct sysctl_args *uap; |
8b24ca5d KM |
63 | int *retval; |
64 | { | |
780d91b3 KM |
65 | int error, dolock = 1; |
66 | u_int savelen, oldlen = 0; | |
67 | sysctlfn *fn; | |
68 | int name[CTL_MAXNAME]; | |
0a4df682 | 69 | |
780d91b3 KM |
70 | if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) |
71 | return (error); | |
72 | /* | |
73 | * all top-level sysctl names are non-terminal | |
74 | */ | |
75 | if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) | |
76 | return (EINVAL); | |
77 | if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) | |
78 | return (error); | |
79 | ||
80 | switch (name[0]) { | |
81 | case CTL_KERN: | |
82 | fn = kern_sysctl; | |
83 | if (name[2] != KERN_VNODE) /* XXX */ | |
84 | dolock = 0; | |
0a4df682 | 85 | break; |
780d91b3 KM |
86 | case CTL_HW: |
87 | fn = hw_sysctl; | |
4a24f1b0 | 88 | break; |
780d91b3 KM |
89 | case CTL_VM: |
90 | fn = vm_sysctl; | |
452737be | 91 | break; |
780d91b3 KM |
92 | case CTL_NET: |
93 | fn = net_sysctl; | |
318784c4 | 94 | break; |
780d91b3 KM |
95 | #ifdef notyet |
96 | case CTL_FS: | |
97 | fn = fs_sysctl; | |
15415c71 | 98 | break; |
8a5906c5 | 99 | #endif |
780d91b3 KM |
100 | case CTL_MACHDEP: |
101 | fn = cpu_sysctl; | |
61ece7fc | 102 | break; |
5da5c832 KM |
103 | #ifdef DEBUG |
104 | case CTL_DEBUG: | |
105 | fn = debug_sysctl; | |
106 | break; | |
780d91b3 | 107 | #endif |
4a24f1b0 | 108 | default: |
780d91b3 | 109 | return (EOPNOTSUPP); |
7acc8d38 | 110 | } |
780d91b3 KM |
111 | |
112 | if (uap->oldlenp && | |
113 | (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) | |
114 | return (error); | |
115 | if (uap->old != NULL) { | |
116 | if (!useracc(uap->old, oldlen, B_WRITE)) | |
117 | return (EFAULT); | |
118 | while (memlock.sl_lock) { | |
119 | memlock.sl_want = 1; | |
120 | sleep((caddr_t)&memlock, PRIBIO+1); | |
121 | memlock.sl_locked++; | |
122 | } | |
123 | memlock.sl_lock = 1; | |
124 | if (dolock) | |
125 | vslock(uap->old, oldlen); | |
126 | savelen = oldlen; | |
2ed8b3ea | 127 | } |
780d91b3 | 128 | error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, |
0f1d36b0 | 129 | uap->new, uap->newlen, p); |
780d91b3 KM |
130 | if (uap->old != NULL) { |
131 | if (dolock) | |
132 | vsunlock(uap->old, savelen, B_WRITE); | |
133 | memlock.sl_lock = 0; | |
134 | if (memlock.sl_want) { | |
135 | memlock.sl_want = 0; | |
136 | wakeup((caddr_t)&memlock); | |
137 | } | |
4a24f1b0 | 138 | } |
780d91b3 KM |
139 | if (error) |
140 | return (error); | |
141 | if (uap->oldlenp) | |
142 | error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); | |
143 | *retval = oldlen; | |
144 | return (0); | |
145 | } | |
146 | ||
147 | /* | |
148 | * Attributes stored in the kernel. | |
149 | */ | |
150 | char hostname[MAXHOSTNAMELEN]; | |
151 | int hostnamelen; | |
152 | long hostid; | |
0f1d36b0 | 153 | int securelevel; |
780d91b3 | 154 | |
0f1d36b0 KM |
155 | /* |
156 | * kernel related system variables. | |
157 | */ | |
158 | kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) | |
780d91b3 KM |
159 | int *name; |
160 | u_int namelen; | |
161 | void *oldp; | |
b48024b7 | 162 | size_t *oldlenp; |
780d91b3 | 163 | void *newp; |
b48024b7 | 164 | size_t newlen; |
0f1d36b0 | 165 | struct proc *p; |
780d91b3 | 166 | { |
5881eb7b | 167 | int error, level, inthostid; |
780d91b3 KM |
168 | extern char ostype[], osrelease[], version[]; |
169 | ||
170 | /* all sysctl names at this level are terminal */ | |
ab16dfd9 | 171 | if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) |
780d91b3 KM |
172 | return (ENOTDIR); /* overloaded */ |
173 | ||
174 | switch (name[0]) { | |
175 | case KERN_OSTYPE: | |
176 | return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); | |
177 | case KERN_OSRELEASE: | |
178 | return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); | |
179 | case KERN_OSREV: | |
180 | return (sysctl_rdint(oldp, oldlenp, newp, BSD)); | |
181 | case KERN_VERSION: | |
182 | return (sysctl_rdstring(oldp, oldlenp, newp, version)); | |
7de147d6 KB |
183 | case KERN_MAXVNODES: |
184 | return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); | |
780d91b3 KM |
185 | case KERN_MAXPROC: |
186 | return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); | |
187 | case KERN_MAXFILES: | |
188 | return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); | |
189 | case KERN_ARGMAX: | |
190 | return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); | |
0f1d36b0 KM |
191 | case KERN_SECURELVL: |
192 | level = securelevel; | |
193 | if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || | |
194 | newp == NULL) | |
195 | return (error); | |
196 | if (level < securelevel && p->p_pid != 1) | |
197 | return (EPERM); | |
198 | securelevel = level; | |
199 | return (0); | |
7de147d6 KB |
200 | case KERN_HOSTNAME: |
201 | error = sysctl_string(oldp, oldlenp, newp, newlen, | |
202 | hostname, sizeof(hostname)); | |
0b8b427e | 203 | if (newp && !error) |
7de147d6 KB |
204 | hostnamelen = newlen; |
205 | return (error); | |
206 | case KERN_HOSTID: | |
5881eb7b KM |
207 | inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ |
208 | error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); | |
209 | hostid = inthostid; | |
210 | return (error); | |
780d91b3 KM |
211 | case KERN_CLOCKRATE: |
212 | return (sysctl_clockrate(oldp, oldlenp)); | |
7d1ac353 KM |
213 | case KERN_BOOTTIME: |
214 | return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, | |
215 | sizeof(struct timeval))); | |
780d91b3 KM |
216 | case KERN_VNODE: |
217 | return (sysctl_vnode(oldp, oldlenp)); | |
218 | case KERN_PROC: | |
219 | return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); | |
7de147d6 KB |
220 | case KERN_FILE: |
221 | return (sysctl_file(oldp, oldlenp)); | |
ab16dfd9 KM |
222 | #ifdef GPROF |
223 | case KERN_PROF: | |
224 | return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, | |
225 | newp, newlen)); | |
226 | #endif | |
7de147d6 KB |
227 | case KERN_POSIX1: |
228 | return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); | |
229 | case KERN_NGROUPS: | |
230 | return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); | |
231 | case KERN_JOB_CONTROL: | |
232 | return (sysctl_rdint(oldp, oldlenp, newp, 1)); | |
233 | case KERN_SAVED_IDS: | |
234 | #ifdef _POSIX_SAVED_IDS | |
235 | return (sysctl_rdint(oldp, oldlenp, newp, 1)); | |
236 | #else | |
237 | return (sysctl_rdint(oldp, oldlenp, newp, 0)); | |
238 | #endif | |
780d91b3 KM |
239 | default: |
240 | return (EOPNOTSUPP); | |
241 | } | |
242 | /* NOTREACHED */ | |
243 | } | |
244 | ||
0f1d36b0 KM |
245 | /* |
246 | * hardware related system variables. | |
247 | */ | |
248 | hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) | |
780d91b3 KM |
249 | int *name; |
250 | u_int namelen; | |
251 | void *oldp; | |
b48024b7 | 252 | size_t *oldlenp; |
780d91b3 | 253 | void *newp; |
b48024b7 | 254 | size_t newlen; |
0f1d36b0 | 255 | struct proc *p; |
780d91b3 KM |
256 | { |
257 | extern char machine[], cpu_model[]; | |
258 | ||
259 | /* all sysctl names at this level are terminal */ | |
260 | if (namelen != 1) | |
261 | return (ENOTDIR); /* overloaded */ | |
262 | ||
263 | switch (name[0]) { | |
264 | case HW_MACHINE: | |
265 | return (sysctl_rdstring(oldp, oldlenp, newp, machine)); | |
266 | case HW_MODEL: | |
267 | return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); | |
268 | case HW_NCPU: | |
269 | return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ | |
c99af07b KM |
270 | case HW_BYTEORDER: |
271 | return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); | |
780d91b3 KM |
272 | case HW_PHYSMEM: |
273 | return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); | |
274 | case HW_USERMEM: | |
275 | return (sysctl_rdint(oldp, oldlenp, newp, | |
276 | ctob(physmem - cnt.v_wire_count))); | |
277 | case HW_PAGESIZE: | |
278 | return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); | |
279 | default: | |
280 | return (EOPNOTSUPP); | |
281 | } | |
282 | /* NOTREACHED */ | |
283 | } | |
284 | ||
5da5c832 KM |
285 | #ifdef DEBUG |
286 | /* | |
287 | * Debugging related system variables. | |
288 | */ | |
289 | struct ctldebug debug0, debug1, debug2, debug3, debug4; | |
290 | struct ctldebug debug5, debug6, debug7, debug8, debug9; | |
291 | struct ctldebug debug10, debug11, debug12, debug13, debug14; | |
292 | struct ctldebug debug15, debug16, debug17, debug18, debug19; | |
293 | static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { | |
294 | &debug0, &debug1, &debug2, &debug3, &debug4, | |
295 | &debug5, &debug6, &debug7, &debug8, &debug9, | |
296 | &debug10, &debug11, &debug12, &debug13, &debug14, | |
297 | &debug15, &debug16, &debug17, &debug18, &debug19, | |
298 | }; | |
299 | int | |
300 | debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) | |
301 | int *name; | |
302 | u_int namelen; | |
303 | void *oldp; | |
304 | size_t *oldlenp; | |
305 | void *newp; | |
306 | size_t newlen; | |
307 | struct proc *p; | |
308 | { | |
309 | struct ctldebug *cdp; | |
310 | ||
311 | /* all sysctl names at this level are name and field */ | |
312 | if (namelen != 2) | |
313 | return (ENOTDIR); /* overloaded */ | |
314 | cdp = debugvars[name[0]]; | |
315 | if (cdp->debugname == 0) | |
316 | return (EOPNOTSUPP); | |
317 | switch (name[1]) { | |
318 | case CTL_DEBUG_NAME: | |
319 | return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); | |
320 | case CTL_DEBUG_VALUE: | |
321 | return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); | |
322 | default: | |
323 | return (EOPNOTSUPP); | |
324 | } | |
325 | /* NOTREACHED */ | |
326 | } | |
327 | #endif /* DEBUG */ | |
328 | ||
780d91b3 KM |
329 | /* |
330 | * Validate parameters and get old / set new parameters | |
331 | * for an integer-valued sysctl function. | |
332 | */ | |
333 | sysctl_int(oldp, oldlenp, newp, newlen, valp) | |
334 | void *oldp; | |
b48024b7 | 335 | size_t *oldlenp; |
780d91b3 | 336 | void *newp; |
b48024b7 | 337 | size_t newlen; |
780d91b3 KM |
338 | int *valp; |
339 | { | |
340 | int error = 0; | |
341 | ||
342 | if (oldp && *oldlenp < sizeof(int)) | |
343 | return (ENOMEM); | |
344 | if (newp && newlen != sizeof(int)) | |
345 | return (EINVAL); | |
346 | *oldlenp = sizeof(int); | |
347 | if (oldp) | |
348 | error = copyout(valp, oldp, sizeof(int)); | |
349 | if (error == 0 && newp) | |
350 | error = copyin(newp, valp, sizeof(int)); | |
351 | return (error); | |
352 | } | |
353 | ||
354 | /* | |
355 | * As above, but read-only. | |
356 | */ | |
357 | sysctl_rdint(oldp, oldlenp, newp, val) | |
358 | void *oldp; | |
b48024b7 | 359 | size_t *oldlenp; |
780d91b3 KM |
360 | void *newp; |
361 | int val; | |
362 | { | |
363 | int error = 0; | |
364 | ||
365 | if (oldp && *oldlenp < sizeof(int)) | |
366 | return (ENOMEM); | |
367 | if (newp) | |
368 | return (EPERM); | |
369 | *oldlenp = sizeof(int); | |
370 | if (oldp) | |
371 | error = copyout((caddr_t)&val, oldp, sizeof(int)); | |
372 | return (error); | |
373 | } | |
374 | ||
375 | /* | |
376 | * Validate parameters and get old / set new parameters | |
377 | * for a string-valued sysctl function. | |
378 | */ | |
379 | sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) | |
380 | void *oldp; | |
b48024b7 | 381 | size_t *oldlenp; |
780d91b3 | 382 | void *newp; |
b48024b7 | 383 | size_t newlen; |
780d91b3 KM |
384 | char *str; |
385 | int maxlen; | |
386 | { | |
387 | int len, error = 0; | |
388 | ||
389 | len = strlen(str) + 1; | |
390 | if (oldp && *oldlenp < len) | |
391 | return (ENOMEM); | |
392 | if (newp && newlen >= maxlen) | |
393 | return (EINVAL); | |
924ae1bd RC |
394 | if (oldp) { |
395 | *oldlenp = len; | |
780d91b3 | 396 | error = copyout(str, oldp, len); |
924ae1bd | 397 | } |
780d91b3 KM |
398 | if (error == 0 && newp) { |
399 | error = copyin(newp, str, newlen); | |
400 | str[newlen] = 0; | |
13bbbe63 | 401 | } |
8b24ca5d | 402 | return (error); |
4a24f1b0 MT |
403 | } |
404 | ||
780d91b3 KM |
405 | /* |
406 | * As above, but read-only. | |
407 | */ | |
408 | sysctl_rdstring(oldp, oldlenp, newp, str) | |
409 | void *oldp; | |
b48024b7 | 410 | size_t *oldlenp; |
780d91b3 KM |
411 | void *newp; |
412 | char *str; | |
413 | { | |
414 | int len, error = 0; | |
415 | ||
416 | len = strlen(str) + 1; | |
417 | if (oldp && *oldlenp < len) | |
418 | return (ENOMEM); | |
419 | if (newp) | |
420 | return (EPERM); | |
421 | *oldlenp = len; | |
422 | if (oldp) | |
423 | error = copyout(str, oldp, len); | |
424 | return (error); | |
425 | } | |
426 | ||
ab16dfd9 KM |
427 | /* |
428 | * Validate parameters and get old / set new parameters | |
429 | * for a structure oriented sysctl function. | |
430 | */ | |
431 | sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) | |
432 | void *oldp; | |
433 | size_t *oldlenp; | |
434 | void *newp; | |
435 | size_t newlen; | |
436 | void *sp; | |
437 | int len; | |
438 | { | |
439 | int error = 0; | |
440 | ||
441 | if (oldp && *oldlenp < len) | |
442 | return (ENOMEM); | |
443 | if (newp && newlen > len) | |
444 | return (EINVAL); | |
445 | if (oldp) { | |
446 | *oldlenp = len; | |
447 | error = copyout(sp, oldp, len); | |
448 | } | |
449 | if (error == 0 && newp) | |
450 | error = copyin(newp, sp, len); | |
451 | return (error); | |
452 | } | |
453 | ||
780d91b3 KM |
454 | /* |
455 | * Validate parameters and get old parameters | |
456 | * for a structure oriented sysctl function. | |
457 | */ | |
458 | sysctl_rdstruct(oldp, oldlenp, newp, sp, len) | |
459 | void *oldp; | |
b48024b7 KB |
460 | size_t *oldlenp; |
461 | void *newp, *sp; | |
780d91b3 KM |
462 | int len; |
463 | { | |
464 | int error = 0; | |
465 | ||
466 | if (oldp && *oldlenp < len) | |
467 | return (ENOMEM); | |
468 | if (newp) | |
469 | return (EPERM); | |
470 | *oldlenp = len; | |
471 | if (oldp) | |
472 | error = copyout(sp, oldp, len); | |
473 | return (error); | |
474 | } | |
475 | ||
476 | /* | |
477 | * Get file structures. | |
478 | */ | |
479 | sysctl_file(where, sizep) | |
480 | char *where; | |
b48024b7 | 481 | size_t *sizep; |
780d91b3 KM |
482 | { |
483 | int buflen, error; | |
484 | struct file *fp; | |
485 | char *start = where; | |
486 | ||
487 | buflen = *sizep; | |
488 | if (where == NULL) { | |
489 | /* | |
490 | * overestimate by 10 files | |
491 | */ | |
492 | *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); | |
493 | return (0); | |
494 | } | |
495 | ||
496 | /* | |
497 | * first copyout filehead | |
498 | */ | |
499 | if (buflen < sizeof(filehead)) { | |
500 | *sizep = 0; | |
501 | return (0); | |
502 | } | |
503 | if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) | |
504 | return (error); | |
505 | buflen += sizeof(filehead); | |
506 | where += sizeof(filehead); | |
507 | ||
508 | /* | |
509 | * followed by an array of file structures | |
510 | */ | |
511 | for (fp = filehead; fp != NULL; fp = fp->f_filef) { | |
512 | if (buflen < sizeof(struct file)) { | |
513 | *sizep = where - start; | |
514 | return (ENOMEM); | |
515 | } | |
516 | if (error = copyout((caddr_t)fp, where, sizeof (struct file))) | |
517 | return (error); | |
518 | buflen -= sizeof(struct file); | |
519 | where += sizeof(struct file); | |
520 | } | |
521 | *sizep = where - start; | |
522 | return (0); | |
523 | } | |
524 | ||
ab16dfd9 KM |
525 | /* |
526 | * try over estimating by 5 procs | |
4a24f1b0 | 527 | */ |
780d91b3 | 528 | #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) |
4a24f1b0 | 529 | |
780d91b3 KM |
530 | sysctl_doproc(name, namelen, where, sizep) |
531 | int *name; | |
b48024b7 | 532 | u_int namelen; |
4a24f1b0 | 533 | char *where; |
b48024b7 | 534 | size_t *sizep; |
4a24f1b0 MT |
535 | { |
536 | register struct proc *p; | |
a65b44f0 | 537 | register struct kinfo_proc *dp = (struct kinfo_proc *)where; |
780d91b3 KM |
538 | register int needed = 0; |
539 | int buflen = where != NULL ? *sizep : 0; | |
4a24f1b0 | 540 | int doingzomb; |
7747bd3b | 541 | struct eproc eproc; |
4a24f1b0 MT |
542 | int error = 0; |
543 | ||
e9c7de58 | 544 | if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) |
780d91b3 | 545 | return (EINVAL); |
80a8e5e6 | 546 | p = (struct proc *)allproc; |
4a24f1b0 MT |
547 | doingzomb = 0; |
548 | again: | |
549 | for (; p != NULL; p = p->p_nxt) { | |
02ea4076 KM |
550 | /* |
551 | * Skip embryonic processes. | |
552 | */ | |
553 | if (p->p_stat == SIDL) | |
554 | continue; | |
ab16dfd9 | 555 | /* |
4a24f1b0 | 556 | * TODO - make more efficient (see notes below). |
ab16dfd9 | 557 | * do by session. |
4a24f1b0 | 558 | */ |
780d91b3 | 559 | switch (name[0]) { |
4a24f1b0 | 560 | |
780d91b3 | 561 | case KERN_PROC_PID: |
4a24f1b0 | 562 | /* could do this with just a lookup */ |
780d91b3 | 563 | if (p->p_pid != (pid_t)name[1]) |
4a24f1b0 MT |
564 | continue; |
565 | break; | |
566 | ||
780d91b3 | 567 | case KERN_PROC_PGRP: |
4a24f1b0 | 568 | /* could do this by traversing pgrp */ |
780d91b3 | 569 | if (p->p_pgrp->pg_id != (pid_t)name[1]) |
4a24f1b0 MT |
570 | continue; |
571 | break; | |
572 | ||
780d91b3 | 573 | case KERN_PROC_TTY: |
ab16dfd9 | 574 | if ((p->p_flag&SCTTY) == 0 || |
4a24f1b0 | 575 | p->p_session->s_ttyp == NULL || |
780d91b3 | 576 | p->p_session->s_ttyp->t_dev != (dev_t)name[1]) |
4a24f1b0 MT |
577 | continue; |
578 | break; | |
579 | ||
780d91b3 KM |
580 | case KERN_PROC_UID: |
581 | if (p->p_ucred->cr_uid != (uid_t)name[1]) | |
4a24f1b0 MT |
582 | continue; |
583 | break; | |
584 | ||
780d91b3 KM |
585 | case KERN_PROC_RUID: |
586 | if (p->p_cred->p_ruid != (uid_t)name[1]) | |
4a24f1b0 MT |
587 | continue; |
588 | break; | |
589 | } | |
780d91b3 | 590 | if (buflen >= sizeof(struct kinfo_proc)) { |
32041eb1 | 591 | fill_eproc(p, &eproc); |
ab16dfd9 | 592 | if (error = copyout((caddr_t)p, &dp->kp_proc, |
780d91b3 | 593 | sizeof(struct proc))) |
4a24f1b0 | 594 | return (error); |
ab16dfd9 | 595 | if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, |
780d91b3 | 596 | sizeof(eproc))) |
4a24f1b0 | 597 | return (error); |
a65b44f0 | 598 | dp++; |
780d91b3 | 599 | buflen -= sizeof(struct kinfo_proc); |
4a24f1b0 | 600 | } |
780d91b3 | 601 | needed += sizeof(struct kinfo_proc); |
4a24f1b0 MT |
602 | } |
603 | if (doingzomb == 0) { | |
604 | p = zombproc; | |
605 | doingzomb++; | |
606 | goto again; | |
607 | } | |
780d91b3 KM |
608 | if (where != NULL) { |
609 | *sizep = (caddr_t)dp - where; | |
610 | if (needed > *sizep) | |
611 | return (ENOMEM); | |
612 | } else { | |
613 | needed += KERN_PROCSLOP; | |
614 | *sizep = needed; | |
615 | } | |
4a24f1b0 MT |
616 | return (0); |
617 | } | |
32041eb1 MK |
618 | |
619 | /* | |
620 | * Fill in an eproc structure for the specified process. | |
621 | */ | |
622 | void | |
623 | fill_eproc(p, ep) | |
624 | register struct proc *p; | |
625 | register struct eproc *ep; | |
626 | { | |
627 | register struct tty *tp; | |
628 | ||
629 | ep->e_paddr = p; | |
630 | ep->e_sess = p->p_pgrp->pg_session; | |
631 | ep->e_pcred = *p->p_cred; | |
632 | ep->e_ucred = *p->p_ucred; | |
13bbbe63 CT |
633 | if (p->p_stat == SIDL || p->p_stat == SZOMB) { |
634 | ep->e_vm.vm_rssize = 0; | |
635 | ep->e_vm.vm_tsize = 0; | |
636 | ep->e_vm.vm_dsize = 0; | |
637 | ep->e_vm.vm_ssize = 0; | |
638 | #ifndef sparc | |
639 | /* ep->e_vm.vm_pmap = XXX; */ | |
640 | #endif | |
641 | } else { | |
642 | register struct vmspace *vm = p->p_vmspace; | |
643 | ||
644 | ep->e_vm.vm_rssize = vm->vm_rssize; | |
645 | ep->e_vm.vm_tsize = vm->vm_tsize; | |
646 | ep->e_vm.vm_dsize = vm->vm_dsize; | |
647 | ep->e_vm.vm_ssize = vm->vm_ssize; | |
648 | #ifndef sparc | |
649 | ep->e_vm.vm_pmap = vm->vm_pmap; | |
650 | #endif | |
651 | } | |
31c481fa MK |
652 | if (p->p_pptr) |
653 | ep->e_ppid = p->p_pptr->p_pid; | |
654 | else | |
655 | ep->e_ppid = 0; | |
32041eb1 MK |
656 | ep->e_pgid = p->p_pgrp->pg_id; |
657 | ep->e_jobc = p->p_pgrp->pg_jobc; | |
ab16dfd9 | 658 | if ((p->p_flag&SCTTY) && |
32041eb1 MK |
659 | (tp = ep->e_sess->s_ttyp)) { |
660 | ep->e_tdev = tp->t_dev; | |
51d82109 | 661 | ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; |
32041eb1 MK |
662 | ep->e_tsess = tp->t_session; |
663 | } else | |
664 | ep->e_tdev = NODEV; | |
665 | ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; | |
666 | if (SESS_LEADER(p)) | |
667 | ep->e_flag |= EPROC_SLEADER; | |
668 | if (p->p_wmesg) | |
669 | strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); | |
670 | ep->e_xsize = ep->e_xrssize = 0; | |
671 | ep->e_xccount = ep->e_xswrss = 0; | |
672 | } | |
318784c4 | 673 | |
780d91b3 | 674 | #ifdef COMPAT_43 |
780d91b3 | 675 | #include <sys/socket.h> |
1fa29dab KM |
676 | #define KINFO_PROC (0<<8) |
677 | #define KINFO_RT (1<<8) | |
678 | #define KINFO_VNODE (2<<8) | |
679 | #define KINFO_FILE (3<<8) | |
680 | #define KINFO_METER (4<<8) | |
681 | #define KINFO_LOADAVG (5<<8) | |
682 | #define KINFO_CLOCKRATE (6<<8) | |
780d91b3 KM |
683 | |
684 | struct getkerninfo_args { | |
685 | int op; | |
686 | char *where; | |
687 | int *size; | |
688 | int arg; | |
689 | }; | |
690 | ||
7e024c88 | 691 | ogetkerninfo(p, uap, retval) |
780d91b3 KM |
692 | struct proc *p; |
693 | register struct getkerninfo_args *uap; | |
694 | int *retval; | |
318784c4 | 695 | { |
780d91b3 KM |
696 | int error, name[5]; |
697 | u_int size; | |
318784c4 | 698 | |
358fe79a | 699 | if (uap->size && |
b48024b7 | 700 | (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) |
780d91b3 | 701 | return (error); |
318784c4 | 702 | |
1fa29dab | 703 | switch (uap->op & 0xff00) { |
318784c4 | 704 | |
780d91b3 KM |
705 | case KINFO_RT: |
706 | name[0] = PF_ROUTE; | |
707 | name[1] = 0; | |
708 | name[2] = (uap->op & 0xff0000) >> 16; | |
709 | name[3] = uap->op & 0xff; | |
710 | name[4] = uap->arg; | |
0f1d36b0 | 711 | error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); |
780d91b3 | 712 | break; |
318784c4 | 713 | |
780d91b3 KM |
714 | case KINFO_VNODE: |
715 | name[0] = KERN_VNODE; | |
0f1d36b0 | 716 | error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
717 | break; |
718 | ||
719 | case KINFO_PROC: | |
720 | name[0] = KERN_PROC; | |
721 | name[1] = uap->op & 0xff; | |
722 | name[2] = uap->arg; | |
0f1d36b0 | 723 | error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
724 | break; |
725 | ||
726 | case KINFO_FILE: | |
727 | name[0] = KERN_FILE; | |
0f1d36b0 | 728 | error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
729 | break; |
730 | ||
731 | case KINFO_METER: | |
732 | name[0] = VM_METER; | |
0f1d36b0 | 733 | error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
734 | break; |
735 | ||
736 | case KINFO_LOADAVG: | |
737 | name[0] = VM_LOADAVG; | |
0f1d36b0 | 738 | error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
739 | break; |
740 | ||
741 | case KINFO_CLOCKRATE: | |
742 | name[0] = KERN_CLOCKRATE; | |
0f1d36b0 | 743 | error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
744 | break; |
745 | ||
746 | default: | |
0f1d36b0 | 747 | return (EOPNOTSUPP); |
780d91b3 KM |
748 | } |
749 | if (error) | |
750 | return (error); | |
751 | *retval = size; | |
358fe79a KM |
752 | if (uap->size) |
753 | error = copyout((caddr_t)&size, (caddr_t)uap->size, | |
754 | sizeof(size)); | |
755 | return (error); | |
318784c4 | 756 | } |
780d91b3 | 757 | #endif /* COMPAT_43 */ |