xref: /minix/minix/lib/libc/sys/__sysctl.c (revision b89261ba)
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
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