xref: /netbsd-src/lib/libc/gen/sysconf.c (revision cac8e449158efc7261bebc8657cbb0125a2cfdde)
1 /*	$NetBSD: sysconf.c,v 1.32 2008/06/25 11:46:12 ad Exp $	*/
2 
3 /*-
4  * Copyright (c) 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Sean Eric Fagan of Cygnus Support.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 #if defined(LIBC_SCCS) && !defined(lint)
37 #if 0
38 static char sccsid[] = "@(#)sysconf.c	8.2 (Berkeley) 3/20/94";
39 #else
40 __RCSID("$NetBSD: sysconf.c,v 1.32 2008/06/25 11:46:12 ad Exp $");
41 #endif
42 #endif /* LIBC_SCCS and not lint */
43 
44 #include "namespace.h"
45 #include <sys/param.h>
46 #include <sys/sysctl.h>
47 #include <sys/time.h>
48 #include <sys/resource.h>
49 
50 #include <errno.h>
51 #include <limits.h>
52 #include <time.h>
53 #include <unistd.h>
54 #include <paths.h>
55 
56 #ifdef __weak_alias
57 __weak_alias(sysconf,__sysconf)
58 #endif
59 
60 /*
61  * sysconf --
62  *	get configurable system variables.
63  *
64  * XXX
65  * POSIX 1003.1 (ISO/IEC 9945-1, 4.8.1.3) states that the variable values
66  * not change during the lifetime of the calling process.  This would seem
67  * to require that any change to system limits kill all running processes.
68  * A workaround might be to cache the values when they are first retrieved
69  * and then simply return the cached value on subsequent calls.  This is
70  * less useful than returning up-to-date values, however.
71  */
72 long
73 sysconf(int name)
74 {
75 	struct rlimit rl;
76 	size_t len;
77 	int mib[CTL_MAXNAME], value;
78 	unsigned int mib_len;
79 	struct clockinfo tmpclock;
80 	static int clk_tck;
81 
82 	len = sizeof(value);
83 
84 	/* Default length of the MIB */
85 	mib_len = 2;
86 
87 	switch (name) {
88 
89 /* 1003.1 */
90 	case _SC_ARG_MAX:
91 		mib[0] = CTL_KERN;
92 		mib[1] = KERN_ARGMAX;
93 		break;
94 	case _SC_CHILD_MAX:
95 		return (getrlimit(RLIMIT_NPROC, &rl) ? -1 : (long)rl.rlim_cur);
96 	case _O_SC_CLK_TCK:
97 		/*
98 		 * For applications compiled when CLK_TCK was a compile-time
99 		 * constant.
100 		 */
101 		return 100;
102 	case _SC_CLK_TCK:
103 		/*
104 		 * Has to be handled specially because it returns a
105 		 * struct clockinfo instead of an integer. Also, since
106 		 * this might be called often by some things that
107 		 * don't grok CLK_TCK can be a macro expanding to a
108 		 * function, cache the value.
109 		 */
110 		if (clk_tck == 0) {
111 			mib[0] = CTL_KERN;
112 			mib[1] = KERN_CLOCKRATE;
113 			len = sizeof(struct clockinfo);
114 			clk_tck = sysctl(mib, 2, &tmpclock, &len, NULL, 0)
115 			    == -1 ? -1 : tmpclock.hz;
116 		}
117 		return(clk_tck);
118 	case _SC_JOB_CONTROL:
119 		mib[0] = CTL_KERN;
120 		mib[1] = KERN_JOB_CONTROL;
121 		goto yesno;
122 	case _SC_NGROUPS_MAX:
123 		mib[0] = CTL_KERN;
124 		mib[1] = KERN_NGROUPS;
125 		break;
126 	case _SC_OPEN_MAX:
127 		return (getrlimit(RLIMIT_NOFILE, &rl) ? -1 : (long)rl.rlim_cur);
128 	case _SC_STREAM_MAX:
129 		mib[0] = CTL_USER;
130 		mib[1] = USER_STREAM_MAX;
131 		break;
132 	case _SC_TZNAME_MAX:
133 		mib[0] = CTL_USER;
134 		mib[1] = USER_TZNAME_MAX;
135 		break;
136 	case _SC_SAVED_IDS:
137 		mib[0] = CTL_KERN;
138 		mib[1] = KERN_SAVED_IDS;
139 		goto yesno;
140 	case _SC_VERSION:
141 		mib[0] = CTL_KERN;
142 		mib[1] = KERN_POSIX1;
143 		break;
144 
145 /* 1003.1b */
146 	case _SC_PAGESIZE:
147 		return _getpagesize();
148 	case _SC_FSYNC:
149 		mib[0] = CTL_KERN;
150 		mib[1] = KERN_FSYNC;
151 		goto yesno;
152 	case _SC_SYNCHRONIZED_IO:
153 		mib[0] = CTL_KERN;
154 		mib[1] = KERN_SYNCHRONIZED_IO;
155 		goto yesno;
156 	case _SC_MAPPED_FILES:
157 		mib[0] = CTL_KERN;
158 		mib[1] = KERN_MAPPED_FILES;
159 		goto yesno;
160 	case _SC_MEMLOCK:
161 		mib[0] = CTL_KERN;
162 		mib[1] = KERN_MEMLOCK;
163 		goto yesno;
164 	case _SC_MEMLOCK_RANGE:
165 		mib[0] = CTL_KERN;
166 		mib[1] = KERN_MEMLOCK_RANGE;
167 		goto yesno;
168 	case _SC_MEMORY_PROTECTION:
169 		mib[0] = CTL_KERN;
170 		mib[1] = KERN_MEMORY_PROTECTION;
171 		goto yesno;
172 	case _SC_MONOTONIC_CLOCK:
173 		mib[0] = CTL_KERN;
174 		mib[1] = KERN_MONOTONIC_CLOCK;
175 		goto yesno;
176 	case _SC_SEMAPHORES:
177 		mib[0] = CTL_KERN;
178 		mib[1] = KERN_POSIX_SEMAPHORES;
179 		goto yesno;
180 	case _SC_TIMERS:
181 		mib[0] = CTL_KERN;
182 		mib[1] = KERN_POSIX_TIMERS;
183 		goto yesno;
184 
185 /* 1003.1c */
186 	case _SC_LOGIN_NAME_MAX:
187 		mib[0] = CTL_KERN;
188 		mib[1] = KERN_LOGIN_NAME_MAX;
189 		break;
190 	case _SC_THREADS:
191 		mib[0] = CTL_KERN;
192 		mib[1] = KERN_POSIX_THREADS;
193 		goto yesno;
194 
195 /* 1003.1j */
196 	case _SC_BARRIERS:
197 		mib[0] = CTL_KERN;
198 		mib[1] = KERN_POSIX_BARRIERS;
199 		goto yesno;
200 	case _SC_SPIN_LOCKS:
201 		mib[0] = CTL_KERN;
202 		mib[1] = KERN_POSIX_SPIN_LOCKS;
203 		goto yesno;
204 	/* Historical; Threads option in 1003.1-2001 */
205 	case _SC_READER_WRITER_LOCKS:
206 		mib[0] = CTL_KERN;
207 		mib[1] = KERN_POSIX_READER_WRITER_LOCKS;
208 		goto yesno;
209 
210 /* 1003.2 */
211 	case _SC_BC_BASE_MAX:
212 		mib[0] = CTL_USER;
213 		mib[1] = USER_BC_BASE_MAX;
214 		break;
215 	case _SC_BC_DIM_MAX:
216 		mib[0] = CTL_USER;
217 		mib[1] = USER_BC_DIM_MAX;
218 		break;
219 	case _SC_BC_SCALE_MAX:
220 		mib[0] = CTL_USER;
221 		mib[1] = USER_BC_SCALE_MAX;
222 		break;
223 	case _SC_BC_STRING_MAX:
224 		mib[0] = CTL_USER;
225 		mib[1] = USER_BC_STRING_MAX;
226 		break;
227 	case _SC_COLL_WEIGHTS_MAX:
228 		mib[0] = CTL_USER;
229 		mib[1] = USER_COLL_WEIGHTS_MAX;
230 		break;
231 	case _SC_EXPR_NEST_MAX:
232 		mib[0] = CTL_USER;
233 		mib[1] = USER_EXPR_NEST_MAX;
234 		break;
235 	case _SC_LINE_MAX:
236 		mib[0] = CTL_USER;
237 		mib[1] = USER_LINE_MAX;
238 		break;
239 	case _SC_RE_DUP_MAX:
240 		mib[0] = CTL_USER;
241 		mib[1] = USER_RE_DUP_MAX;
242 		break;
243 	case _SC_2_VERSION:
244 		mib[0] = CTL_USER;
245 		mib[1] = USER_POSIX2_VERSION;
246 		break;
247 	case _SC_2_C_BIND:
248 		mib[0] = CTL_USER;
249 		mib[1] = USER_POSIX2_C_BIND;
250 		goto yesno;
251 	case _SC_2_C_DEV:
252 		mib[0] = CTL_USER;
253 		mib[1] = USER_POSIX2_C_DEV;
254 		goto yesno;
255 	case _SC_2_CHAR_TERM:
256 		mib[0] = CTL_USER;
257 		mib[1] = USER_POSIX2_CHAR_TERM;
258 		goto yesno;
259 	case _SC_2_FORT_DEV:
260 		mib[0] = CTL_USER;
261 		mib[1] = USER_POSIX2_FORT_DEV;
262 		goto yesno;
263 	case _SC_2_FORT_RUN:
264 		mib[0] = CTL_USER;
265 		mib[1] = USER_POSIX2_FORT_RUN;
266 		goto yesno;
267 	case _SC_2_LOCALEDEF:
268 		mib[0] = CTL_USER;
269 		mib[1] = USER_POSIX2_LOCALEDEF;
270 		goto yesno;
271 	case _SC_2_SW_DEV:
272 		mib[0] = CTL_USER;
273 		mib[1] = USER_POSIX2_SW_DEV;
274 		goto yesno;
275 	case _SC_2_UPE:
276 		mib[0] = CTL_USER;
277 		mib[1] = USER_POSIX2_UPE;
278 		goto yesno;
279 
280 /* XPG 4.2 */
281 	case _SC_IOV_MAX:
282 		mib[0] = CTL_KERN;
283 		mib[1] = KERN_IOV_MAX;
284 		break;
285 	case _SC_XOPEN_SHM:
286 		mib[0] = CTL_KERN;
287 		mib[1] = KERN_SYSVIPC;
288 		mib[2] = KERN_SYSVIPC_SHM;
289 		mib_len = 3;
290 		goto yesno;
291 
292 /* 1003.1-2001, XSI Option Group */
293 	case _SC_AIO_LISTIO_MAX:
294 		if (sysctlgetmibinfo("kern.aio_listio_max", &mib[0], &mib_len,
295 		    NULL, NULL, NULL, SYSCTL_VERSION))
296 			return -1;
297 		break;
298 	case _SC_AIO_MAX:
299 		if (sysctlgetmibinfo("kern.aio_max", &mib[0], &mib_len,
300 		    NULL, NULL, NULL, SYSCTL_VERSION))
301 			return -1;
302 		break;
303 	case _SC_ASYNCHRONOUS_IO:
304 		if (sysctlgetmibinfo("kern.posix_aio", &mib[0], &mib_len,
305 		    NULL, NULL, NULL, SYSCTL_VERSION))
306 			return -1;
307 		goto yesno;
308 	case _SC_MESSAGE_PASSING:
309 		if (sysctlgetmibinfo("kern.posix_msg", &mib[0], &mib_len,
310 		    NULL, NULL, NULL, SYSCTL_VERSION))
311 			return -1;
312 		goto yesno;
313 	case _SC_MQ_OPEN_MAX:
314 		if (sysctlgetmibinfo("kern.mqueue.mq_open_max", &mib[0],
315 		    &mib_len, NULL, NULL, NULL, SYSCTL_VERSION))
316 			return -1;
317 		break;
318 	case _SC_MQ_PRIO_MAX:
319 		if (sysctlgetmibinfo("kern.mqueue.mq_prio_max", &mib[0],
320 		    &mib_len, NULL, NULL, NULL, SYSCTL_VERSION))
321 			return -1;
322 		break;
323 	case _SC_PRIORITY_SCHEDULING:
324 		if (sysctlgetmibinfo("kern.posix_sched", &mib[0], &mib_len,
325 		    NULL, NULL, NULL, SYSCTL_VERSION))
326 			return -1;
327 		goto yesno;
328 	case _SC_ATEXIT_MAX:
329 		mib[0] = CTL_USER;
330 		mib[1] = USER_ATEXIT_MAX;
331 		break;
332 
333 /* 1003.1-2001, TSF */
334 	case _SC_GETGR_R_SIZE_MAX:
335 		return _GETGR_R_SIZE_MAX;
336 	case _SC_GETPW_R_SIZE_MAX:
337 		return _GETPW_R_SIZE_MAX;
338 
339 yesno:		if (sysctl(mib, mib_len, &value, &len, NULL, 0) == -1)
340 			return (-1);
341 		if (value == 0)
342 			return (-1);
343 		return (value);
344 		/*NOTREACHED*/
345 		break;
346 
347 /* Extensions */
348 	case _SC_NPROCESSORS_CONF:
349 		mib[0] = CTL_HW;
350 		mib[1] = HW_NCPU;
351 		break;
352 	case _SC_NPROCESSORS_ONLN:
353 		mib[0] = CTL_HW;
354 		mib[1] = HW_NCPUONLINE;
355 		break;
356 
357 /* Native */
358 	case _SC_SCHED_RT_TS:
359 		if (sysctlgetmibinfo("kern.sched.rtts", &mib[0], &mib_len,
360 		    NULL, NULL, NULL, SYSCTL_VERSION))
361 			return -1;
362 		break;
363 	case _SC_SCHED_PRI_MIN:
364 		if (sysctlgetmibinfo("kern.sched.pri_min", &mib[0], &mib_len,
365 		    NULL, NULL, NULL, SYSCTL_VERSION))
366 			return -1;
367 		break;
368 	case _SC_SCHED_PRI_MAX:
369 		if (sysctlgetmibinfo("kern.sched.pri_max", &mib[0], &mib_len,
370 		    NULL, NULL, NULL, SYSCTL_VERSION))
371 			return -1;
372 		break;
373 	case _SC_THREAD_DESTRUCTOR_ITERATIONS:
374 		return _POSIX_THREAD_DESTRUCTOR_ITERATIONS;
375 	case _SC_THREAD_KEYS_MAX:
376 		return _POSIX_THREAD_KEYS_MAX;
377 	case _SC_THREAD_STACK_MIN:
378 		return _getpagesize();
379 	case _SC_THREAD_THREADS_MAX:
380 		if (sysctlgetmibinfo("kern.maxproc", &mib[0], &mib_len,
381 		    NULL, NULL, NULL, SYSCTL_VERSION))	/* XXX */
382 			return -1;
383 		goto yesno;
384 	case _SC_THREAD_ATTR_STACKADDR:
385 		return _POSIX_THREAD_ATTR_STACKADDR;
386 	case _SC_THREAD_ATTR_STACKSIZE:
387 		return _POSIX_THREAD_ATTR_STACKSIZE;
388 	case _SC_THREAD_SAFE_FUNCTIONS:
389 		return _POSIX_THREAD_SAFE_FUNCTIONS;
390 	case _SC_THREAD_PRIORITY_SCHEDULING:
391 	case _SC_THREAD_PRIO_INHERIT:
392 	case _SC_THREAD_PRIO_PROTECT:
393 	case _SC_THREAD_PROCESS_SHARED:
394 		return -1;
395 	case _SC_TTY_NAME_MAX:
396 		return pathconf(_PATH_DEV, _PC_NAME_MAX);
397 	default:
398 		errno = EINVAL;
399 		return (-1);
400 	}
401 	return (sysctl(mib, mib_len, &value, &len, NULL, 0) == -1 ? -1 : value);
402 }
403