1 #include <sys/cdefs.h>
2 #include <lib.h>
3 #include "namespace.h"
4 #include "extern.h"
5 #include <string.h>
6
7 /*
8 * The sysctl(2) system call, handled by the MIB service.
9 */
10 int
__sysctl(const int * name,unsigned int namelen,void * oldp,size_t * oldlenp,const void * newp,size_t newlen)11 __sysctl(const int * name, unsigned int namelen, void * oldp, size_t * oldlenp,
12 const void * newp, size_t newlen)
13 {
14 message m;
15 int r;
16
17 memset(&m, 0, sizeof(m));
18 m.m_lc_mib_sysctl.oldp = (vir_bytes)oldp;
19 m.m_lc_mib_sysctl.oldlen = (oldlenp != NULL) ? *oldlenp : 0;
20 m.m_lc_mib_sysctl.newp = (vir_bytes)newp;
21 m.m_lc_mib_sysctl.newlen = newlen;
22 m.m_lc_mib_sysctl.namelen = namelen;
23 m.m_lc_mib_sysctl.namep = (vir_bytes)name;
24 if (namelen <= CTL_SHORTNAME)
25 memcpy(m.m_lc_mib_sysctl.name, name, sizeof(*name) * namelen);
26
27 r = _syscall(MIB_PROC_NR, MIB_SYSCTL, &m);
28
29 /*
30 * We copy the NetBSD behavior of replying with the old length also if
31 * the call failed, typically with ENOMEM. This is undocumented
32 * behavior, but unfortunately relied on by sysctl(8) and other NetBSD
33 * userland code. If the call failed at the IPC level, the resulting
34 * value will be garbage, but it should then not be used anyway.
35 */
36 if (oldlenp != NULL)
37 *oldlenp = m.m_mib_lc_sysctl.oldlen;
38
39 return r;
40 }
41