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