sysconf.c revision 168718
1/*-
2 * Copyright (c) 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Sean Eric Fagan of Cygnus Support.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char sccsid[] = "@(#)sysconf.c	8.2 (Berkeley) 3/20/94";
35#endif /* LIBC_SCCS and not lint */
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/lib/libc/gen/sysconf.c 168718 2007-04-14 13:06:57Z pjd $");
38
39#include <sys/param.h>
40#include <sys/time.h>
41#include <sys/sysctl.h>
42#include <sys/resource.h>
43#include <sys/socket.h>
44
45#include <errno.h>
46#include <limits.h>
47#include <paths.h>
48#include <pthread.h>		/* we just need the limits */
49#include <time.h>
50#include <unistd.h>
51
52#include "../stdlib/atexit.h"
53#include "../stdtime/tzfile.h"
54
55#define	_PATH_ZONEINFO	TZDIR	/* from tzfile.h */
56
57/*
58 * sysconf --
59 *	get configurable system variables.
60 *
61 * XXX
62 * POSIX 1003.1 (ISO/IEC 9945-1, 4.8.1.3) states that the variable values
63 * not change during the lifetime of the calling process.  This would seem
64 * to require that any change to system limits kill all running processes.
65 * A workaround might be to cache the values when they are first retrieved
66 * and then simply return the cached value on subsequent calls.  This is
67 * less useful than returning up-to-date values, however.
68 */
69long
70sysconf(name)
71	int name;
72{
73	struct rlimit rl;
74	size_t len;
75	int mib[2], sverrno, value;
76	long lvalue, defaultresult;
77	const char *path;
78
79	defaultresult = -1;
80
81	switch (name) {
82	case _SC_ARG_MAX:
83		mib[0] = CTL_KERN;
84		mib[1] = KERN_ARGMAX;
85		break;
86	case _SC_CHILD_MAX:
87		if (getrlimit(RLIMIT_NPROC, &rl) != 0)
88			return (-1);
89		if (rl.rlim_cur == RLIM_INFINITY)
90			return (-1);
91		if (rl.rlim_cur > LONG_MAX) {
92			errno = EOVERFLOW;
93			return (-1);
94		}
95		return ((long)rl.rlim_cur);
96	case _SC_CLK_TCK:
97		return (CLK_TCK);
98	case _SC_NGROUPS_MAX:
99		mib[0] = CTL_KERN;
100		mib[1] = KERN_NGROUPS;
101		break;
102	case _SC_OPEN_MAX:
103	case _SC_STREAM_MAX:	/* assume fds run out before memory does */
104		if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
105			return (-1);
106		if (rl.rlim_cur == RLIM_INFINITY)
107			return (-1);
108		if (rl.rlim_cur > LONG_MAX) {
109			errno = EOVERFLOW;
110			return (-1);
111		}
112		return ((long)rl.rlim_cur);
113	case _SC_JOB_CONTROL:
114		return (_POSIX_JOB_CONTROL);
115	case _SC_SAVED_IDS:
116		/* XXX - must be 1 */
117		mib[0] = CTL_KERN;
118		mib[1] = KERN_SAVED_IDS;
119		goto yesno;
120	case _SC_VERSION:
121		mib[0] = CTL_KERN;
122		mib[1] = KERN_POSIX1;
123		break;
124	case _SC_BC_BASE_MAX:
125		return (BC_BASE_MAX);
126	case _SC_BC_DIM_MAX:
127		return (BC_DIM_MAX);
128	case _SC_BC_SCALE_MAX:
129		return (BC_SCALE_MAX);
130	case _SC_BC_STRING_MAX:
131		return (BC_STRING_MAX);
132	case _SC_COLL_WEIGHTS_MAX:
133		return (COLL_WEIGHTS_MAX);
134	case _SC_EXPR_NEST_MAX:
135		return (EXPR_NEST_MAX);
136	case _SC_LINE_MAX:
137		return (LINE_MAX);
138	case _SC_RE_DUP_MAX:
139		return (RE_DUP_MAX);
140	case _SC_2_VERSION:
141		/*
142		 * This is something of a lie, but it would be silly at
143		 * this point to try to deduce this from the contents
144		 * of the filesystem.
145		 */
146		return (_POSIX2_VERSION);
147	case _SC_2_C_BIND:
148		return (_POSIX2_C_BIND);
149	case _SC_2_C_DEV:
150		return (_POSIX2_C_DEV);
151	case _SC_2_CHAR_TERM:
152		return (_POSIX2_CHAR_TERM);
153	case _SC_2_FORT_DEV:
154		return (_POSIX2_FORT_DEV);
155	case _SC_2_FORT_RUN:
156		return (_POSIX2_FORT_RUN);
157	case _SC_2_LOCALEDEF:
158		return (_POSIX2_LOCALEDEF);
159	case _SC_2_SW_DEV:
160		return (_POSIX2_SW_DEV);
161	case _SC_2_UPE:
162		return (_POSIX2_UPE);
163	case _SC_TZNAME_MAX:
164		path = _PATH_ZONEINFO;
165do_NAME_MAX:
166		sverrno = errno;
167		errno = 0;
168		lvalue = pathconf(path, _PC_NAME_MAX);
169		if (lvalue == -1 && errno != 0)
170			return (-1);
171		errno = sverrno;
172		return (lvalue);
173
174	case _SC_ASYNCHRONOUS_IO:
175#if _POSIX_ASYNCHRONOUS_IO == 0
176		mib[0] = CTL_P1003_1B;
177		mib[1] = CTL_P1003_1B_ASYNCHRONOUS_IO;
178		break;
179#else
180		return (_POSIX_ASYNCHRONOUS_IO);
181#endif
182	case _SC_MAPPED_FILES:
183		return (_POSIX_MAPPED_FILES);
184	case _SC_MEMLOCK:
185		return (_POSIX_MEMLOCK);
186	case _SC_MEMLOCK_RANGE:
187		return (_POSIX_MEMLOCK_RANGE);
188	case _SC_MEMORY_PROTECTION:
189		return (_POSIX_MEMORY_PROTECTION);
190	case _SC_MESSAGE_PASSING:
191#if _POSIX_MESSAGE_PASSING == 0
192		mib[0] = CTL_P1003_1B;
193		mib[1] = CTL_P1003_1B_MESSAGE_PASSING;
194		goto yesno;
195#else
196		return (_POSIX_MESSAGE_PASSING);
197#endif
198	case _SC_PRIORITIZED_IO:
199#if _POSIX_PRIORITIZED_IO == 0
200		mib[0] = CTL_P1003_1B;
201		mib[1] = CTL_P1003_1B_PRIORITIZED_IO;
202		goto yesno;
203#else
204		return (_POSIX_PRIORITIZED_IO);
205#endif
206	case _SC_PRIORITY_SCHEDULING:
207#if _POSIX_PRIORITY_SCHEDULING == 0
208		mib[0] = CTL_P1003_1B;
209		mib[1] = CTL_P1003_1B_PRIORITY_SCHEDULING;
210		goto yesno;
211#else
212		return (_POSIX_PRIORITY_SCHEDULING);
213#endif
214	case _SC_REALTIME_SIGNALS:
215#if _POSIX_REALTIME_SIGNALS == 0
216		mib[0] = CTL_P1003_1B;
217		mib[1] = CTL_P1003_1B_REALTIME_SIGNALS;
218		goto yesno;
219#else
220		return (_POSIX_REALTIME_SIGNALS);
221#endif
222	case _SC_SEMAPHORES:
223#if _POSIX_SEMAPHORES == 0
224		mib[0] = CTL_P1003_1B;
225		mib[1] = CTL_P1003_1B_SEMAPHORES;
226		goto yesno;
227#else
228		return (_POSIX_SEMAPHORES);
229#endif
230	case _SC_FSYNC:
231		return (_POSIX_FSYNC);
232
233	case _SC_SHARED_MEMORY_OBJECTS:
234		return (_POSIX_SHARED_MEMORY_OBJECTS);
235	case _SC_SYNCHRONIZED_IO:
236#if _POSIX_SYNCHRONIZED_IO == 0
237		mib[0] = CTL_P1003_1B;
238		mib[1] = CTL_P1003_1B_SYNCHRONIZED_IO;
239		goto yesno;
240#else
241		return (_POSIX_SYNCHRONIZED_IO);
242#endif
243	case _SC_TIMERS:
244#if _POSIX_TIMERS == 0
245		mib[0] = CTL_P1003_1B;
246		mib[1] = CTL_P1003_1B_TIMERS;
247		goto yesno;
248#else
249		return (_POSIX_TIMERS);
250#endif
251	case _SC_AIO_LISTIO_MAX:
252		mib[0] = CTL_P1003_1B;
253		mib[1] = CTL_P1003_1B_AIO_LISTIO_MAX;
254		break;
255	case _SC_AIO_MAX:
256		mib[0] = CTL_P1003_1B;
257		mib[1] = CTL_P1003_1B_AIO_MAX;
258		break;
259	case _SC_AIO_PRIO_DELTA_MAX:
260		mib[0] = CTL_P1003_1B;
261		mib[1] = CTL_P1003_1B_AIO_PRIO_DELTA_MAX;
262		break;
263	case _SC_DELAYTIMER_MAX:
264		mib[0] = CTL_P1003_1B;
265		mib[1] = CTL_P1003_1B_DELAYTIMER_MAX;
266		goto yesno;
267	case _SC_MQ_OPEN_MAX:
268		mib[0] = CTL_P1003_1B;
269		mib[1] = CTL_P1003_1B_MQ_OPEN_MAX;
270		goto yesno;
271	case _SC_PAGESIZE:
272		defaultresult = getpagesize();
273		mib[0] = CTL_P1003_1B;
274		mib[1] = CTL_P1003_1B_PAGESIZE;
275		goto yesno;
276	case _SC_RTSIG_MAX:
277		mib[0] = CTL_P1003_1B;
278		mib[1] = CTL_P1003_1B_RTSIG_MAX;
279		goto yesno;
280	case _SC_SEM_NSEMS_MAX:
281		mib[0] = CTL_P1003_1B;
282		mib[1] = CTL_P1003_1B_SEM_NSEMS_MAX;
283		goto yesno;
284	case _SC_SEM_VALUE_MAX:
285		mib[0] = CTL_P1003_1B;
286		mib[1] = CTL_P1003_1B_SEM_VALUE_MAX;
287		goto yesno;
288	case _SC_SIGQUEUE_MAX:
289		mib[0] = CTL_P1003_1B;
290		mib[1] = CTL_P1003_1B_SIGQUEUE_MAX;
291		goto yesno;
292	case _SC_TIMER_MAX:
293		mib[0] = CTL_P1003_1B;
294		mib[1] = CTL_P1003_1B_TIMER_MAX;
295yesno:
296		len = sizeof(value);
297		if (sysctl(mib, 2, &value, &len, NULL, 0) == -1)
298			return (-1);
299		if (value == 0)
300			return (defaultresult);
301		return ((long)value);
302
303	case _SC_2_PBS:
304	case _SC_2_PBS_ACCOUNTING:
305	case _SC_2_PBS_CHECKPOINT:
306	case _SC_2_PBS_LOCATE:
307	case _SC_2_PBS_MESSAGE:
308	case _SC_2_PBS_TRACK:
309#if _POSIX2_PBS == 0
310#error "don't know how to determine _SC_2_PBS"
311		/*
312		 * This probably requires digging through the filesystem
313		 * to see if the appropriate package has been installed.
314		 * Since we don't currently support this option at all,
315		 * it's not worth the effort to write the code now.
316		 * Figuring out which of the sub-options are supported
317		 * would be even more difficult, so it's probably easier
318		 * to always say ``no''.
319		 */
320#else
321		return (_POSIX2_PBS);
322#endif
323	case _SC_ADVISORY_INFO:
324#if _POSIX_ADVISORY_INFO == 0
325#error "_POSIX_ADVISORY_INFO"
326#else
327		return (_POSIX_ADVISORY_INFO);
328#endif
329	case _SC_BARRIERS:
330#if _POSIX_BARRIERS == 0
331#error "_POSIX_BARRIERS"
332#else
333		return (_POSIX_BARRIERS);
334#endif
335	case _SC_CLOCK_SELECTION:
336#if _POSIX_CLOCK_SELECTION == 0
337#error "_POSIX_CLOCK_SELECTION"
338#else
339		return (_POSIX_CLOCK_SELECTION);
340#endif
341	case _SC_CPUTIME:
342#if _POSIX_CPUTIME == 0
343#error "_POSIX_CPUTIME"
344#else
345		return (_POSIX_CPUTIME);
346#endif
347#ifdef notdef
348	case _SC_FILE_LOCKING:
349		/*
350		 * XXX - The standard doesn't tell us how to define
351		 * _POSIX_FILE_LOCKING, so we can't answer this one.
352		 */
353#endif
354#if _POSIX_THREAD_SAFE_FUNCTIONS > -1
355	case _SC_GETGR_R_SIZE_MAX:
356	case _SC_GETPW_R_SIZE_MAX:
357#error "somebody needs to implement this"
358#endif
359	case _SC_HOST_NAME_MAX:
360		return (MAXHOSTNAMELEN - 1); /* does not include \0 */
361	case _SC_LOGIN_NAME_MAX:
362		return (MAXLOGNAME);
363	case _SC_MONOTONIC_CLOCK:
364#if _POSIX_MONOTONIC_CLOCK == 0
365#error "_POSIX_MONOTONIC_CLOCK"
366#else
367		return (_POSIX_MONOTONIC_CLOCK);
368#endif
369#if _POSIX_MESSAGE_PASSING > -1
370	case _SC_MQ_PRIO_MAX:
371		return (MQ_PRIO_MAX);
372#endif
373	case _SC_READER_WRITER_LOCKS:
374		return (_POSIX_READER_WRITER_LOCKS);
375	case _SC_REGEXP:
376		return (_POSIX_REGEXP);
377	case _SC_SHELL:
378		return (_POSIX_SHELL);
379	case _SC_SPAWN:
380		return (_POSIX_SPAWN);
381	case _SC_SPIN_LOCKS:
382		return (_POSIX_SPIN_LOCKS);
383	case _SC_SPORADIC_SERVER:
384#if _POSIX_SPORADIC_SERVER == 0
385#error "_POSIX_SPORADIC_SERVER"
386#else
387		return (_POSIX_SPORADIC_SERVER);
388#endif
389	case _SC_THREAD_ATTR_STACKADDR:
390		return (_POSIX_THREAD_ATTR_STACKADDR);
391	case _SC_THREAD_ATTR_STACKSIZE:
392		return (_POSIX_THREAD_ATTR_STACKSIZE);
393	case _SC_THREAD_CPUTIME:
394		return (_POSIX_THREAD_CPUTIME);
395	case _SC_THREAD_DESTRUCTOR_ITERATIONS:
396		return (PTHREAD_DESTRUCTOR_ITERATIONS);
397	case _SC_THREAD_KEYS_MAX:
398		return (PTHREAD_KEYS_MAX);
399	case _SC_THREAD_PRIO_INHERIT:
400		return (_POSIX_THREAD_PRIO_INHERIT);
401	case _SC_THREAD_PRIO_PROTECT:
402		return (_POSIX_THREAD_PRIO_PROTECT);
403	case _SC_THREAD_PRIORITY_SCHEDULING:
404		return (_POSIX_THREAD_PRIORITY_SCHEDULING);
405	case _SC_THREAD_PROCESS_SHARED:
406		return (_POSIX_THREAD_PROCESS_SHARED);
407	case _SC_THREAD_SAFE_FUNCTIONS:
408		return (_POSIX_THREAD_SAFE_FUNCTIONS);
409	case _SC_THREAD_STACK_MIN:
410		return (PTHREAD_STACK_MIN);
411	case _SC_THREAD_THREADS_MAX:
412		return (PTHREAD_THREADS_MAX); /* XXX wrong type! */
413	case _SC_TIMEOUTS:
414		return (_POSIX_TIMEOUTS);
415	case _SC_THREADS:
416		return (_POSIX_THREADS);
417	case _SC_TRACE:
418#if _POSIX_TRACE == 0
419#error "_POSIX_TRACE"
420		/* While you're implementing this, also do the ones below. */
421#else
422		return (_POSIX_TRACE);
423#endif
424#if _POSIX_TRACE > -1
425	case _SC_TRACE_EVENT_FILTER:
426		return (_POSIX_TRACE_EVENT_FILTER);
427	case _SC_TRACE_INHERIT:
428		return (_POSIX_TRACE_INHERIT);
429	case _SC_TRACE_LOG:
430		return (_POSIX_TRACE_LOG);
431#endif
432	case _SC_TTY_NAME_MAX:
433		path = _PATH_DEV;
434		goto do_NAME_MAX;
435	case _SC_TYPED_MEMORY_OBJECTS:
436#if _POSIX_TYPED_MEMORY_OBJECTS == 0
437#error "_POSIX_TYPED_MEMORY_OBJECTS"
438#else
439		return (_POSIX_TYPED_MEMORY_OBJECTS);
440#endif
441	case _SC_V6_ILP32_OFF32:
442#if _V6_ILP32_OFF32 == 0
443		if (sizeof(int) * CHAR_BIT == 32 &&
444		    sizeof(int) == sizeof(long) &&
445		    sizeof(long) == sizeof(void *) &&
446		    sizeof(void *) == sizeof(off_t))
447			return 1;
448		else
449			return -1;
450#else
451		return (_V6_ILP32_OFF32);
452#endif
453	case _SC_V6_ILP32_OFFBIG:
454#if _V6_ILP32_OFFBIG == 0
455		if (sizeof(int) * CHAR_BIT == 32 &&
456		    sizeof(int) == sizeof(long) &&
457		    sizeof(long) == sizeof(void *) &&
458		    sizeof(off_t) * CHAR_BIT >= 64)
459			return 1;
460		else
461			return -1;
462#else
463		return (_V6_ILP32_OFFBIG);
464#endif
465	case _SC_V6_LP64_OFF64:
466#if _V6_LP64_OFF64 == 0
467		if (sizeof(int) * CHAR_BIT == 32 &&
468		    sizeof(long) * CHAR_BIT == 64 &&
469		    sizeof(long) == sizeof(void *) &&
470		    sizeof(void *) == sizeof(off_t))
471			return 1;
472		else
473			return -1;
474#else
475		return (_V6_LP64_OFF64);
476#endif
477	case _SC_V6_LPBIG_OFFBIG:
478#if _V6_LPBIG_OFFBIG == 0
479		if (sizeof(int) * CHAR_BIT >= 32 &&
480		    sizeof(long) * CHAR_BIT >= 64 &&
481		    sizeof(void *) * CHAR_BIT >= 64 &&
482		    sizeof(off_t) * CHAR_BIT >= 64)
483			return 1;
484		else
485			return -1;
486#else
487		return (_V6_LPBIG_OFFBIG);
488#endif
489	case _SC_ATEXIT_MAX:
490		return (ATEXIT_SIZE);
491	case _SC_IOV_MAX:
492		mib[0] = CTL_KERN;
493		mib[1] = KERN_IOV_MAX;
494		break;
495	case _SC_XOPEN_CRYPT:
496		return (_XOPEN_CRYPT);
497	case _SC_XOPEN_ENH_I18N:
498		return (_XOPEN_ENH_I18N);
499	case _SC_XOPEN_LEGACY:
500		return (_XOPEN_LEGACY);
501	case _SC_XOPEN_REALTIME:
502#if _XOPEN_REALTIME == 0
503		sverrno = errno;
504		value = sysconf(_SC_ASYNCHRONOUS_IO) > 0 &&
505			sysconf(_SC_MEMLOCK) > 0 &&
506			sysconf(_SC_MEMLOCK_RANGE) > 0 &&
507			sysconf(_SC_MESSAGE_PASSING) > 0 &&
508			sysconf(_SC_PRIORITY_SCHEDULING) > 0 &&
509			sysconf(_SC_REALTIME_SIGNALS) > 0 &&
510			sysconf(_SC_SEMAPHORES) > 0 &&
511			sysconf(_SC_SHARED_MEMORY_OBJECTS) > 0 &&
512			sysconf(_SC_SYNCHRONIZED_IO) > 0 &&
513			sysconf(_SC_TIMERS) > 0;
514		errno = sverrno;
515		if (value)
516			return (200112L);
517		else
518			return (-1);
519#else
520		return (_XOPEN_REALTIME);
521#endif
522	case _SC_XOPEN_REALTIME_THREADS:
523#if _XOPEN_REALTIME_THREADS == 0
524#error "_XOPEN_REALTIME_THREADS"
525#else
526		return (_XOPEN_REALTIME_THREADS);
527#endif
528	case _SC_XOPEN_SHM:
529		len = sizeof(lvalue);
530		sverrno = errno;
531		if (sysctlbyname("kern.ipc.shmmin", &lvalue, &len, NULL,
532		    0) == -1) {
533			errno = sverrno;
534			return (-1);
535		}
536		errno = sverrno;
537		return (1);
538	case _SC_XOPEN_STREAMS:
539		return (_XOPEN_STREAMS);
540	case _SC_XOPEN_UNIX:
541		return (_XOPEN_UNIX);
542#ifdef _XOPEN_VERSION
543	case _SC_XOPEN_VERSION:
544		return (_XOPEN_VERSION);
545#endif
546#ifdef _XOPEN_XCU_VERSION
547	case _SC_XOPEN_XCU_VERSION:
548		return (_XOPEN_XCU_VERSION);
549#endif
550	case _SC_SYMLOOP_MAX:
551		return (MAXSYMLINKS);
552	case _SC_RAW_SOCKETS:
553		return (_POSIX_RAW_SOCKETS);
554	case _SC_IPV6:
555#if _POSIX_IPV6 == 0
556		sverrno = errno;
557		value = socket(PF_INET6, SOCK_DGRAM, 0);
558		errno = sverrno;
559		if (value >= 0) {
560			close(value);
561			return (200112L);
562		} else
563			return (0);
564#else
565		return (_POSIX_IPV6);
566#endif
567
568	case _SC_NPROCESSORS_CONF:
569	case _SC_NPROCESSORS_ONLN:
570		mib[0] = CTL_HW;
571		mib[1] = HW_NCPU;
572		break;
573
574#ifdef _SC_PHYS_PAGES
575	case _SC_PHYS_PAGES:
576		len = sizeof(lvalue);
577		if (sysctlbyname("hw.availpages", &lvalue, &len, NULL, 0) == -1)
578			return (-1);
579		return (lvalue);
580#endif
581
582	default:
583		errno = EINVAL;
584		return (-1);
585	}
586	len = sizeof(value);
587	if (sysctl(mib, 2, &value, &len, NULL, 0) == -1)
588		value = -1;
589	return ((long)value);
590}
591