xref: /openbsd-src/lib/libc/gen/sysconf.c (revision cb39b41371628601fbe4c618205356d538b9d08a)
1 /*	$OpenBSD: sysconf.c,v 1.22 2015/01/16 18:18:58 millert 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/types.h>
35 #include <sys/sem.h>
36 #include <sys/sysctl.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <sys/socket.h>
40 
41 #include <errno.h>
42 #include <grp.h>
43 #include <pthread.h>
44 #include <pwd.h>
45 #include <stdio.h>
46 #include <unistd.h>
47 
48 /*
49  * sysconf --
50  *	get configurable system variables.
51  *
52  * XXX
53  * POSIX 1003.1 (ISO/IEC 9945-1, 4.8.1.3) states that the variable values
54  * not change during the lifetime of the calling process.  This would seem
55  * to require that any change to system limits kill all running processes.
56  * A workaround might be to cache the values when they are first retrieved
57  * and then simply return the cached value on subsequent calls.  This is
58  * less useful than returning up-to-date values, however.
59  */
60 long
61 sysconf(int name)
62 {
63 	struct rlimit rl;
64 	size_t len;
65 	int mib[3], value, namelen, sverrno;
66 
67 	len = sizeof(value);
68 	namelen = 2;
69 
70 	switch (name) {
71 /* 1003.1 */
72 	case _SC_ARG_MAX:
73 		mib[0] = CTL_KERN;
74 		mib[1] = KERN_ARGMAX;
75 		break;
76 	case _SC_CHILD_MAX:
77 		if (getrlimit(RLIMIT_NPROC, &rl) != 0)
78 			return (-1);
79 		if (rl.rlim_cur == RLIM_INFINITY)
80 			return (-1);
81 		if (rl.rlim_cur > LONG_MAX) {
82 			errno = EOVERFLOW;
83 			return (-1);
84 		}
85 		return ((long)rl.rlim_cur);
86 	case _SC_CLK_TCK:
87 		return (CLK_TCK);
88 	case _SC_JOB_CONTROL:
89 		return (_POSIX_JOB_CONTROL);
90 	case _SC_NGROUPS_MAX:
91 		mib[0] = CTL_KERN;
92 		mib[1] = KERN_NGROUPS;
93 		break;
94 	case _SC_OPEN_MAX:
95 		if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
96 			return (-1);
97 		if (rl.rlim_cur == RLIM_INFINITY)
98 			return (-1);
99 		if (rl.rlim_cur > LONG_MAX) {
100 			errno = EOVERFLOW;
101 			return (-1);
102 		}
103 		return ((long)rl.rlim_cur);
104 	case _SC_STREAM_MAX:
105 		if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
106 			return (-1);
107 		if (rl.rlim_cur == RLIM_INFINITY)
108 			return (-1);
109 		if (rl.rlim_cur > LONG_MAX) {
110 			errno = EOVERFLOW;
111 			return (-1);
112 		}
113 		/*
114 		 * struct __sFILE currently has a limitation that
115 		 * file descriptors must fit in a signed short.
116 		 * This doesn't precisely capture the letter of POSIX
117 		 * but approximates the spirit.
118 		 */
119 		if (rl.rlim_cur > SHRT_MAX)
120 			return (SHRT_MAX);
121 
122 		return ((long)rl.rlim_cur);
123 	case _SC_TZNAME_MAX:
124 		return (NAME_MAX);
125 	case _SC_SAVED_IDS:
126 		return (_POSIX_SAVED_IDS);
127 	case _SC_VERSION:
128 		mib[0] = CTL_KERN;
129 		mib[1] = KERN_POSIX1;
130 		break;
131 
132 /* 1003.1b */
133 	case _SC_PAGESIZE:
134 		mib[0] = CTL_HW;
135 		mib[1] = HW_PAGESIZE;
136 		break;
137 	case _SC_FSYNC:
138 		return (_POSIX_FSYNC);
139 
140 /* 1003.1c */
141 	case _SC_LOGIN_NAME_MAX:
142 		return (LOGIN_NAME_MAX);
143 
144 	case _SC_THREAD_SAFE_FUNCTIONS:
145 		return (_POSIX_THREAD_SAFE_FUNCTIONS);
146 
147 	case _SC_GETGR_R_SIZE_MAX:
148 		return (_GR_BUF_LEN);
149 
150 	case _SC_GETPW_R_SIZE_MAX:
151 		return (_PW_BUF_LEN);
152 
153 /* 1003.2 */
154 	case _SC_BC_BASE_MAX:
155 		return (BC_BASE_MAX);
156 	case _SC_BC_DIM_MAX:
157 		return (BC_DIM_MAX);
158 	case _SC_BC_SCALE_MAX:
159 		return (BC_SCALE_MAX);
160 	case _SC_BC_STRING_MAX:
161 		return (BC_STRING_MAX);
162 	case _SC_COLL_WEIGHTS_MAX:
163 		return (COLL_WEIGHTS_MAX);
164 	case _SC_EXPR_NEST_MAX:
165 		return (EXPR_NEST_MAX);
166 	case _SC_LINE_MAX:
167 		return (LINE_MAX);
168 	case _SC_RE_DUP_MAX:
169 		return (RE_DUP_MAX);
170 	case _SC_2_VERSION:
171 		return (_POSIX2_VERSION);
172 	case _SC_2_C_BIND:
173 		return (_POSIX2_C_BIND);
174 	case _SC_2_C_DEV:
175 		return (_POSIX2_C_DEV);
176 	case _SC_2_CHAR_TERM:
177 		return (_POSIX2_CHAR_TERM);
178 	case _SC_2_FORT_DEV:
179 		return (_POSIX2_FORT_DEV);
180 	case _SC_2_FORT_RUN:
181 		return (_POSIX2_FORT_RUN);
182 	case _SC_2_LOCALEDEF:
183 		return (_POSIX2_LOCALEDEF);
184 	case _SC_2_SW_DEV:
185 		return (_POSIX2_SW_DEV);
186 	case _SC_2_UPE:
187 		return (_POSIX2_UPE);
188 
189 /* XPG 4.2 */
190 	case _SC_XOPEN_SHM:
191 		mib[0] = CTL_KERN;
192 		mib[1] = KERN_SYSVSHM;
193 		if (sysctl(mib, namelen, &value, &len, NULL, 0) == -1)
194 			return (-1);
195 		if (value == 0)
196 			return (-1);
197 		return (value);
198 		break;
199 	case _SC_SEM_NSEMS_MAX:
200 		return (-1);
201 	case _SC_SEM_VALUE_MAX:
202 		return (SEM_VALUE_MAX);
203 
204 /* Unsorted */
205 	case _SC_HOST_NAME_MAX:
206 		return (HOST_NAME_MAX);	/* does not include \0 */
207 	case _SC_MONOTONIC_CLOCK:
208 		return (_POSIX_MONOTONIC_CLOCK);
209 	case _SC_2_PBS:
210 	case _SC_2_PBS_ACCOUNTING:
211 	case _SC_2_PBS_CHECKPOINT:
212 	case _SC_2_PBS_LOCATE:
213 	case _SC_2_PBS_MESSAGE:
214 	case _SC_2_PBS_TRACK:
215 		return (_POSIX2_PBS);
216 	case _SC_ADVISORY_INFO:
217 		return (_POSIX_ADVISORY_INFO);
218 	case _SC_AIO_LISTIO_MAX:
219 	case _SC_AIO_MAX:
220 	case _SC_AIO_PRIO_DELTA_MAX:
221 		return (-1);
222 	case _SC_ASYNCHRONOUS_IO:
223 		return (_POSIX_ASYNCHRONOUS_IO);
224 	case _SC_ATEXIT_MAX:
225 		return (-1);
226 	case _SC_BARRIERS:
227 		return (_POSIX_BARRIERS);
228 	case _SC_CLOCK_SELECTION:
229 		return (_POSIX_CLOCK_SELECTION);
230 	case _SC_CPUTIME:
231 		return (_POSIX_CPUTIME);
232 	case _SC_DELAYTIMER_MAX:
233 		return (-1);
234 	case _SC_IOV_MAX:
235 		return (IOV_MAX);
236 	case _SC_IPV6:
237 #if _POSIX_IPV6 == 0
238 		sverrno = errno;
239 		value = socket(PF_INET6, SOCK_DGRAM, 0);
240 		errno = sverrno;
241 		if (value >= 0) {
242 			close(value);
243 			return (200112L);
244 		} else
245 			return (0);
246 #else
247 		return (_POSIX_IPV6);
248 #endif
249 	case _SC_MAPPED_FILES:
250 		return (_POSIX_MAPPED_FILES);
251 	case _SC_MEMLOCK:
252 		return (_POSIX_MEMLOCK);
253 	case _SC_MEMLOCK_RANGE:
254 		return (_POSIX_MEMLOCK_RANGE);
255 	case _SC_MEMORY_PROTECTION:
256 		return (_POSIX_MEMORY_PROTECTION);
257 	case _SC_MESSAGE_PASSING:
258 		return (_POSIX_MESSAGE_PASSING);
259 	case _SC_PRIORITIZED_IO:
260 		return (_POSIX_PRIORITIZED_IO);
261 	case _SC_PRIORITY_SCHEDULING:
262 		return (_POSIX_PRIORITY_SCHEDULING);
263 	case _SC_RAW_SOCKETS:
264 		return (_POSIX_RAW_SOCKETS);
265 	case _SC_READER_WRITER_LOCKS:
266 		return (_POSIX_READER_WRITER_LOCKS);
267 	case _SC_REALTIME_SIGNALS:
268 		return (_POSIX_REALTIME_SIGNALS);
269 	case _SC_REGEXP:
270 		return (_POSIX_REGEXP);
271 	case _SC_SEMAPHORES:
272 		return (_POSIX_SEMAPHORES);
273 	case _SC_SHARED_MEMORY_OBJECTS:
274 		return (_POSIX_SHARED_MEMORY_OBJECTS);
275 	case _SC_SHELL:
276 		return (_POSIX_SHELL);
277 	case _SC_SIGQUEUE_MAX:
278 		return (-1);
279 	case _SC_SPAWN:
280 		return (_POSIX_SPAWN);
281 	case _SC_SPIN_LOCKS:
282 		return (_POSIX_SPIN_LOCKS);
283 	case _SC_SPORADIC_SERVER:
284 		return (_POSIX_SPORADIC_SERVER);
285 	case _SC_SYNCHRONIZED_IO:
286 		return (_POSIX_SYNCHRONIZED_IO);
287 	case _SC_SYMLOOP_MAX:
288 		return (SYMLOOP_MAX);
289 	case _SC_THREAD_ATTR_STACKADDR:
290 		return (_POSIX_THREAD_ATTR_STACKADDR);
291 	case _SC_THREAD_ATTR_STACKSIZE:
292 		return (_POSIX_THREAD_ATTR_STACKSIZE);
293 	case _SC_THREAD_CPUTIME:
294 		return (_POSIX_THREAD_CPUTIME);
295 	case _SC_THREAD_DESTRUCTOR_ITERATIONS:
296 		return (PTHREAD_DESTRUCTOR_ITERATIONS);
297 	case _SC_THREAD_KEYS_MAX:
298 		return (PTHREAD_KEYS_MAX);
299 	case _SC_THREAD_PRIO_INHERIT:
300 		return (_POSIX_THREAD_PRIO_INHERIT);
301 	case _SC_THREAD_PRIO_PROTECT:
302 		return (_POSIX_THREAD_PRIO_PROTECT);
303 	case _SC_THREAD_PRIORITY_SCHEDULING:
304 		return (_POSIX_THREAD_PRIORITY_SCHEDULING);
305 	case _SC_THREAD_PROCESS_SHARED:
306 		return (_POSIX_THREAD_PROCESS_SHARED);
307 	case _SC_THREAD_ROBUST_PRIO_INHERIT:
308 		return (_POSIX_THREAD_ROBUST_PRIO_INHERIT);
309 	case _SC_THREAD_ROBUST_PRIO_PROTECT:
310 		return (_POSIX_THREAD_ROBUST_PRIO_PROTECT);
311 	case _SC_THREAD_SPORADIC_SERVER:
312 		return (_POSIX_THREAD_SPORADIC_SERVER);
313 	case _SC_THREAD_STACK_MIN:
314 		return (PTHREAD_STACK_MIN);
315 	case _SC_THREAD_THREADS_MAX:
316 		return (PTHREAD_THREADS_MAX);
317 	case _SC_THREADS:
318 		return (_POSIX_THREADS);
319 	case _SC_TIMEOUTS:
320 		return (_POSIX_TIMEOUTS);
321 	case _SC_TIMER_MAX:
322 		return (-1);
323 	case _SC_TIMERS:
324 		return (_POSIX_TIMERS);
325 	case _SC_TRACE:
326 	case _SC_TRACE_EVENT_FILTER:
327 	case _SC_TRACE_EVENT_NAME_MAX:
328 	case _SC_TRACE_INHERIT:
329 	case _SC_TRACE_LOG:
330 		return (_POSIX_TRACE);
331 	case _SC_TTY_NAME_MAX:
332 		return (TTY_NAME_MAX);
333 	case _SC_TYPED_MEMORY_OBJECTS:
334 		return (_POSIX_TYPED_MEMORY_OBJECTS);
335 	case _SC_V6_ILP32_OFF32:
336 		return (_POSIX_V6_ILP32_OFF32);
337 	case _SC_V6_ILP32_OFFBIG:
338 #if _POSIX_V6_ILP32_OFFBIG == 0
339 		if (sizeof(int) * CHAR_BIT == 32 &&
340 		    sizeof(long) * CHAR_BIT == 32 &&
341 		    sizeof(void *) * CHAR_BIT == 32 &&
342 		    sizeof(off_t) * CHAR_BIT >= 64)
343 			return 1;
344 		else
345 			return -1;
346 #else
347 		return (_POSIX_V6_ILP32_OFFBIG);
348 #endif
349 	case _SC_V6_LP64_OFF64:
350 #if _POSIX_V6_LP64_OFF64 == 0
351 		if (sizeof(int) * CHAR_BIT == 32 &&
352 		    sizeof(long) * CHAR_BIT == 64 &&
353 		    sizeof(void *) * CHAR_BIT == 64 &&
354 		    sizeof(off_t) * CHAR_BIT == 64)
355 			return 1;
356 		else
357 			return -1;
358 #else
359 		return (_POSIX_V6_LP64_OFF64);
360 #endif
361 	case _SC_V6_LPBIG_OFFBIG:
362 #if _POSIX_V6_LPBIG_OFFBIG == 0
363 		if (sizeof(int) * CHAR_BIT >= 32 &&
364 		    sizeof(long) * CHAR_BIT >= 64 &&
365 		    sizeof(void *) * CHAR_BIT >= 64 &&
366 		    sizeof(off_t) * CHAR_BIT >= 64)
367 			return 1;
368 		else
369 			return -1;
370 #else
371 		return (_POSIX_V6_LPBIG_OFFBIG);
372 #endif
373 	case _SC_V7_ILP32_OFF32:
374 		return (_POSIX_V7_ILP32_OFF32);
375 	case _SC_V7_ILP32_OFFBIG:
376 #if _POSIX_V7_ILP32_OFFBIG == 0
377 		if (sizeof(int) * CHAR_BIT == 32 &&
378 		    sizeof(long) * CHAR_BIT == 32 &&
379 		    sizeof(void *) * CHAR_BIT == 32 &&
380 		    sizeof(off_t) * CHAR_BIT >= 64)
381 			return 1;
382 		else
383 			return -1;
384 #else
385 		return (_POSIX_V7_ILP32_OFFBIG);
386 #endif
387 	case _SC_V7_LP64_OFF64:
388 #if _POSIX_V7_LP64_OFF64 == 0
389 		if (sizeof(int) * CHAR_BIT == 32 &&
390 		    sizeof(long) * CHAR_BIT == 64 &&
391 		    sizeof(void *) * CHAR_BIT == 64 &&
392 		    sizeof(off_t) * CHAR_BIT == 64)
393 			return 1;
394 		else
395 			return -1;
396 #else
397 		return (_POSIX_V7_LP64_OFF64);
398 #endif
399 	case _SC_V7_LPBIG_OFFBIG:
400 #if _POSIX_V7_LPBIG_OFFBIG == 0
401 		if (sizeof(int) * CHAR_BIT >= 32 &&
402 		    sizeof(long) * CHAR_BIT >= 64 &&
403 		    sizeof(void *) * CHAR_BIT >= 64 &&
404 		    sizeof(off_t) * CHAR_BIT >= 64)
405 			return 1;
406 		else
407 			return -1;
408 #else
409 		return (_POSIX_V7_LPBIG_OFFBIG);
410 #endif
411 	case _SC_XOPEN_CRYPT:
412 		return (_XOPEN_CRYPT);
413 	case _SC_XOPEN_ENH_I18N:
414 		return (_XOPEN_ENH_I18N);
415 	case _SC_XOPEN_LEGACY:
416 		return (_XOPEN_LEGACY);
417 	case _SC_XOPEN_REALTIME:
418 		return (_XOPEN_REALTIME);
419 	case _SC_XOPEN_REALTIME_THREADS:
420 		return (_XOPEN_REALTIME_THREADS);
421 	case _SC_XOPEN_STREAMS:
422 		return (_XOPEN_STREAMS);
423 	case _SC_XOPEN_UNIX:
424 		return (_XOPEN_UNIX);
425 	case _SC_XOPEN_UUCP:
426 		return (_XOPEN_UUCP);
427 #ifdef _XOPEN_VERSION
428 	case _SC_XOPEN_VERSION:
429 		return (_XOPEN_VERSION);
430 #endif
431 
432 /* Extensions */
433 	case _SC_PHYS_PAGES:
434 	{
435 		int64_t physmem;
436 
437 		mib[0] = CTL_HW;
438 		mib[1] = HW_PHYSMEM64;
439 		len = sizeof(physmem);
440 		if (sysctl(mib, namelen, &physmem, &len, NULL, 0) == -1)
441 			return (-1);
442 		return (physmem / getpagesize());
443 	}
444 	case _SC_AVPHYS_PAGES:
445 	{
446 		struct uvmexp uvmexp;
447 
448 		mib[0] = CTL_VM;
449 		mib[1] = VM_UVMEXP;
450 		len = sizeof(uvmexp);
451 		if (sysctl(mib, namelen, &uvmexp, &len, NULL, 0) == -1)
452 			return (-1);
453 		return (uvmexp.free);
454 	}
455 
456 	case _SC_NPROCESSORS_CONF:
457 		mib[0] = CTL_HW;
458 		mib[1] = HW_NCPU;
459 		break;
460 	case _SC_NPROCESSORS_ONLN:
461 		mib[0] = CTL_HW;
462 		mib[1] = HW_NCPU;
463 		break;
464 
465 	default:
466 		errno = EINVAL;
467 		return (-1);
468 	}
469 	return (sysctl(mib, namelen, &value, &len, NULL, 0) == -1 ? -1 : value);
470 }
471