1/*	$NetBSD: sysconf.c,v 1.44 2023/10/25 08:19:34 simonb Exp $	*/
2
3/*-
4 * Copyright (c) 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Sean Eric Fagan of Cygnus Support.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)sysconf.c	8.2 (Berkeley) 3/20/94";
39#else
40__RCSID("$NetBSD: sysconf.c,v 1.44 2023/10/25 08:19:34 simonb Exp $");
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include "namespace.h"
45#include <sys/param.h>
46#include <sys/sysctl.h>
47#include <sys/time.h>
48#include <sys/resource.h>
49#include <uvm/uvm_extern.h>
50
51#include <errno.h>
52#include <limits.h>
53#include <time.h>
54#include <unistd.h>
55#include <paths.h>
56#include <pwd.h>
57
58#ifdef __weak_alias
59__weak_alias(sysconf,__sysconf)
60#endif
61
62/*
63 * sysconf --
64 *	get configurable system variables.
65 *
66 * XXX
67 * POSIX 1003.1 (ISO/IEC 9945-1, 4.8.1.3) states that the variable values
68 * not change during the lifetime of the calling process.  This would seem
69 * to require that any change to system limits kill all running processes.
70 * A workaround might be to cache the values when they are first retrieved
71 * and then simply return the cached value on subsequent calls.  This is
72 * less useful than returning up-to-date values, however.
73 */
74long
75sysconf(int name)
76{
77	struct rlimit rl;
78	size_t len;
79	uint64_t mem;
80	int mib[CTL_MAXNAME], value;
81	unsigned int mib_len;
82	struct clockinfo tmpclock;
83	struct uvmexp_sysctl uvmexp;
84	static int clk_tck;
85
86	len = sizeof(value);
87
88	/* Default length of the MIB */
89	mib_len = 2;
90
91	switch (name) {
92
93/* 1003.1 */
94	case _SC_ARG_MAX:
95		mib[0] = CTL_KERN;
96		mib[1] = KERN_ARGMAX;
97		break;
98	case _SC_CHILD_MAX:
99		return (getrlimit(RLIMIT_NPROC, &rl) ? -1 : (long)rl.rlim_cur);
100	case _O_SC_CLK_TCK:
101		/*
102		 * For applications compiled when CLK_TCK was a compile-time
103		 * constant.
104		 */
105		return 100;
106	case _SC_CLK_TCK:
107		/*
108		 * Has to be handled specially because it returns a
109		 * struct clockinfo instead of an integer. Also, since
110		 * this might be called often by some things that
111		 * don't grok CLK_TCK can be a macro expanding to a
112		 * function, cache the value.
113		 */
114		if (clk_tck == 0) {
115			mib[0] = CTL_KERN;
116			mib[1] = KERN_CLOCKRATE;
117			len = sizeof(struct clockinfo);
118			clk_tck = sysctl(mib, 2, &tmpclock, &len, NULL, 0)
119			    == -1 ? -1 : tmpclock.hz;
120		}
121		return(clk_tck);
122	case _SC_JOB_CONTROL:
123		mib[0] = CTL_KERN;
124		mib[1] = KERN_JOB_CONTROL;
125		goto yesno;
126	case _SC_NGROUPS_MAX:
127		mib[0] = CTL_KERN;
128		mib[1] = KERN_NGROUPS;
129		break;
130	case _SC_OPEN_MAX:
131		return (getrlimit(RLIMIT_NOFILE, &rl) ? -1 : (long)rl.rlim_cur);
132	case _SC_STREAM_MAX:
133		mib[0] = CTL_USER;
134		mib[1] = USER_STREAM_MAX;
135		break;
136	case _SC_TZNAME_MAX:
137		mib[0] = CTL_USER;
138		mib[1] = USER_TZNAME_MAX;
139		break;
140	case _SC_SAVED_IDS:
141		mib[0] = CTL_KERN;
142		mib[1] = KERN_SAVED_IDS;
143		goto yesno;
144	case _SC_VERSION:
145		mib[0] = CTL_KERN;
146		mib[1] = KERN_POSIX1;
147		break;
148
149/* 1003.1b */
150	case _SC_PAGESIZE:
151		return _getpagesize();
152	case _SC_FSYNC:
153		mib[0] = CTL_KERN;
154		mib[1] = KERN_FSYNC;
155		goto yesno;
156	case _SC_SYNCHRONIZED_IO:
157		mib[0] = CTL_KERN;
158		mib[1] = KERN_SYNCHRONIZED_IO;
159		goto yesno;
160	case _SC_MAPPED_FILES:
161		mib[0] = CTL_KERN;
162		mib[1] = KERN_MAPPED_FILES;
163		goto yesno;
164	case _SC_MEMLOCK:
165		mib[0] = CTL_KERN;
166		mib[1] = KERN_MEMLOCK;
167		goto yesno;
168	case _SC_MEMLOCK_RANGE:
169		mib[0] = CTL_KERN;
170		mib[1] = KERN_MEMLOCK_RANGE;
171		goto yesno;
172	case _SC_MEMORY_PROTECTION:
173		mib[0] = CTL_KERN;
174		mib[1] = KERN_MEMORY_PROTECTION;
175		goto yesno;
176	case _SC_MONOTONIC_CLOCK:
177		mib[0] = CTL_KERN;
178		mib[1] = KERN_MONOTONIC_CLOCK;
179		goto yesno;
180	case _SC_SEMAPHORES:
181		mib[0] = CTL_KERN;
182		mib[1] = KERN_POSIX_SEMAPHORES;
183		goto yesno;
184	case _SC_TIMERS:
185		mib[0] = CTL_KERN;
186		mib[1] = KERN_POSIX_TIMERS;
187		goto yesno;
188
189/* 1003.1c */
190	case _SC_LOGIN_NAME_MAX:
191		mib[0] = CTL_KERN;
192		mib[1] = KERN_LOGIN_NAME_MAX;
193		break;
194	case _SC_THREADS:
195		mib[0] = CTL_KERN;
196		mib[1] = KERN_POSIX_THREADS;
197		goto yesno;
198
199/* 1003.1j */
200	case _SC_BARRIERS:
201		mib[0] = CTL_KERN;
202		mib[1] = KERN_POSIX_BARRIERS;
203		goto yesno;
204	case _SC_SPIN_LOCKS:
205		mib[0] = CTL_KERN;
206		mib[1] = KERN_POSIX_SPIN_LOCKS;
207		goto yesno;
208	/* Historical; Threads option in 1003.1-2001 */
209	case _SC_READER_WRITER_LOCKS:
210		mib[0] = CTL_KERN;
211		mib[1] = KERN_POSIX_READER_WRITER_LOCKS;
212		goto yesno;
213
214/* 1003.2 */
215	case _SC_BC_BASE_MAX:
216		mib[0] = CTL_USER;
217		mib[1] = USER_BC_BASE_MAX;
218		break;
219	case _SC_BC_DIM_MAX:
220		mib[0] = CTL_USER;
221		mib[1] = USER_BC_DIM_MAX;
222		break;
223	case _SC_BC_SCALE_MAX:
224		mib[0] = CTL_USER;
225		mib[1] = USER_BC_SCALE_MAX;
226		break;
227	case _SC_BC_STRING_MAX:
228		mib[0] = CTL_USER;
229		mib[1] = USER_BC_STRING_MAX;
230		break;
231	case _SC_COLL_WEIGHTS_MAX:
232		mib[0] = CTL_USER;
233		mib[1] = USER_COLL_WEIGHTS_MAX;
234		break;
235	case _SC_EXPR_NEST_MAX:
236		mib[0] = CTL_USER;
237		mib[1] = USER_EXPR_NEST_MAX;
238		break;
239	case _SC_LINE_MAX:
240		mib[0] = CTL_USER;
241		mib[1] = USER_LINE_MAX;
242		break;
243	case _SC_RE_DUP_MAX:
244		mib[0] = CTL_USER;
245		mib[1] = USER_RE_DUP_MAX;
246		break;
247	case _SC_2_VERSION:
248		mib[0] = CTL_USER;
249		mib[1] = USER_POSIX2_VERSION;
250		break;
251	case _SC_2_C_BIND:
252		mib[0] = CTL_USER;
253		mib[1] = USER_POSIX2_C_BIND;
254		goto yesno;
255	case _SC_2_C_DEV:
256		mib[0] = CTL_USER;
257		mib[1] = USER_POSIX2_C_DEV;
258		goto yesno;
259	case _SC_2_CHAR_TERM:
260		mib[0] = CTL_USER;
261		mib[1] = USER_POSIX2_CHAR_TERM;
262		goto yesno;
263	case _SC_2_FORT_DEV:
264		mib[0] = CTL_USER;
265		mib[1] = USER_POSIX2_FORT_DEV;
266		goto yesno;
267	case _SC_2_FORT_RUN:
268		mib[0] = CTL_USER;
269		mib[1] = USER_POSIX2_FORT_RUN;
270		goto yesno;
271	case _SC_2_LOCALEDEF:
272		mib[0] = CTL_USER;
273		mib[1] = USER_POSIX2_LOCALEDEF;
274		goto yesno;
275	case _SC_2_SW_DEV:
276		mib[0] = CTL_USER;
277		mib[1] = USER_POSIX2_SW_DEV;
278		goto yesno;
279	case _SC_2_UPE:
280		mib[0] = CTL_USER;
281		mib[1] = USER_POSIX2_UPE;
282		goto yesno;
283
284/* XPG 4.2 */
285	case _SC_IOV_MAX:
286		mib[0] = CTL_KERN;
287		mib[1] = KERN_IOV_MAX;
288		break;
289	case _SC_XOPEN_SHM:
290		mib[0] = CTL_KERN;
291		mib[1] = KERN_SYSVIPC;
292		mib[2] = KERN_SYSVIPC_SHM;
293		mib_len = 3;
294		goto yesno;
295
296/* 1003.1-2001, XSI Option Group */
297	case _SC_AIO_LISTIO_MAX:
298		if (sysctlgetmibinfo("kern.aio_listio_max", &mib[0], &mib_len,
299		    NULL, NULL, NULL, SYSCTL_VERSION))
300			return -1;
301		break;
302	case _SC_AIO_MAX:
303		if (sysctlgetmibinfo("kern.aio_max", &mib[0], &mib_len,
304		    NULL, NULL, NULL, SYSCTL_VERSION))
305			return -1;
306		break;
307	case _SC_ASYNCHRONOUS_IO:
308		if (sysctlgetmibinfo("kern.posix_aio", &mib[0], &mib_len,
309		    NULL, NULL, NULL, SYSCTL_VERSION))
310			return -1;
311		goto yesno;
312	case _SC_MESSAGE_PASSING:
313		if (sysctlgetmibinfo("kern.posix_msg", &mib[0], &mib_len,
314		    NULL, NULL, NULL, SYSCTL_VERSION))
315			return -1;
316		goto yesno;
317	case _SC_MQ_OPEN_MAX:
318		if (sysctlgetmibinfo("kern.mqueue.mq_open_max", &mib[0],
319		    &mib_len, NULL, NULL, NULL, SYSCTL_VERSION))
320			return -1;
321		break;
322	case _SC_MQ_PRIO_MAX:
323		if (sysctlgetmibinfo("kern.mqueue.mq_prio_max", &mib[0],
324		    &mib_len, NULL, NULL, NULL, SYSCTL_VERSION))
325			return -1;
326		break;
327	case _SC_PRIORITY_SCHEDULING:
328		if (sysctlgetmibinfo("kern.posix_sched", &mib[0], &mib_len,
329		    NULL, NULL, NULL, SYSCTL_VERSION))
330			return -1;
331		goto yesno;
332	case _SC_ATEXIT_MAX:
333		mib[0] = CTL_USER;
334		mib[1] = USER_ATEXIT_MAX;
335		break;
336
337/* 1003.1-2001, TSF */
338	case _SC_GETGR_R_SIZE_MAX:
339		return _GETGR_R_SIZE_MAX;
340	case _SC_GETPW_R_SIZE_MAX:
341		return _GETPW_R_SIZE_MAX;
342
343/* Unsorted */
344	case _SC_RTSIG_MAX:
345		return SIGRTMAX - SIGRTMIN;
346	case _SC_HOST_NAME_MAX:
347		return MAXHOSTNAMELEN;
348	case _SC_PASS_MAX:
349		return _PASSWORD_LEN;
350	case _SC_REGEXP:
351		return _POSIX_REGEXP;
352	case _SC_SHARED_MEMORY_OBJECTS:
353		return _POSIX_SHARED_MEMORY_OBJECTS;
354	case _SC_SHELL:
355		return _POSIX_SHELL;
356	case _SC_SPAWN:
357		return _POSIX_SPAWN;
358	case _SC_SYMLOOP_MAX:
359		return MAXSYMLINKS;
360
361yesno:		if (sysctl(mib, mib_len, &value, &len, NULL, 0) == -1)
362			return (-1);
363		if (value == 0)
364			return (-1);
365		return (value);
366
367/* Extensions */
368	case _SC_NPROCESSORS_CONF:
369		mib[0] = CTL_HW;
370		mib[1] = HW_NCPU;
371		break;
372	case _SC_NPROCESSORS_ONLN:
373		mib[0] = CTL_HW;
374		mib[1] = HW_NCPUONLINE;
375		break;
376
377/* Linux/Solaris */
378	case _SC_PHYS_PAGES:
379		len = sizeof(mem);
380		mib[0] = CTL_HW;
381		mib[1] = HW_PHYSMEM64;
382		return sysctl(mib, 2, &mem, &len, NULL, 0) == -1 ? -1 :
383		    (long)(mem / _getpagesize());
384
385	case _SC_AVPHYS_PAGES:
386		len = sizeof(uvmexp);
387		mib[0] = CTL_VM;
388		mib[1] = VM_UVMEXP2;
389		return sysctl(mib, 2, &uvmexp, &len, NULL, 0) == -1 ? -1 :
390		    (long)(uvmexp.free);
391
392/* Native */
393	case _SC_SCHED_RT_TS:
394		if (sysctlgetmibinfo("kern.sched.rtts", &mib[0], &mib_len,
395		    NULL, NULL, NULL, SYSCTL_VERSION))
396			return -1;
397		break;
398	case _SC_SCHED_PRI_MIN:
399		if (sysctlgetmibinfo("kern.sched.pri_min", &mib[0], &mib_len,
400		    NULL, NULL, NULL, SYSCTL_VERSION))
401			return -1;
402		break;
403	case _SC_SCHED_PRI_MAX:
404		if (sysctlgetmibinfo("kern.sched.pri_max", &mib[0], &mib_len,
405		    NULL, NULL, NULL, SYSCTL_VERSION))
406			return -1;
407		break;
408	case _SC_THREAD_DESTRUCTOR_ITERATIONS:
409		return _POSIX_THREAD_DESTRUCTOR_ITERATIONS;
410	case _SC_THREAD_KEYS_MAX:
411		return _POSIX_THREAD_KEYS_MAX;
412	case _SC_THREAD_STACK_MIN:
413		return _getpagesize();
414	case _SC_THREAD_THREADS_MAX:
415		if (sysctlgetmibinfo("kern.maxproc", &mib[0], &mib_len,
416		    NULL, NULL, NULL, SYSCTL_VERSION))	/* XXX */
417			return -1;
418		goto yesno;
419	case _SC_THREAD_ATTR_STACKADDR:
420		return _POSIX_THREAD_ATTR_STACKADDR;
421	case _SC_THREAD_ATTR_STACKSIZE:
422		return _POSIX_THREAD_ATTR_STACKSIZE;
423	case _SC_THREAD_SAFE_FUNCTIONS:
424		return _POSIX_THREAD_SAFE_FUNCTIONS;
425	case _SC_THREAD_PRIO_PROTECT:
426		return _POSIX_THREAD_PRIO_PROTECT;
427	case _SC_THREAD_PRIORITY_SCHEDULING:
428	case _SC_THREAD_PRIO_INHERIT:
429	case _SC_THREAD_PROCESS_SHARED:
430		return -1;
431	case _SC_TTY_NAME_MAX:
432		return pathconf(_PATH_DEV, _PC_NAME_MAX);
433	case _SC_TIMER_MAX:
434		return _POSIX_TIMER_MAX;
435	case _SC_SEM_NSEMS_MAX:
436		return LONG_MAX;
437	case _SC_CPUTIME:
438		return _POSIX_CPUTIME;
439	case _SC_THREAD_CPUTIME:
440		return _POSIX_THREAD_CPUTIME;
441	case _SC_DELAYTIMER_MAX:
442		return _POSIX_DELAYTIMER_MAX;
443	case _SC_SIGQUEUE_MAX:
444		return _POSIX_SIGQUEUE_MAX;
445	case _SC_REALTIME_SIGNALS:
446		return 200112L;
447	default:
448		errno = EINVAL;
449		return (-1);
450	}
451	return (sysctl(mib, mib_len, &value, &len, NULL, 0) == -1 ? -1 : value);
452}
453