xref: /openbsd-src/lib/libc/gen/sysconf.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: sysconf.c,v 1.16 2012/06/24 20:11:16 matthew Exp $ */
2 /*-
3  * Copyright (c) 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Sean Eric Fagan of Cygnus Support.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/sem.h>
36 #include <sys/sysctl.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <sys/vmmeter.h>
40 #include <sys/socket.h>
41 
42 #include <errno.h>
43 #include <grp.h>
44 #include <pthread.h>
45 #include <pwd.h>
46 #include <stdio.h>
47 #include <unistd.h>
48 
49 /*
50  * sysconf --
51  *	get configurable system variables.
52  *
53  * XXX
54  * POSIX 1003.1 (ISO/IEC 9945-1, 4.8.1.3) states that the variable values
55  * not change during the lifetime of the calling process.  This would seem
56  * to require that any change to system limits kill all running processes.
57  * A workaround might be to cache the values when they are first retrieved
58  * and then simply return the cached value on subsequent calls.  This is
59  * less useful than returning up-to-date values, however.
60  */
61 long
62 sysconf(int name)
63 {
64 	struct rlimit rl;
65 	size_t len;
66 	int mib[3], value, namelen, sverrno;
67 
68 	len = sizeof(value);
69 	namelen = 2;
70 
71 	switch (name) {
72 /* 1003.1 */
73 	case _SC_ARG_MAX:
74 		mib[0] = CTL_KERN;
75 		mib[1] = KERN_ARGMAX;
76 		break;
77 	case _SC_CHILD_MAX:
78 		return (getrlimit(RLIMIT_NPROC, &rl) ? -1 : rl.rlim_cur);
79 	case _SC_CLK_TCK:
80 		return (CLK_TCK);
81 	case _SC_JOB_CONTROL:
82 		return (_POSIX_JOB_CONTROL);
83 	case _SC_NGROUPS_MAX:
84 		mib[0] = CTL_KERN;
85 		mib[1] = KERN_NGROUPS;
86 		break;
87 	case _SC_OPEN_MAX:
88 		return (getrlimit(RLIMIT_NOFILE, &rl) ? -1 : rl.rlim_cur);
89 	case _SC_STREAM_MAX:
90 		return (FOPEN_MAX);
91 	case _SC_TZNAME_MAX:
92 		return (NAME_MAX);
93 	case _SC_SAVED_IDS:
94 		return (_POSIX_SAVED_IDS);
95 	case _SC_VERSION:
96 		mib[0] = CTL_KERN;
97 		mib[1] = KERN_POSIX1;
98 		break;
99 
100 /* 1003.1b */
101 	case _SC_PAGESIZE:
102 		mib[0] = CTL_HW;
103 		mib[1] = HW_PAGESIZE;
104 		break;
105 	case _SC_FSYNC:
106 		return (_POSIX_FSYNC);
107 
108 /* 1003.1c */
109 	case _SC_LOGIN_NAME_MAX:
110 		return (LOGIN_NAME_MAX);
111 
112 	case _SC_THREAD_SAFE_FUNCTIONS:
113 		return (_POSIX_THREAD_SAFE_FUNCTIONS);
114 
115 	case _SC_GETGR_R_SIZE_MAX:
116 		return (_GR_BUF_LEN);
117 
118 	case _SC_GETPW_R_SIZE_MAX:
119 		return (_PW_BUF_LEN);
120 
121 /* 1003.2 */
122 	case _SC_BC_BASE_MAX:
123 		return (BC_BASE_MAX);
124 	case _SC_BC_DIM_MAX:
125 		return (BC_DIM_MAX);
126 	case _SC_BC_SCALE_MAX:
127 		return (BC_SCALE_MAX);
128 	case _SC_BC_STRING_MAX:
129 		return (BC_STRING_MAX);
130 	case _SC_COLL_WEIGHTS_MAX:
131 		return (COLL_WEIGHTS_MAX);
132 	case _SC_EXPR_NEST_MAX:
133 		return (EXPR_NEST_MAX);
134 	case _SC_LINE_MAX:
135 		return (LINE_MAX);
136 	case _SC_RE_DUP_MAX:
137 		return (RE_DUP_MAX);
138 	case _SC_2_VERSION:
139 		return (_POSIX2_VERSION);
140 	case _SC_2_C_BIND:
141 		return (_POSIX2_C_BIND);
142 	case _SC_2_C_DEV:
143 		return (_POSIX2_C_DEV);
144 	case _SC_2_CHAR_TERM:
145 		return (_POSIX2_CHAR_TERM);
146 	case _SC_2_FORT_DEV:
147 		return (_POSIX2_FORT_DEV);
148 	case _SC_2_FORT_RUN:
149 		return (_POSIX2_FORT_RUN);
150 	case _SC_2_LOCALEDEF:
151 		return (_POSIX2_LOCALEDEF);
152 	case _SC_2_SW_DEV:
153 		return (_POSIX2_SW_DEV);
154 	case _SC_2_UPE:
155 		return (_POSIX2_UPE);
156 
157 /* XPG 4.2 */
158 	case _SC_XOPEN_SHM:
159 		mib[0] = CTL_KERN;
160 		mib[1] = KERN_SYSVSHM;
161 
162 yesno:		if (sysctl(mib, namelen, &value, &len, NULL, 0) == -1)
163 			return (-1);
164 		if (value == 0)
165 			return (-1);
166 		return (value);
167 		break;
168 	case _SC_SEM_NSEMS_MAX:
169 	case _SC_SEM_VALUE_MAX:
170 		mib[0] = CTL_KERN;
171 		mib[1] = KERN_SEMINFO;
172 		mib[2] = name = _SC_SEM_NSEMS_MAX ?
173 		    KERN_SEMINFO_SEMMNS : KERN_SEMINFO_SEMVMX;
174 		namelen = 3;
175 		break;
176 
177 /* Unsorted */
178 	case _SC_HOST_NAME_MAX:
179 		return (MAXHOSTNAMELEN - 1); /* does not include \0 */
180 	case _SC_MONOTONIC_CLOCK:
181 		return (_POSIX_MONOTONIC_CLOCK);
182 	case _SC_2_PBS:
183 	case _SC_2_PBS_ACCOUNTING:
184 	case _SC_2_PBS_CHECKPOINT:
185 	case _SC_2_PBS_LOCATE:
186 	case _SC_2_PBS_MESSAGE:
187 	case _SC_2_PBS_TRACK:
188 		return (_POSIX2_PBS);
189 	case _SC_ADVISORY_INFO:
190 		return (_POSIX_ADVISORY_INFO);
191 	case _SC_AIO_LISTIO_MAX:
192 	case _SC_AIO_MAX:
193 	case _SC_AIO_PRIO_DELTA_MAX:
194 		return (-1);
195 	case _SC_ASYNCHRONOUS_IO:
196 		return (_POSIX_ASYNCHRONOUS_IO);
197 	case _SC_ATEXIT_MAX:
198 		return (-1);
199 	case _SC_BARRIERS:
200 		return (_POSIX_BARRIERS);
201 	case _SC_CLOCK_SELECTION:
202 		return (_POSIX_CLOCK_SELECTION);
203 	case _SC_CPUTIME:
204 		return (_POSIX_CPUTIME);
205 	case _SC_DELAYTIMER_MAX:
206 		return (-1);
207 	case _SC_IOV_MAX:
208 		return (IOV_MAX);
209 	case _SC_IPV6:
210 #if _POSIX_IPV6 == 0
211 		sverrno = errno;
212 		value = socket(PF_INET6, SOCK_DGRAM, 0);
213 		errno = sverrno;
214 		if (value >= 0) {
215 			close(value);
216 			return (200112L);
217 		} else
218 			return (0);
219 #else
220 		return (_POSIX_IPV6);
221 #endif
222 	case _SC_MAPPED_FILES:
223 		return (_POSIX_MAPPED_FILES);
224 	case _SC_MEMLOCK:
225 		return (_POSIX_MEMLOCK);
226 	case _SC_MEMLOCK_RANGE:
227 		return (_POSIX_MEMLOCK_RANGE);
228 	case _SC_MEMORY_PROTECTION:
229 		return (_POSIX_MEMORY_PROTECTION);
230 	case _SC_MESSAGE_PASSING:
231 		return (_POSIX_MESSAGE_PASSING);
232 	case _SC_PRIORITIZED_IO:
233 		return (_POSIX_PRIORITIZED_IO);
234 	case _SC_PRIORITY_SCHEDULING:
235 		return (_POSIX_PRIORITY_SCHEDULING);
236 	case _SC_RAW_SOCKETS:
237 		return (_POSIX_RAW_SOCKETS);
238 	case _SC_READER_WRITER_LOCKS:
239 		return (_POSIX_READER_WRITER_LOCKS);
240 	case _SC_REALTIME_SIGNALS:
241 		return (_POSIX_REALTIME_SIGNALS);
242 	case _SC_REGEXP:
243 		return (_POSIX_REGEXP);
244 	case _SC_SEMAPHORES:
245 		return (_POSIX_SEMAPHORES);
246 	case _SC_SHARED_MEMORY_OBJECTS:
247 		return (_POSIX_SHARED_MEMORY_OBJECTS);
248 	case _SC_SHELL:
249 		return (_POSIX_SHELL);
250 	case _SC_SIGQUEUE_MAX:
251 		return (-1);
252 	case _SC_SPAWN:
253 		return (_POSIX_SPAWN);
254 	case _SC_SPIN_LOCKS:
255 		return (_POSIX_SPIN_LOCKS);
256 	case _SC_SPORADIC_SERVER:
257 		return (_POSIX_SPORADIC_SERVER);
258 	case _SC_SYNCHRONIZED_IO:
259 		return (_POSIX_SYNCHRONIZED_IO);
260 	case _SC_SYMLOOP_MAX:
261 		return (SYMLOOP_MAX);
262 	case _SC_THREAD_ATTR_STACKADDR:
263 		return (_POSIX_THREAD_ATTR_STACKADDR);
264 	case _SC_THREAD_ATTR_STACKSIZE:
265 		return (_POSIX_THREAD_ATTR_STACKSIZE);
266 	case _SC_THREAD_CPUTIME:
267 		return (_POSIX_THREAD_CPUTIME);
268 	case _SC_THREAD_DESTRUCTOR_ITERATIONS:
269 		return (PTHREAD_DESTRUCTOR_ITERATIONS);
270 	case _SC_THREAD_KEYS_MAX:
271 		return (PTHREAD_KEYS_MAX);
272 	case _SC_THREAD_PRIO_INHERIT:
273 		return (_POSIX_THREAD_PRIO_INHERIT);
274 	case _SC_THREAD_PRIO_PROTECT:
275 		return (_POSIX_THREAD_PRIO_PROTECT);
276 	case _SC_THREAD_PRIORITY_SCHEDULING:
277 		return (_POSIX_THREAD_PRIORITY_SCHEDULING);
278 	case _SC_THREAD_PROCESS_SHARED:
279 		return (_POSIX_THREAD_PROCESS_SHARED);
280 	case _SC_THREAD_ROBUST_PRIO_INHERIT:
281 		return (_POSIX_THREAD_ROBUST_PRIO_INHERIT);
282 	case _SC_THREAD_ROBUST_PRIO_PROTECT:
283 		return (_POSIX_THREAD_ROBUST_PRIO_PROTECT);
284 	case _SC_THREAD_SPORADIC_SERVER:
285 		return (_POSIX_THREAD_SPORADIC_SERVER);
286 	case _SC_THREAD_STACK_MIN:
287 		return (PTHREAD_STACK_MIN);
288 	case _SC_THREAD_THREADS_MAX:
289 		return (PTHREAD_THREADS_MAX);
290 	case _SC_THREADS:
291 		return (_POSIX_THREADS);
292 	case _SC_TIMEOUTS:
293 		return (_POSIX_TIMEOUTS);
294 	case _SC_TIMER_MAX:
295 		return (-1);
296 	case _SC_TIMERS:
297 		return (_POSIX_TIMERS);
298 	case _SC_TRACE:
299 	case _SC_TRACE_EVENT_FILTER:
300 	case _SC_TRACE_EVENT_NAME_MAX:
301 	case _SC_TRACE_INHERIT:
302 	case _SC_TRACE_LOG:
303 		return (_POSIX_TRACE);
304 	case _SC_TTY_NAME_MAX:
305 		return (TTY_NAME_MAX);
306 	case _SC_TYPED_MEMORY_OBJECTS:
307 		return (_POSIX_TYPED_MEMORY_OBJECTS);
308 	case _SC_V6_ILP32_OFF32:
309 		return (_POSIX_V6_ILP32_OFF32);
310 	case _SC_V6_ILP32_OFFBIG:
311 #if _POSIX_V6_ILP32_OFFBIG == 0
312 		if (sizeof(int) * CHAR_BIT == 32 &&
313 		    sizeof(long) * CHAR_BIT == 32 &&
314 		    sizeof(void *) * CHAR_BIT == 32 &&
315 		    sizeof(off_t) * CHAR_BIT >= 64)
316 			return 1;
317 		else
318 			return -1;
319 #else
320 		return (_POSIX_V6_ILP32_OFFBIG);
321 #endif
322 	case _SC_V6_LP64_OFF64:
323 #if _POSIX_V6_LP64_OFF64 == 0
324 		if (sizeof(int) * CHAR_BIT == 32 &&
325 		    sizeof(long) * CHAR_BIT == 64 &&
326 		    sizeof(void *) * CHAR_BIT == 64 &&
327 		    sizeof(off_t) * CHAR_BIT == 64)
328 			return 1;
329 		else
330 			return -1;
331 #else
332 		return (_POSIX_V6_LP64_OFF64);
333 #endif
334 	case _SC_V6_LPBIG_OFFBIG:
335 #if _POSIX_V6_LPBIG_OFFBIG == 0
336 		if (sizeof(int) * CHAR_BIT >= 32 &&
337 		    sizeof(long) * CHAR_BIT >= 64 &&
338 		    sizeof(void *) * CHAR_BIT >= 64 &&
339 		    sizeof(off_t) * CHAR_BIT >= 64)
340 			return 1;
341 		else
342 			return -1;
343 #else
344 		return (_POSIX_V6_LPBIG_OFFBIG);
345 #endif
346 	case _SC_V7_ILP32_OFF32:
347 		return (_POSIX_V7_ILP32_OFF32);
348 	case _SC_V7_ILP32_OFFBIG:
349 #if _POSIX_V7_ILP32_OFFBIG == 0
350 		if (sizeof(int) * CHAR_BIT == 32 &&
351 		    sizeof(long) * CHAR_BIT == 32 &&
352 		    sizeof(void *) * CHAR_BIT == 32 &&
353 		    sizeof(off_t) * CHAR_BIT >= 64)
354 			return 1;
355 		else
356 			return -1;
357 #else
358 		return (_POSIX_V7_ILP32_OFFBIG);
359 #endif
360 	case _SC_V7_LP64_OFF64:
361 #if _POSIX_V7_LP64_OFF64 == 0
362 		if (sizeof(int) * CHAR_BIT == 32 &&
363 		    sizeof(long) * CHAR_BIT == 64 &&
364 		    sizeof(void *) * CHAR_BIT == 64 &&
365 		    sizeof(off_t) * CHAR_BIT == 64)
366 			return 1;
367 		else
368 			return -1;
369 #else
370 		return (_POSIX_V7_LP64_OFF64);
371 #endif
372 	case _SC_V7_LPBIG_OFFBIG:
373 #if _POSIX_V7_LPBIG_OFFBIG == 0
374 		if (sizeof(int) * CHAR_BIT >= 32 &&
375 		    sizeof(long) * CHAR_BIT >= 64 &&
376 		    sizeof(void *) * CHAR_BIT >= 64 &&
377 		    sizeof(off_t) * CHAR_BIT >= 64)
378 			return 1;
379 		else
380 			return -1;
381 #else
382 		return (_POSIX_V7_LPBIG_OFFBIG);
383 #endif
384 	case _SC_XOPEN_CRYPT:
385 		return (_XOPEN_CRYPT);
386 	case _SC_XOPEN_ENH_I18N:
387 		return (_XOPEN_ENH_I18N);
388 	case _SC_XOPEN_LEGACY:
389 		return (_XOPEN_LEGACY);
390 	case _SC_XOPEN_REALTIME:
391 		return (_XOPEN_REALTIME);
392 	case _SC_XOPEN_REALTIME_THREADS:
393 		return (_XOPEN_REALTIME_THREADS);
394 	case _SC_XOPEN_STREAMS:
395 		return (_XOPEN_STREAMS);
396 	case _SC_XOPEN_UNIX:
397 		return (_XOPEN_UNIX);
398 	case _SC_XOPEN_UUCP:
399 		return (_XOPEN_UUCP);
400 #ifdef _XOPEN_VERSION
401 	case _SC_XOPEN_VERSION:
402 		return (_XOPEN_VERSION);
403 #endif
404 
405 /* Extensions */
406 	case _SC_PHYS_PAGES:
407 	{
408 		int64_t physmem;
409 
410 		mib[0] = CTL_HW;
411 		mib[1] = HW_PHYSMEM64;
412 		len = sizeof(physmem);
413 		if (sysctl(mib, namelen, &physmem, &len, NULL, 0) == -1)
414 			return (-1);
415 		return (physmem / getpagesize());
416 	}
417 	case _SC_AVPHYS_PAGES:
418 	{
419 		struct vmtotal vmtotal;
420 
421 		mib[0] = CTL_VM;
422 		mib[1] = VM_METER;
423 		len = sizeof(vmtotal);
424 		if (sysctl(mib, namelen, &vmtotal, &len, NULL, 0) == -1)
425 			return (-1);
426 		return (vmtotal.t_free);
427 	}
428 
429 	case _SC_NPROCESSORS_CONF:
430 		mib[0] = CTL_HW;
431 		mib[1] = HW_NCPU;
432 		break;
433 	case _SC_NPROCESSORS_ONLN:
434 		mib[0] = CTL_HW;
435 		mib[1] = HW_NCPU;
436 		break;
437 
438 	default:
439 		errno = EINVAL;
440 		return (-1);
441 	}
442 	return (sysctl(mib, namelen, &value, &len, NULL, 0) == -1 ? -1 : value);
443 }
444