Commit | Line | Data |
---|---|---|
780d91b3 KM |
1 | /*- |
2 | * Copyright (c) 1982, 1986, 1989, 1993 Regents of the University of California. | |
4a24f1b0 MT |
3 | * All rights reserved. |
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 | * |
0b8b427e | 10 | * @(#)kern_sysctl.c 7.44 (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 | { |
0f1d36b0 | 167 | int error, level; |
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: | |
207 | return (sysctl_int(oldp, oldlenp, newp, newlen, &hostid)); | |
780d91b3 KM |
208 | case KERN_CLOCKRATE: |
209 | return (sysctl_clockrate(oldp, oldlenp)); | |
7d1ac353 KM |
210 | case KERN_BOOTTIME: |
211 | return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, | |
212 | sizeof(struct timeval))); | |
780d91b3 KM |
213 | case KERN_VNODE: |
214 | return (sysctl_vnode(oldp, oldlenp)); | |
215 | case KERN_PROC: | |
216 | return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); | |
7de147d6 KB |
217 | case KERN_FILE: |
218 | return (sysctl_file(oldp, oldlenp)); | |
ab16dfd9 KM |
219 | #ifdef GPROF |
220 | case KERN_PROF: | |
221 | return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, | |
222 | newp, newlen)); | |
223 | #endif | |
7de147d6 KB |
224 | case KERN_POSIX1: |
225 | return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); | |
226 | case KERN_NGROUPS: | |
227 | return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); | |
228 | case KERN_JOB_CONTROL: | |
229 | return (sysctl_rdint(oldp, oldlenp, newp, 1)); | |
230 | case KERN_SAVED_IDS: | |
231 | #ifdef _POSIX_SAVED_IDS | |
232 | return (sysctl_rdint(oldp, oldlenp, newp, 1)); | |
233 | #else | |
234 | return (sysctl_rdint(oldp, oldlenp, newp, 0)); | |
235 | #endif | |
780d91b3 KM |
236 | default: |
237 | return (EOPNOTSUPP); | |
238 | } | |
239 | /* NOTREACHED */ | |
240 | } | |
241 | ||
0f1d36b0 KM |
242 | /* |
243 | * hardware related system variables. | |
244 | */ | |
245 | hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) | |
780d91b3 KM |
246 | int *name; |
247 | u_int namelen; | |
248 | void *oldp; | |
b48024b7 | 249 | size_t *oldlenp; |
780d91b3 | 250 | void *newp; |
b48024b7 | 251 | size_t newlen; |
0f1d36b0 | 252 | struct proc *p; |
780d91b3 KM |
253 | { |
254 | extern char machine[], cpu_model[]; | |
255 | ||
256 | /* all sysctl names at this level are terminal */ | |
257 | if (namelen != 1) | |
258 | return (ENOTDIR); /* overloaded */ | |
259 | ||
260 | switch (name[0]) { | |
261 | case HW_MACHINE: | |
262 | return (sysctl_rdstring(oldp, oldlenp, newp, machine)); | |
263 | case HW_MODEL: | |
264 | return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); | |
265 | case HW_NCPU: | |
266 | return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ | |
c99af07b KM |
267 | case HW_BYTEORDER: |
268 | return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); | |
780d91b3 KM |
269 | case HW_PHYSMEM: |
270 | return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); | |
271 | case HW_USERMEM: | |
272 | return (sysctl_rdint(oldp, oldlenp, newp, | |
273 | ctob(physmem - cnt.v_wire_count))); | |
274 | case HW_PAGESIZE: | |
275 | return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); | |
276 | default: | |
277 | return (EOPNOTSUPP); | |
278 | } | |
279 | /* NOTREACHED */ | |
280 | } | |
281 | ||
5da5c832 KM |
282 | #ifdef DEBUG |
283 | /* | |
284 | * Debugging related system variables. | |
285 | */ | |
286 | struct ctldebug debug0, debug1, debug2, debug3, debug4; | |
287 | struct ctldebug debug5, debug6, debug7, debug8, debug9; | |
288 | struct ctldebug debug10, debug11, debug12, debug13, debug14; | |
289 | struct ctldebug debug15, debug16, debug17, debug18, debug19; | |
290 | static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { | |
291 | &debug0, &debug1, &debug2, &debug3, &debug4, | |
292 | &debug5, &debug6, &debug7, &debug8, &debug9, | |
293 | &debug10, &debug11, &debug12, &debug13, &debug14, | |
294 | &debug15, &debug16, &debug17, &debug18, &debug19, | |
295 | }; | |
296 | int | |
297 | debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) | |
298 | int *name; | |
299 | u_int namelen; | |
300 | void *oldp; | |
301 | size_t *oldlenp; | |
302 | void *newp; | |
303 | size_t newlen; | |
304 | struct proc *p; | |
305 | { | |
306 | struct ctldebug *cdp; | |
307 | ||
308 | /* all sysctl names at this level are name and field */ | |
309 | if (namelen != 2) | |
310 | return (ENOTDIR); /* overloaded */ | |
311 | cdp = debugvars[name[0]]; | |
312 | if (cdp->debugname == 0) | |
313 | return (EOPNOTSUPP); | |
314 | switch (name[1]) { | |
315 | case CTL_DEBUG_NAME: | |
316 | return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); | |
317 | case CTL_DEBUG_VALUE: | |
318 | return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); | |
319 | default: | |
320 | return (EOPNOTSUPP); | |
321 | } | |
322 | /* NOTREACHED */ | |
323 | } | |
324 | #endif /* DEBUG */ | |
325 | ||
780d91b3 KM |
326 | /* |
327 | * Validate parameters and get old / set new parameters | |
328 | * for an integer-valued sysctl function. | |
329 | */ | |
330 | sysctl_int(oldp, oldlenp, newp, newlen, valp) | |
331 | void *oldp; | |
b48024b7 | 332 | size_t *oldlenp; |
780d91b3 | 333 | void *newp; |
b48024b7 | 334 | size_t newlen; |
780d91b3 KM |
335 | int *valp; |
336 | { | |
337 | int error = 0; | |
338 | ||
339 | if (oldp && *oldlenp < sizeof(int)) | |
340 | return (ENOMEM); | |
341 | if (newp && newlen != sizeof(int)) | |
342 | return (EINVAL); | |
343 | *oldlenp = sizeof(int); | |
344 | if (oldp) | |
345 | error = copyout(valp, oldp, sizeof(int)); | |
346 | if (error == 0 && newp) | |
347 | error = copyin(newp, valp, sizeof(int)); | |
348 | return (error); | |
349 | } | |
350 | ||
351 | /* | |
352 | * As above, but read-only. | |
353 | */ | |
354 | sysctl_rdint(oldp, oldlenp, newp, val) | |
355 | void *oldp; | |
b48024b7 | 356 | size_t *oldlenp; |
780d91b3 KM |
357 | void *newp; |
358 | int val; | |
359 | { | |
360 | int error = 0; | |
361 | ||
362 | if (oldp && *oldlenp < sizeof(int)) | |
363 | return (ENOMEM); | |
364 | if (newp) | |
365 | return (EPERM); | |
366 | *oldlenp = sizeof(int); | |
367 | if (oldp) | |
368 | error = copyout((caddr_t)&val, oldp, sizeof(int)); | |
369 | return (error); | |
370 | } | |
371 | ||
372 | /* | |
373 | * Validate parameters and get old / set new parameters | |
374 | * for a string-valued sysctl function. | |
375 | */ | |
376 | sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) | |
377 | void *oldp; | |
b48024b7 | 378 | size_t *oldlenp; |
780d91b3 | 379 | void *newp; |
b48024b7 | 380 | size_t newlen; |
780d91b3 KM |
381 | char *str; |
382 | int maxlen; | |
383 | { | |
384 | int len, error = 0; | |
385 | ||
386 | len = strlen(str) + 1; | |
387 | if (oldp && *oldlenp < len) | |
388 | return (ENOMEM); | |
389 | if (newp && newlen >= maxlen) | |
390 | return (EINVAL); | |
924ae1bd RC |
391 | if (oldp) { |
392 | *oldlenp = len; | |
780d91b3 | 393 | error = copyout(str, oldp, len); |
924ae1bd | 394 | } |
780d91b3 KM |
395 | if (error == 0 && newp) { |
396 | error = copyin(newp, str, newlen); | |
397 | str[newlen] = 0; | |
13bbbe63 | 398 | } |
8b24ca5d | 399 | return (error); |
4a24f1b0 MT |
400 | } |
401 | ||
780d91b3 KM |
402 | /* |
403 | * As above, but read-only. | |
404 | */ | |
405 | sysctl_rdstring(oldp, oldlenp, newp, str) | |
406 | void *oldp; | |
b48024b7 | 407 | size_t *oldlenp; |
780d91b3 KM |
408 | void *newp; |
409 | char *str; | |
410 | { | |
411 | int len, error = 0; | |
412 | ||
413 | len = strlen(str) + 1; | |
414 | if (oldp && *oldlenp < len) | |
415 | return (ENOMEM); | |
416 | if (newp) | |
417 | return (EPERM); | |
418 | *oldlenp = len; | |
419 | if (oldp) | |
420 | error = copyout(str, oldp, len); | |
421 | return (error); | |
422 | } | |
423 | ||
ab16dfd9 KM |
424 | /* |
425 | * Validate parameters and get old / set new parameters | |
426 | * for a structure oriented sysctl function. | |
427 | */ | |
428 | sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) | |
429 | void *oldp; | |
430 | size_t *oldlenp; | |
431 | void *newp; | |
432 | size_t newlen; | |
433 | void *sp; | |
434 | int len; | |
435 | { | |
436 | int error = 0; | |
437 | ||
438 | if (oldp && *oldlenp < len) | |
439 | return (ENOMEM); | |
440 | if (newp && newlen > len) | |
441 | return (EINVAL); | |
442 | if (oldp) { | |
443 | *oldlenp = len; | |
444 | error = copyout(sp, oldp, len); | |
445 | } | |
446 | if (error == 0 && newp) | |
447 | error = copyin(newp, sp, len); | |
448 | return (error); | |
449 | } | |
450 | ||
780d91b3 KM |
451 | /* |
452 | * Validate parameters and get old parameters | |
453 | * for a structure oriented sysctl function. | |
454 | */ | |
455 | sysctl_rdstruct(oldp, oldlenp, newp, sp, len) | |
456 | void *oldp; | |
b48024b7 KB |
457 | size_t *oldlenp; |
458 | void *newp, *sp; | |
780d91b3 KM |
459 | int len; |
460 | { | |
461 | int error = 0; | |
462 | ||
463 | if (oldp && *oldlenp < len) | |
464 | return (ENOMEM); | |
465 | if (newp) | |
466 | return (EPERM); | |
467 | *oldlenp = len; | |
468 | if (oldp) | |
469 | error = copyout(sp, oldp, len); | |
470 | return (error); | |
471 | } | |
472 | ||
473 | /* | |
474 | * Get file structures. | |
475 | */ | |
476 | sysctl_file(where, sizep) | |
477 | char *where; | |
b48024b7 | 478 | size_t *sizep; |
780d91b3 KM |
479 | { |
480 | int buflen, error; | |
481 | struct file *fp; | |
482 | char *start = where; | |
483 | ||
484 | buflen = *sizep; | |
485 | if (where == NULL) { | |
486 | /* | |
487 | * overestimate by 10 files | |
488 | */ | |
489 | *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); | |
490 | return (0); | |
491 | } | |
492 | ||
493 | /* | |
494 | * first copyout filehead | |
495 | */ | |
496 | if (buflen < sizeof(filehead)) { | |
497 | *sizep = 0; | |
498 | return (0); | |
499 | } | |
500 | if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) | |
501 | return (error); | |
502 | buflen += sizeof(filehead); | |
503 | where += sizeof(filehead); | |
504 | ||
505 | /* | |
506 | * followed by an array of file structures | |
507 | */ | |
508 | for (fp = filehead; fp != NULL; fp = fp->f_filef) { | |
509 | if (buflen < sizeof(struct file)) { | |
510 | *sizep = where - start; | |
511 | return (ENOMEM); | |
512 | } | |
513 | if (error = copyout((caddr_t)fp, where, sizeof (struct file))) | |
514 | return (error); | |
515 | buflen -= sizeof(struct file); | |
516 | where += sizeof(struct file); | |
517 | } | |
518 | *sizep = where - start; | |
519 | return (0); | |
520 | } | |
521 | ||
ab16dfd9 KM |
522 | /* |
523 | * try over estimating by 5 procs | |
4a24f1b0 | 524 | */ |
780d91b3 | 525 | #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) |
4a24f1b0 | 526 | |
780d91b3 KM |
527 | sysctl_doproc(name, namelen, where, sizep) |
528 | int *name; | |
b48024b7 | 529 | u_int namelen; |
4a24f1b0 | 530 | char *where; |
b48024b7 | 531 | size_t *sizep; |
4a24f1b0 MT |
532 | { |
533 | register struct proc *p; | |
a65b44f0 | 534 | register struct kinfo_proc *dp = (struct kinfo_proc *)where; |
780d91b3 KM |
535 | register int needed = 0; |
536 | int buflen = where != NULL ? *sizep : 0; | |
4a24f1b0 | 537 | int doingzomb; |
7747bd3b | 538 | struct eproc eproc; |
4a24f1b0 MT |
539 | int error = 0; |
540 | ||
e9c7de58 | 541 | if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) |
780d91b3 | 542 | return (EINVAL); |
80a8e5e6 | 543 | p = (struct proc *)allproc; |
4a24f1b0 MT |
544 | doingzomb = 0; |
545 | again: | |
546 | for (; p != NULL; p = p->p_nxt) { | |
02ea4076 KM |
547 | /* |
548 | * Skip embryonic processes. | |
549 | */ | |
550 | if (p->p_stat == SIDL) | |
551 | continue; | |
ab16dfd9 | 552 | /* |
4a24f1b0 | 553 | * TODO - make more efficient (see notes below). |
ab16dfd9 | 554 | * do by session. |
4a24f1b0 | 555 | */ |
780d91b3 | 556 | switch (name[0]) { |
4a24f1b0 | 557 | |
780d91b3 | 558 | case KERN_PROC_PID: |
4a24f1b0 | 559 | /* could do this with just a lookup */ |
780d91b3 | 560 | if (p->p_pid != (pid_t)name[1]) |
4a24f1b0 MT |
561 | continue; |
562 | break; | |
563 | ||
780d91b3 | 564 | case KERN_PROC_PGRP: |
4a24f1b0 | 565 | /* could do this by traversing pgrp */ |
780d91b3 | 566 | if (p->p_pgrp->pg_id != (pid_t)name[1]) |
4a24f1b0 MT |
567 | continue; |
568 | break; | |
569 | ||
780d91b3 | 570 | case KERN_PROC_TTY: |
ab16dfd9 | 571 | if ((p->p_flag&SCTTY) == 0 || |
4a24f1b0 | 572 | p->p_session->s_ttyp == NULL || |
780d91b3 | 573 | p->p_session->s_ttyp->t_dev != (dev_t)name[1]) |
4a24f1b0 MT |
574 | continue; |
575 | break; | |
576 | ||
780d91b3 KM |
577 | case KERN_PROC_UID: |
578 | if (p->p_ucred->cr_uid != (uid_t)name[1]) | |
4a24f1b0 MT |
579 | continue; |
580 | break; | |
581 | ||
780d91b3 KM |
582 | case KERN_PROC_RUID: |
583 | if (p->p_cred->p_ruid != (uid_t)name[1]) | |
4a24f1b0 MT |
584 | continue; |
585 | break; | |
586 | } | |
780d91b3 | 587 | if (buflen >= sizeof(struct kinfo_proc)) { |
32041eb1 | 588 | fill_eproc(p, &eproc); |
ab16dfd9 | 589 | if (error = copyout((caddr_t)p, &dp->kp_proc, |
780d91b3 | 590 | sizeof(struct proc))) |
4a24f1b0 | 591 | return (error); |
ab16dfd9 | 592 | if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, |
780d91b3 | 593 | sizeof(eproc))) |
4a24f1b0 | 594 | return (error); |
a65b44f0 | 595 | dp++; |
780d91b3 | 596 | buflen -= sizeof(struct kinfo_proc); |
4a24f1b0 | 597 | } |
780d91b3 | 598 | needed += sizeof(struct kinfo_proc); |
4a24f1b0 MT |
599 | } |
600 | if (doingzomb == 0) { | |
601 | p = zombproc; | |
602 | doingzomb++; | |
603 | goto again; | |
604 | } | |
780d91b3 KM |
605 | if (where != NULL) { |
606 | *sizep = (caddr_t)dp - where; | |
607 | if (needed > *sizep) | |
608 | return (ENOMEM); | |
609 | } else { | |
610 | needed += KERN_PROCSLOP; | |
611 | *sizep = needed; | |
612 | } | |
4a24f1b0 MT |
613 | return (0); |
614 | } | |
32041eb1 MK |
615 | |
616 | /* | |
617 | * Fill in an eproc structure for the specified process. | |
618 | */ | |
619 | void | |
620 | fill_eproc(p, ep) | |
621 | register struct proc *p; | |
622 | register struct eproc *ep; | |
623 | { | |
624 | register struct tty *tp; | |
625 | ||
626 | ep->e_paddr = p; | |
627 | ep->e_sess = p->p_pgrp->pg_session; | |
628 | ep->e_pcred = *p->p_cred; | |
629 | ep->e_ucred = *p->p_ucred; | |
13bbbe63 CT |
630 | if (p->p_stat == SIDL || p->p_stat == SZOMB) { |
631 | ep->e_vm.vm_rssize = 0; | |
632 | ep->e_vm.vm_tsize = 0; | |
633 | ep->e_vm.vm_dsize = 0; | |
634 | ep->e_vm.vm_ssize = 0; | |
635 | #ifndef sparc | |
636 | /* ep->e_vm.vm_pmap = XXX; */ | |
637 | #endif | |
638 | } else { | |
639 | register struct vmspace *vm = p->p_vmspace; | |
640 | ||
641 | ep->e_vm.vm_rssize = vm->vm_rssize; | |
642 | ep->e_vm.vm_tsize = vm->vm_tsize; | |
643 | ep->e_vm.vm_dsize = vm->vm_dsize; | |
644 | ep->e_vm.vm_ssize = vm->vm_ssize; | |
645 | #ifndef sparc | |
646 | ep->e_vm.vm_pmap = vm->vm_pmap; | |
647 | #endif | |
648 | } | |
31c481fa MK |
649 | if (p->p_pptr) |
650 | ep->e_ppid = p->p_pptr->p_pid; | |
651 | else | |
652 | ep->e_ppid = 0; | |
32041eb1 MK |
653 | ep->e_pgid = p->p_pgrp->pg_id; |
654 | ep->e_jobc = p->p_pgrp->pg_jobc; | |
ab16dfd9 | 655 | if ((p->p_flag&SCTTY) && |
32041eb1 MK |
656 | (tp = ep->e_sess->s_ttyp)) { |
657 | ep->e_tdev = tp->t_dev; | |
51d82109 | 658 | ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; |
32041eb1 MK |
659 | ep->e_tsess = tp->t_session; |
660 | } else | |
661 | ep->e_tdev = NODEV; | |
662 | ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; | |
663 | if (SESS_LEADER(p)) | |
664 | ep->e_flag |= EPROC_SLEADER; | |
665 | if (p->p_wmesg) | |
666 | strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); | |
667 | ep->e_xsize = ep->e_xrssize = 0; | |
668 | ep->e_xccount = ep->e_xswrss = 0; | |
669 | } | |
318784c4 | 670 | |
780d91b3 | 671 | #ifdef COMPAT_43 |
780d91b3 | 672 | #include <sys/socket.h> |
1fa29dab KM |
673 | #define KINFO_PROC (0<<8) |
674 | #define KINFO_RT (1<<8) | |
675 | #define KINFO_VNODE (2<<8) | |
676 | #define KINFO_FILE (3<<8) | |
677 | #define KINFO_METER (4<<8) | |
678 | #define KINFO_LOADAVG (5<<8) | |
679 | #define KINFO_CLOCKRATE (6<<8) | |
780d91b3 KM |
680 | |
681 | struct getkerninfo_args { | |
682 | int op; | |
683 | char *where; | |
684 | int *size; | |
685 | int arg; | |
686 | }; | |
687 | ||
7e024c88 | 688 | ogetkerninfo(p, uap, retval) |
780d91b3 KM |
689 | struct proc *p; |
690 | register struct getkerninfo_args *uap; | |
691 | int *retval; | |
318784c4 | 692 | { |
780d91b3 KM |
693 | int error, name[5]; |
694 | u_int size; | |
318784c4 | 695 | |
358fe79a | 696 | if (uap->size && |
b48024b7 | 697 | (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) |
780d91b3 | 698 | return (error); |
318784c4 | 699 | |
1fa29dab | 700 | switch (uap->op & 0xff00) { |
318784c4 | 701 | |
780d91b3 KM |
702 | case KINFO_RT: |
703 | name[0] = PF_ROUTE; | |
704 | name[1] = 0; | |
705 | name[2] = (uap->op & 0xff0000) >> 16; | |
706 | name[3] = uap->op & 0xff; | |
707 | name[4] = uap->arg; | |
0f1d36b0 | 708 | error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); |
780d91b3 | 709 | break; |
318784c4 | 710 | |
780d91b3 KM |
711 | case KINFO_VNODE: |
712 | name[0] = KERN_VNODE; | |
0f1d36b0 | 713 | error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
714 | break; |
715 | ||
716 | case KINFO_PROC: | |
717 | name[0] = KERN_PROC; | |
718 | name[1] = uap->op & 0xff; | |
719 | name[2] = uap->arg; | |
0f1d36b0 | 720 | error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
721 | break; |
722 | ||
723 | case KINFO_FILE: | |
724 | name[0] = KERN_FILE; | |
0f1d36b0 | 725 | error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
726 | break; |
727 | ||
728 | case KINFO_METER: | |
729 | name[0] = VM_METER; | |
0f1d36b0 | 730 | error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
731 | break; |
732 | ||
733 | case KINFO_LOADAVG: | |
734 | name[0] = VM_LOADAVG; | |
0f1d36b0 | 735 | error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
736 | break; |
737 | ||
738 | case KINFO_CLOCKRATE: | |
739 | name[0] = KERN_CLOCKRATE; | |
0f1d36b0 | 740 | error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); |
780d91b3 KM |
741 | break; |
742 | ||
743 | default: | |
0f1d36b0 | 744 | return (EOPNOTSUPP); |
780d91b3 KM |
745 | } |
746 | if (error) | |
747 | return (error); | |
748 | *retval = size; | |
358fe79a KM |
749 | if (uap->size) |
750 | error = copyout((caddr_t)&size, (caddr_t)uap->size, | |
751 | sizeof(size)); | |
752 | return (error); | |
318784c4 | 753 | } |
780d91b3 | 754 | #endif /* COMPAT_43 */ |