xref: /openbsd-src/lib/libc/gen/sysconf.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /*	$OpenBSD: sysconf.c,v 1.17 2012/08/29 21:46:29 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 		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 	case _SC_SEM_VALUE_MAX:
202 		mib[0] = CTL_KERN;
203 		mib[1] = KERN_SEMINFO;
204 		mib[2] = name = _SC_SEM_NSEMS_MAX ?
205 		    KERN_SEMINFO_SEMMNS : KERN_SEMINFO_SEMVMX;
206 		namelen = 3;
207 		break;
208 
209 /* Unsorted */
210 	case _SC_HOST_NAME_MAX:
211 		return (MAXHOSTNAMELEN - 1); /* does not include \0 */
212 	case _SC_MONOTONIC_CLOCK:
213 		return (_POSIX_MONOTONIC_CLOCK);
214 	case _SC_2_PBS:
215 	case _SC_2_PBS_ACCOUNTING:
216 	case _SC_2_PBS_CHECKPOINT:
217 	case _SC_2_PBS_LOCATE:
218 	case _SC_2_PBS_MESSAGE:
219 	case _SC_2_PBS_TRACK:
220 		return (_POSIX2_PBS);
221 	case _SC_ADVISORY_INFO:
222 		return (_POSIX_ADVISORY_INFO);
223 	case _SC_AIO_LISTIO_MAX:
224 	case _SC_AIO_MAX:
225 	case _SC_AIO_PRIO_DELTA_MAX:
226 		return (-1);
227 	case _SC_ASYNCHRONOUS_IO:
228 		return (_POSIX_ASYNCHRONOUS_IO);
229 	case _SC_ATEXIT_MAX:
230 		return (-1);
231 	case _SC_BARRIERS:
232 		return (_POSIX_BARRIERS);
233 	case _SC_CLOCK_SELECTION:
234 		return (_POSIX_CLOCK_SELECTION);
235 	case _SC_CPUTIME:
236 		return (_POSIX_CPUTIME);
237 	case _SC_DELAYTIMER_MAX:
238 		return (-1);
239 	case _SC_IOV_MAX:
240 		return (IOV_MAX);
241 	case _SC_IPV6:
242 #if _POSIX_IPV6 == 0
243 		sverrno = errno;
244 		value = socket(PF_INET6, SOCK_DGRAM, 0);
245 		errno = sverrno;
246 		if (value >= 0) {
247 			close(value);
248 			return (200112L);
249 		} else
250 			return (0);
251 #else
252 		return (_POSIX_IPV6);
253 #endif
254 	case _SC_MAPPED_FILES:
255 		return (_POSIX_MAPPED_FILES);
256 	case _SC_MEMLOCK:
257 		return (_POSIX_MEMLOCK);
258 	case _SC_MEMLOCK_RANGE:
259 		return (_POSIX_MEMLOCK_RANGE);
260 	case _SC_MEMORY_PROTECTION:
261 		return (_POSIX_MEMORY_PROTECTION);
262 	case _SC_MESSAGE_PASSING:
263 		return (_POSIX_MESSAGE_PASSING);
264 	case _SC_PRIORITIZED_IO:
265 		return (_POSIX_PRIORITIZED_IO);
266 	case _SC_PRIORITY_SCHEDULING:
267 		return (_POSIX_PRIORITY_SCHEDULING);
268 	case _SC_RAW_SOCKETS:
269 		return (_POSIX_RAW_SOCKETS);
270 	case _SC_READER_WRITER_LOCKS:
271 		return (_POSIX_READER_WRITER_LOCKS);
272 	case _SC_REALTIME_SIGNALS:
273 		return (_POSIX_REALTIME_SIGNALS);
274 	case _SC_REGEXP:
275 		return (_POSIX_REGEXP);
276 	case _SC_SEMAPHORES:
277 		return (_POSIX_SEMAPHORES);
278 	case _SC_SHARED_MEMORY_OBJECTS:
279 		return (_POSIX_SHARED_MEMORY_OBJECTS);
280 	case _SC_SHELL:
281 		return (_POSIX_SHELL);
282 	case _SC_SIGQUEUE_MAX:
283 		return (-1);
284 	case _SC_SPAWN:
285 		return (_POSIX_SPAWN);
286 	case _SC_SPIN_LOCKS:
287 		return (_POSIX_SPIN_LOCKS);
288 	case _SC_SPORADIC_SERVER:
289 		return (_POSIX_SPORADIC_SERVER);
290 	case _SC_SYNCHRONIZED_IO:
291 		return (_POSIX_SYNCHRONIZED_IO);
292 	case _SC_SYMLOOP_MAX:
293 		return (SYMLOOP_MAX);
294 	case _SC_THREAD_ATTR_STACKADDR:
295 		return (_POSIX_THREAD_ATTR_STACKADDR);
296 	case _SC_THREAD_ATTR_STACKSIZE:
297 		return (_POSIX_THREAD_ATTR_STACKSIZE);
298 	case _SC_THREAD_CPUTIME:
299 		return (_POSIX_THREAD_CPUTIME);
300 	case _SC_THREAD_DESTRUCTOR_ITERATIONS:
301 		return (PTHREAD_DESTRUCTOR_ITERATIONS);
302 	case _SC_THREAD_KEYS_MAX:
303 		return (PTHREAD_KEYS_MAX);
304 	case _SC_THREAD_PRIO_INHERIT:
305 		return (_POSIX_THREAD_PRIO_INHERIT);
306 	case _SC_THREAD_PRIO_PROTECT:
307 		return (_POSIX_THREAD_PRIO_PROTECT);
308 	case _SC_THREAD_PRIORITY_SCHEDULING:
309 		return (_POSIX_THREAD_PRIORITY_SCHEDULING);
310 	case _SC_THREAD_PROCESS_SHARED:
311 		return (_POSIX_THREAD_PROCESS_SHARED);
312 	case _SC_THREAD_ROBUST_PRIO_INHERIT:
313 		return (_POSIX_THREAD_ROBUST_PRIO_INHERIT);
314 	case _SC_THREAD_ROBUST_PRIO_PROTECT:
315 		return (_POSIX_THREAD_ROBUST_PRIO_PROTECT);
316 	case _SC_THREAD_SPORADIC_SERVER:
317 		return (_POSIX_THREAD_SPORADIC_SERVER);
318 	case _SC_THREAD_STACK_MIN:
319 		return (PTHREAD_STACK_MIN);
320 	case _SC_THREAD_THREADS_MAX:
321 		return (PTHREAD_THREADS_MAX);
322 	case _SC_THREADS:
323 		return (_POSIX_THREADS);
324 	case _SC_TIMEOUTS:
325 		return (_POSIX_TIMEOUTS);
326 	case _SC_TIMER_MAX:
327 		return (-1);
328 	case _SC_TIMERS:
329 		return (_POSIX_TIMERS);
330 	case _SC_TRACE:
331 	case _SC_TRACE_EVENT_FILTER:
332 	case _SC_TRACE_EVENT_NAME_MAX:
333 	case _SC_TRACE_INHERIT:
334 	case _SC_TRACE_LOG:
335 		return (_POSIX_TRACE);
336 	case _SC_TTY_NAME_MAX:
337 		return (TTY_NAME_MAX);
338 	case _SC_TYPED_MEMORY_OBJECTS:
339 		return (_POSIX_TYPED_MEMORY_OBJECTS);
340 	case _SC_V6_ILP32_OFF32:
341 		return (_POSIX_V6_ILP32_OFF32);
342 	case _SC_V6_ILP32_OFFBIG:
343 #if _POSIX_V6_ILP32_OFFBIG == 0
344 		if (sizeof(int) * CHAR_BIT == 32 &&
345 		    sizeof(long) * CHAR_BIT == 32 &&
346 		    sizeof(void *) * CHAR_BIT == 32 &&
347 		    sizeof(off_t) * CHAR_BIT >= 64)
348 			return 1;
349 		else
350 			return -1;
351 #else
352 		return (_POSIX_V6_ILP32_OFFBIG);
353 #endif
354 	case _SC_V6_LP64_OFF64:
355 #if _POSIX_V6_LP64_OFF64 == 0
356 		if (sizeof(int) * CHAR_BIT == 32 &&
357 		    sizeof(long) * CHAR_BIT == 64 &&
358 		    sizeof(void *) * CHAR_BIT == 64 &&
359 		    sizeof(off_t) * CHAR_BIT == 64)
360 			return 1;
361 		else
362 			return -1;
363 #else
364 		return (_POSIX_V6_LP64_OFF64);
365 #endif
366 	case _SC_V6_LPBIG_OFFBIG:
367 #if _POSIX_V6_LPBIG_OFFBIG == 0
368 		if (sizeof(int) * CHAR_BIT >= 32 &&
369 		    sizeof(long) * CHAR_BIT >= 64 &&
370 		    sizeof(void *) * CHAR_BIT >= 64 &&
371 		    sizeof(off_t) * CHAR_BIT >= 64)
372 			return 1;
373 		else
374 			return -1;
375 #else
376 		return (_POSIX_V6_LPBIG_OFFBIG);
377 #endif
378 	case _SC_V7_ILP32_OFF32:
379 		return (_POSIX_V7_ILP32_OFF32);
380 	case _SC_V7_ILP32_OFFBIG:
381 #if _POSIX_V7_ILP32_OFFBIG == 0
382 		if (sizeof(int) * CHAR_BIT == 32 &&
383 		    sizeof(long) * CHAR_BIT == 32 &&
384 		    sizeof(void *) * CHAR_BIT == 32 &&
385 		    sizeof(off_t) * CHAR_BIT >= 64)
386 			return 1;
387 		else
388 			return -1;
389 #else
390 		return (_POSIX_V7_ILP32_OFFBIG);
391 #endif
392 	case _SC_V7_LP64_OFF64:
393 #if _POSIX_V7_LP64_OFF64 == 0
394 		if (sizeof(int) * CHAR_BIT == 32 &&
395 		    sizeof(long) * CHAR_BIT == 64 &&
396 		    sizeof(void *) * CHAR_BIT == 64 &&
397 		    sizeof(off_t) * CHAR_BIT == 64)
398 			return 1;
399 		else
400 			return -1;
401 #else
402 		return (_POSIX_V7_LP64_OFF64);
403 #endif
404 	case _SC_V7_LPBIG_OFFBIG:
405 #if _POSIX_V7_LPBIG_OFFBIG == 0
406 		if (sizeof(int) * CHAR_BIT >= 32 &&
407 		    sizeof(long) * CHAR_BIT >= 64 &&
408 		    sizeof(void *) * CHAR_BIT >= 64 &&
409 		    sizeof(off_t) * CHAR_BIT >= 64)
410 			return 1;
411 		else
412 			return -1;
413 #else
414 		return (_POSIX_V7_LPBIG_OFFBIG);
415 #endif
416 	case _SC_XOPEN_CRYPT:
417 		return (_XOPEN_CRYPT);
418 	case _SC_XOPEN_ENH_I18N:
419 		return (_XOPEN_ENH_I18N);
420 	case _SC_XOPEN_LEGACY:
421 		return (_XOPEN_LEGACY);
422 	case _SC_XOPEN_REALTIME:
423 		return (_XOPEN_REALTIME);
424 	case _SC_XOPEN_REALTIME_THREADS:
425 		return (_XOPEN_REALTIME_THREADS);
426 	case _SC_XOPEN_STREAMS:
427 		return (_XOPEN_STREAMS);
428 	case _SC_XOPEN_UNIX:
429 		return (_XOPEN_UNIX);
430 	case _SC_XOPEN_UUCP:
431 		return (_XOPEN_UUCP);
432 #ifdef _XOPEN_VERSION
433 	case _SC_XOPEN_VERSION:
434 		return (_XOPEN_VERSION);
435 #endif
436 
437 /* Extensions */
438 	case _SC_PHYS_PAGES:
439 	{
440 		int64_t physmem;
441 
442 		mib[0] = CTL_HW;
443 		mib[1] = HW_PHYSMEM64;
444 		len = sizeof(physmem);
445 		if (sysctl(mib, namelen, &physmem, &len, NULL, 0) == -1)
446 			return (-1);
447 		return (physmem / getpagesize());
448 	}
449 	case _SC_AVPHYS_PAGES:
450 	{
451 		struct vmtotal vmtotal;
452 
453 		mib[0] = CTL_VM;
454 		mib[1] = VM_METER;
455 		len = sizeof(vmtotal);
456 		if (sysctl(mib, namelen, &vmtotal, &len, NULL, 0) == -1)
457 			return (-1);
458 		return (vmtotal.t_free);
459 	}
460 
461 	case _SC_NPROCESSORS_CONF:
462 		mib[0] = CTL_HW;
463 		mib[1] = HW_NCPU;
464 		break;
465 	case _SC_NPROCESSORS_ONLN:
466 		mib[0] = CTL_HW;
467 		mib[1] = HW_NCPU;
468 		break;
469 
470 	default:
471 		errno = EINVAL;
472 		return (-1);
473 	}
474 	return (sysctl(mib, namelen, &value, &len, NULL, 0) == -1 ? -1 : value);
475 }
476