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 */
60long
61sysconf(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}
478DEF_WEAK(sysconf);
479