[klibc] Framework and trivial implementation of sysconf(3)

Framework for sysconf(3) that hopefully doesn't pull in all possible
sysconf data providers every time it is referenced.

So far only the page size is provided.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
diff --git a/usr/dash/config.h b/usr/dash/config.h
index 35230c7..9757009 100644
--- a/usr/dash/config.h
+++ b/usr/dash/config.h
@@ -81,7 +81,7 @@
 #define HAVE_STRTOUMAX 1
 
 /* Define to 1 if you have the `sysconf' function. */
-/* #undef HAVE_SYSCONF */
+#define HAVE_SYSCONF 1
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1
diff --git a/usr/include/sys/sysconf.h b/usr/include/sys/sysconf.h
new file mode 100644
index 0000000..13ababc
--- /dev/null
+++ b/usr/include/sys/sysconf.h
@@ -0,0 +1,40 @@
+/*
+ * sys/sysconf.h
+ *
+ * sysconf() macros and demultiplex
+ * This file is included in <unistd.h>
+ *
+ * Add things here as needed, we don't really want to add things wildly.
+ * For things that require a lot of code, create an out-of-line function
+ * and put it in a .c file in the sysconf directory.
+ */
+
+#ifndef _SYS_SYSCONF_H
+#define _SYS_SYSCONF_H
+
+#ifndef _UNISTD_H
+# include <unistd.h>
+#endif
+#include <errno.h>
+
+enum sysconf {
+	_SC_PAGESIZE = 1,
+};
+
+__extern long sysconf(int);
+
+__must_inline long __sysconf_inline(int __val)
+{
+	switch (__val) {
+	case _SC_PAGESIZE:
+		return getpagesize();
+	default:
+		errno = EINVAL;
+		return -1;
+	}
+}
+
+#define sysconf(x) \
+	(__builtin_constant_p(x) ? __sysconf_inline(x) : sysconf(x))
+
+#endif /* _SYS_SYSCONF_H */
diff --git a/usr/include/unistd.h b/usr/include/unistd.h
index f0e19c2..d425df8 100644
--- a/usr/include/unistd.h
+++ b/usr/include/unistd.h
@@ -144,13 +144,13 @@
 __extern int isatty(int);
 
 __extern unsigned int __page_size;
-static __inline__ int getpagesize(void)
+__must_inline int getpagesize(void)
 {
 	return __page_size;
 }
 
 __extern unsigned int __page_shift;
-static __inline__ int __getpageshift(void)
+__must_inline int __getpageshift(void)
 {
 	return __page_shift;
 }
@@ -162,4 +162,7 @@
 #define STDOUT_FILENO	1
 #define STDERR_FILENO	2
 
+/* This #include must be at the end */
+#include <sys/sysconf.h>
+
 #endif				/* _UNISTD_H */
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index 2bef9ca..da1dce0 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -70,7 +70,8 @@
 	  stdio/fread.o stdio/fwrite.o stdio/fflush.o \
 	  stdio/ungetc.o stdio/fgetc.o \
 	  stdio/fseek.o stdio/ftell.o stdio/rewind.o \
-	  stdio/fileno.o stdio/feof.o stdio/ferror.o
+	  stdio/fileno.o stdio/feof.o stdio/ferror.o \
+	  sysconf/sysconf.o
 
 klib-$(CONFIG_KLIBC_ERRLIST) += errlist.o
 
diff --git a/usr/klibc/sysconf/sysconf.c b/usr/klibc/sysconf/sysconf.c
new file mode 100644
index 0000000..0e21beb
--- /dev/null
+++ b/usr/klibc/sysconf/sysconf.c
@@ -0,0 +1,8 @@
+#include <sys/sysconf.h>
+
+#undef sysconf
+
+long sysconf(int val)
+{
+	return __sysconf_inline(val);
+}