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