2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1982, 1986, 1989, 1993
24 * The Regents of the University of California. All rights reserved.
26 * This code is derived from software contributed to Berkeley by
27 * Mike Karels at Berkeley Software Design, Inc.
29 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
30 * project, to make these variables more userfriendly.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
64 #include <sys/param.h>
66 #include <sys/kernel.h>
67 #include <sys/sysctl.h>
68 #include <sys/malloc.h>
70 #include <sys/systm.h>
73 struct sysctl_oid_list sysctl__debug_children;
74 struct sysctl_oid_list sysctl__kern_children;
75 struct sysctl_oid_list sysctl__net_children;
76 struct sysctl_oid_list sysctl__sysctl_children;
79 extern struct sysctl_oid
*newsysctl_list
[];
83 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
);
90 static struct sysctl_lock
{
96 static int sysctl_root SYSCTL_HANDLER_ARGS
;
98 struct sysctl_oid_list sysctl__children
; /* root list */
101 * Initialization of the MIB tree.
103 * Order by number in each list.
106 void sysctl_register_oid(struct sysctl_oid
*oidp
)
108 struct sysctl_oid_list
*parent
= oidp
->oid_parent
;
109 struct sysctl_oid
*p
;
110 struct sysctl_oid
*q
;
114 * If this oid has a number OID_AUTO, give it a number which
115 * is greater than any current oid. Make sure it is at least
116 * 100 to leave space for pre-assigned oid numbers.
118 /* sysctl_sysctl_debug_dump_node(parent, 3); */
119 if (oidp
->oid_number
== OID_AUTO
) {
120 /* First, find the highest oid in the parent list >99 */
122 SLIST_FOREACH(p
, parent
, oid_link
) {
123 if (p
->oid_number
> n
)
126 oidp
->oid_number
= n
+ 1;
130 * Insert the oid into the parent's list in order.
133 SLIST_FOREACH(p
, parent
, oid_link
) {
134 if (oidp
->oid_number
< p
->oid_number
)
139 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
141 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
144 void sysctl_unregister_oid(struct sysctl_oid
*oidp
)
146 SLIST_REMOVE(oidp
->oid_parent
, oidp
, sysctl_oid
, oid_link
);
150 * Bulk-register all the oids in a linker_set.
152 void sysctl_register_set(struct linker_set
*lsp
)
154 int count
= lsp
->ls_length
;
156 for (i
= 0; i
< count
; i
++)
157 sysctl_register_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
160 void sysctl_unregister_set(struct linker_set
*lsp
)
162 int count
= lsp
->ls_length
;
164 for (i
= 0; i
< count
; i
++)
165 sysctl_unregister_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
170 * Register OID's from fixed list
173 void sysctl_register_fixed()
178 while (newsysctl_list
[i
]) {
179 /* printf("Registering %d\n", i); */
180 sysctl_register_oid(newsysctl_list
[i
++]);
185 * Register the kernel's oids on startup.
187 struct linker_set sysctl_set
;
189 void sysctl_register_all(void *arg
)
191 sysctl_register_set(&sysctl_set
);
194 SYSINIT(sysctl
, SI_SUB_KMEM
, SI_ORDER_ANY
, sysctl_register_all
, 0);
199 * These functions implement a presently undocumented interface
200 * used by the sysctl program to walk the tree, and get the type
201 * so it can print the value.
202 * This interface is under work and consideration, and should probably
203 * be killed with a big axe by the first person who can find the time.
204 * (be aware though, that the proper interface isn't as obvious as it
205 * may seem, there are various conflicting requirements.
207 * {0,0} printf the entire MIB-tree.
208 * {0,1,...} return the name of the "..." OID.
209 * {0,2,...} return the next OID.
210 * {0,3} return the OID of the name in "new"
211 * {0,4,...} return the kind & format info for the "..." OID.
215 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
218 struct sysctl_oid
*oidp
;
220 SLIST_FOREACH(oidp
, l
, oid_link
) {
225 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
228 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
229 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
231 if (oidp
->oid_handler
)
234 switch (oidp
->oid_kind
& CTLTYPE
) {
237 if (!oidp
->oid_handler
) {
238 sysctl_sysctl_debug_dump_node(
239 oidp
->oid_arg1
, i
+2);
242 case CTLTYPE_INT
: printf(" Int\n"); break;
243 case CTLTYPE_STRING
: printf(" String\n"); break;
244 case CTLTYPE_QUAD
: printf(" Quad\n"); break;
245 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
246 default: printf("\n");
253 sysctl_sysctl_debug SYSCTL_HANDLER_ARGS
255 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
259 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
,
260 0, 0, sysctl_sysctl_debug
, "-", "");
263 sysctl_sysctl_name SYSCTL_HANDLER_ARGS
265 int *name
= (int *) arg1
;
266 u_int namelen
= arg2
;
268 struct sysctl_oid
*oid
;
269 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
274 snprintf(buf
,sizeof(buf
),"%d",*name
);
276 error
= SYSCTL_OUT(req
, ".", 1);
278 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
286 SLIST_FOREACH(oid
, lsp
, oid_link
) {
287 if (oid
->oid_number
!= *name
)
291 error
= SYSCTL_OUT(req
, ".", 1);
293 error
= SYSCTL_OUT(req
, oid
->oid_name
,
294 strlen(oid
->oid_name
));
301 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
304 if (oid
->oid_handler
)
307 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
312 return (SYSCTL_OUT(req
, "", 1));
315 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
, sysctl_sysctl_name
, "");
318 sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
319 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
321 struct sysctl_oid
*oidp
;
324 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
325 *next
= oidp
->oid_number
;
329 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
331 if (oidp
->oid_handler
)
332 /* We really should call the handler here...*/
334 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
335 if (!sysctl_sysctl_next_ls (lsp
, 0, 0, next
+1,
336 len
, level
+1, oidpp
))
341 if (oidp
->oid_number
< *name
)
344 if (oidp
->oid_number
> *name
) {
345 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
347 if (oidp
->oid_handler
)
349 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
350 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1,
351 next
+1, len
, level
+1, oidpp
))
355 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
358 if (oidp
->oid_handler
)
361 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
362 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1, next
+1,
363 len
, level
+1, oidpp
))
373 sysctl_sysctl_next SYSCTL_HANDLER_ARGS
375 int *name
= (int *) arg1
;
376 u_int namelen
= arg2
;
378 struct sysctl_oid
*oid
;
379 struct sysctl_oid_list
*lsp
= &sysctl__children
;
380 int newoid
[CTL_MAXNAME
];
382 i
= sysctl_sysctl_next_ls (lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
385 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
389 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
, sysctl_sysctl_next
, "");
392 name2oid (char *name
, int *oid
, int *len
, struct sysctl_oid
**oidpp
)
395 struct sysctl_oid
*oidp
;
396 struct sysctl_oid_list
*lsp
= &sysctl__children
;
402 p
= name
+ strlen(name
) - 1 ;
408 for (p
= name
; *p
&& *p
!= '.'; p
++)
414 oidp
= SLIST_FIRST(lsp
);
416 while (oidp
&& *len
< CTL_MAXNAME
) {
417 if (strcmp(name
, oidp
->oid_name
)) {
418 oidp
= SLIST_NEXT(oidp
, oid_link
);
421 *oid
++ = oidp
->oid_number
;
430 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
433 if (oidp
->oid_handler
)
436 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
437 oidp
= SLIST_FIRST(lsp
);
439 for (p
= name
; *p
&& *p
!= '.'; p
++)
449 sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS
452 int error
, oid
[CTL_MAXNAME
], len
;
453 struct sysctl_oid
*op
= 0;
457 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
458 return (ENAMETOOLONG
);
460 p
= _MALLOC(req
->newlen
+1, M_TEMP
, M_WAITOK
);
465 error
= SYSCTL_IN(req
, p
, req
->newlen
);
471 p
[req
->newlen
] = '\0';
473 error
= name2oid(p
, oid
, &len
, &op
);
480 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
484 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
|CTLFLAG_ANYBODY
, 0, 0,
485 sysctl_sysctl_name2oid
, "I", "");
488 sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS
490 int *name
= (int *) arg1
, error
;
491 u_int namelen
= arg2
;
493 struct sysctl_oid
*oid
;
494 struct sysctl_oid_list
*lsp
= &sysctl__children
;
496 oid
= SLIST_FIRST(lsp
);
499 while (oid
&& indx
< CTL_MAXNAME
) {
500 if (oid
->oid_number
== name
[indx
]) {
502 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
503 if (oid
->oid_handler
)
507 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
508 oid
= SLIST_FIRST(lsp
);
515 oid
= SLIST_NEXT(oid
, oid_link
);
522 error
= SYSCTL_OUT(req
,
523 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
525 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
526 strlen(oid
->oid_fmt
)+1);
531 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
, sysctl_sysctl_oidfmt
, "");
534 * Default "handler" functions.
538 * Handle an int, signed or unsigned.
540 * a variable: point arg1 at it.
541 * a constant: pass it in arg2.
545 sysctl_handle_int SYSCTL_HANDLER_ARGS
550 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
552 error
= SYSCTL_OUT(req
, &arg2
, sizeof(int));
554 if (error
|| !req
->newptr
)
560 error
= SYSCTL_IN(req
, arg1
, sizeof(int));
565 * Handle a long, signed or unsigned. arg1 points to it.
569 sysctl_handle_long SYSCTL_HANDLER_ARGS
575 error
= SYSCTL_OUT(req
, arg1
, sizeof(long));
577 if (error
|| !req
->newptr
)
580 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
585 * Handle our generic '\0' terminated 'C' string.
587 * a variable string: point arg1 at it, arg2 is max length.
588 * a constant string: point arg1 at it, arg2 is zero.
592 sysctl_handle_string SYSCTL_HANDLER_ARGS
596 error
= SYSCTL_OUT(req
, arg1
, strlen((char *)arg1
)+1);
598 if (error
|| !req
->newptr
)
601 if ((req
->newlen
- req
->newidx
) >= arg2
) {
604 arg2
= (req
->newlen
- req
->newidx
);
605 error
= SYSCTL_IN(req
, arg1
, arg2
);
606 ((char *)arg1
)[arg2
] = '\0';
613 * Handle any kind of opaque data.
614 * arg1 points to it, arg2 is the size.
618 sysctl_handle_opaque SYSCTL_HANDLER_ARGS
622 error
= SYSCTL_OUT(req
, arg1
, arg2
);
624 if (error
|| !req
->newptr
)
627 error
= SYSCTL_IN(req
, arg1
, arg2
);
633 * Transfer functions to/from kernel space.
634 * XXX: rather untested at this point
637 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
644 if (i
> req
->oldlen
- req
->oldidx
)
645 i
= req
->oldlen
- req
->oldidx
;
647 error
= copyout(p
, (char *)req
->oldptr
+ req
->oldidx
, i
);
653 if (req
->oldptr
&& i
!= l
)
659 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
663 if (req
->newlen
- req
->newidx
< l
)
665 copyin((char *)req
->newptr
+ req
->newidx
, p
, l
);
671 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
, size_t *retval
)
674 struct sysctl_req req
;
676 bzero(&req
, sizeof req
);
681 req
.oldlen
= *oldlenp
;
693 req
.oldfunc
= sysctl_old_kernel
;
694 req
.newfunc
= sysctl_new_kernel
;
697 /* XXX this should probably be done in a general way */
698 while (memlock
.sl_lock
) {
700 (void) tsleep((caddr_t
)&memlock
, PRIBIO
+1, "sysctl", 0);
705 error
= sysctl_root(0, name
, namelen
, &req
);
708 vsunlock(req
.oldptr
, req
.oldlen
, B_WRITE
);
712 if (memlock
.sl_want
) {
714 wakeup((caddr_t
)&memlock
);
717 if (error
&& error
!= ENOMEM
)
721 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
722 *retval
= req
.oldlen
;
724 *retval
= req
.oldidx
;
730 * Transfer function to/from user space.
733 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
739 if (req
->oldlen
- req
->oldidx
< l
)
742 if (i
> req
->oldlen
- req
->oldidx
)
743 i
= req
->oldlen
- req
->oldidx
;
745 error
= copyout(p
, (char *)req
->oldptr
+ req
->oldidx
,
751 if (req
->oldptr
&& i
< l
)
757 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
763 if (req
->newlen
- req
->newidx
< l
)
765 error
= copyin((char *)req
->newptr
+ req
->newidx
, p
, l
);
771 * Traverse our tree, and find the right node, execute whatever it points
772 * at, and return the resulting error code.
776 sysctl_root SYSCTL_HANDLER_ARGS
778 int *name
= (int *) arg1
;
779 u_int namelen
= arg2
;
781 struct sysctl_oid
*oid
;
782 struct sysctl_oid_list
*lsp
= &sysctl__children
;
785 oid
= SLIST_FIRST(lsp
);
788 while (oid
&& indx
< CTL_MAXNAME
) {
789 if (oid
->oid_number
== name
[indx
]) {
791 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
793 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
794 if (oid
->oid_handler
)
798 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
799 oid
= SLIST_FIRST(lsp
);
806 oid
= SLIST_NEXT(oid
, oid_link
);
811 /* If writing isn't allowed */
812 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
813 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
817 /* Most likely only root can write */
818 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
819 req
->newptr
&& req
->p
&&
820 (error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
)))
823 if (!oid
->oid_handler
) {
828 * Switch to the NETWORK funnel for CTL_NET and KERN_IPC sysctls
831 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
832 (name
[1] == KERN_IPC
))))
833 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
835 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
836 i
= (oid
->oid_handler
) (oid
,
837 name
+ indx
, namelen
- indx
,
840 i
= (oid
->oid_handler
) (oid
,
841 oid
->oid_arg1
, oid
->oid_arg2
,
846 * Switch back to the KERNEL funnel, if necessary
849 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
850 (name
[1] == KERN_IPC
))))
851 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
856 #ifndef _SYS_SYSPROTO_H_
868 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
869 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
871 int error
, i
, name
[CTL_MAXNAME
];
874 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
877 error
= copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int));
881 error
= userland_sysctl(p
, name
, uap
->namelen
,
882 uap
->old
, uap
->oldlenp
, 0,
883 uap
->new, uap
->newlen
, &j
);
884 if (error
&& error
!= ENOMEM
)
887 i
= copyout(&j
, uap
->oldlenp
, sizeof(j
));
895 * This is used from various compatibility syscalls too. That's why name
896 * must be in kernel space.
899 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, int inkernel
, void *new, size_t newlen
, size_t *retval
)
902 struct sysctl_req req
, req2
;
904 bzero(&req
, sizeof req
);
910 req
.oldlen
= *oldlenp
;
912 error
= copyin(oldlenp
, &req
.oldlen
, sizeof(*oldlenp
));
927 req
.oldfunc
= sysctl_old_user
;
928 req
.newfunc
= sysctl_new_user
;
933 error
= sysctl_root(0, name
, namelen
, &req2
);
934 } while (error
== EAGAIN
);
938 if (error
&& error
!= ENOMEM
)
942 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
943 *retval
= req
.oldlen
;
945 *retval
= req
.oldidx
;
952 #include <sys/socket.h>
953 #include <vm/vm_param.h>
955 #define KINFO_PROC (0<<8)
956 #define KINFO_RT (1<<8)
957 #define KINFO_VNODE (2<<8)
958 #define KINFO_FILE (3<<8)
959 #define KINFO_METER (4<<8)
960 #define KINFO_LOADAVG (5<<8)
961 #define KINFO_CLOCKRATE (6<<8)
963 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
964 #define KINFO_BSDI_SYSINFO (101<<8)
967 * XXX this is bloat, but I hope it's better here than on the potentially
968 * limited kernel stack... -Peter
972 int bsdi_machine
; /* "i386" on BSD/386 */
973 /* ^^^ this is an offset to the string, relative to the struct start */
982 int bsdi_ostype
; /* "BSD/386" on BSD/386 */
983 int bsdi_osrelease
; /* "1.1" on BSD/386 */
995 struct timeval pad16
;
996 /* we dont set this, because BSDI's uname used gethostname() instead */
997 int bsdi_hostname
; /* hostname on BSD/386 */
999 /* the actual string data is appended here */
1003 * this data is appended to the end of the bsdi_si structure during copyout.
1004 * The "char *" offsets are relative to the base of the bsdi_si struct.
1005 * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
1006 * should not exceed the length of the buffer here... (or else!! :-)
1008 static char bsdi_strings
[80]; /* It had better be less than this! */
1010 #ifndef _SYS_SYSPROTO_H_
1011 struct getkerninfo_args
{
1020 ogetkerninfo(struct proc
*p
, struct getkerninfo_args
*uap
)
1025 switch (uap
->op
& 0xff00) {
1031 name
[3] = (uap
->op
& 0xff0000) >> 16;
1032 name
[4] = uap
->op
& 0xff;
1034 error
= userland_sysctl(p
, name
, 6, uap
->where
, uap
->size
,
1040 name
[1] = KERN_VNODE
;
1041 error
= userland_sysctl(p
, name
, 2, uap
->where
, uap
->size
,
1047 name
[1] = KERN_PROC
;
1048 name
[2] = uap
->op
& 0xff;
1050 error
= userland_sysctl(p
, name
, 4, uap
->where
, uap
->size
,
1056 name
[1] = KERN_FILE
;
1057 error
= userland_sysctl(p
, name
, 2, uap
->where
, uap
->size
,
1064 error
= userland_sysctl(p
, name
, 2, uap
->where
, uap
->size
,
1070 name
[1] = VM_LOADAVG
;
1071 error
= userland_sysctl(p
, name
, 2, uap
->where
, uap
->size
,
1075 case KINFO_CLOCKRATE
:
1077 name
[1] = KERN_CLOCKRATE
;
1078 error
= userland_sysctl(p
, name
, 2, uap
->where
, uap
->size
,
1082 case KINFO_BSDI_SYSINFO
: {
1084 * this is pretty crude, but it's just enough for uname()
1085 * from BSDI's 1.x libc to work.
1087 * In particular, it doesn't return the same results when
1088 * the supplied buffer is too small. BSDI's version apparently
1089 * will return the amount copied, and set the *size to how
1090 * much was needed. The emulation framework here isn't capable
1091 * of that, so we just set both to the amount copied.
1092 * BSDI's 2.x product apparently fails with ENOMEM in this
1100 bzero((char *)&bsdi_si
, sizeof(bsdi_si
));
1101 bzero(bsdi_strings
, sizeof(bsdi_strings
));
1105 bsdi_si
.bsdi_ostype
= (s
- bsdi_strings
) + sizeof(bsdi_si
);
1109 bsdi_si
.bsdi_osrelease
= (s
- bsdi_strings
) + sizeof(bsdi_si
);
1110 strcpy(s
, osrelease
);
1113 bsdi_si
.bsdi_machine
= (s
- bsdi_strings
) + sizeof(bsdi_si
);
1117 needed
= sizeof(bsdi_si
) + (s
- bsdi_strings
);
1119 if (uap
->where
== NULL
) {
1120 /* process is asking how much buffer to supply.. */
1127 /* if too much buffer supplied, trim it down */
1131 /* how much of the buffer is remaining */
1134 if ((error
= copyout((char *)&bsdi_si
, uap
->where
, left
)) != 0)
1137 /* is there any point in continuing? */
1138 if (left
> sizeof(bsdi_si
)) {
1139 left
-= sizeof(bsdi_si
);
1140 error
= copyout(&bsdi_strings
,
1141 uap
->where
+ sizeof(bsdi_si
), left
);
1147 return (EOPNOTSUPP
);
1151 p
->p_retval
[0] = size
;
1153 error
= copyout((caddr_t
)&size
, (caddr_t
)uap
->size
,
1157 #endif /* COMPAT_43 */