summaryrefslogtreecommitdiff
path: root/core/musl
diff options
context:
space:
mode:
Diffstat (limited to 'core/musl')
-rw-r--r--core/musl/.footprint247
-rw-r--r--core/musl/.signature12
-rw-r--r--core/musl/CVE-2026-40200.patch179
-rw-r--r--core/musl/CVE-2026-6042.patch321
-rw-r--r--core/musl/MAKEPKG67
-rw-r--r--core/musl/getconf.c338
-rw-r--r--core/musl/getent.c536
-rw-r--r--core/musl/iconv.c110
-rw-r--r--core/musl/ldd19
9 files changed, 1829 insertions, 0 deletions
diff --git a/core/musl/.footprint b/core/musl/.footprint
new file mode 100644
index 0000000..e27870b
--- /dev/null
+++ b/core/musl/.footprint
@@ -0,0 +1,247 @@
+drwxr-xr-x root/root bin/
+-rwxr-xr-x root/root bin/getconf
+-rwxr-xr-x root/root bin/getent
+-rwxr-xr-x root/root bin/iconv
+-rwxr-xr-x root/root bin/ldd
+drwxr-xr-x root/root include/
+-rw-r--r-- root/root include/aio.h
+-rw-r--r-- root/root include/alloca.h
+-rw-r--r-- root/root include/ar.h
+-rw-r--r-- root/root include/assert.h
+-rw-r--r-- root/root include/byteswap.h
+-rw-r--r-- root/root include/complex.h
+-rw-r--r-- root/root include/cpio.h
+-rw-r--r-- root/root include/crypt.h
+-rw-r--r-- root/root include/ctype.h
+-rw-r--r-- root/root include/dirent.h
+-rw-r--r-- root/root include/dlfcn.h
+-rw-r--r-- root/root include/elf.h
+-rw-r--r-- root/root include/endian.h
+-rw-r--r-- root/root include/err.h
+-rw-r--r-- root/root include/errno.h
+-rw-r--r-- root/root include/fcntl.h
+-rw-r--r-- root/root include/features.h
+-rw-r--r-- root/root include/fenv.h
+-rw-r--r-- root/root include/float.h
+-rw-r--r-- root/root include/fmtmsg.h
+-rw-r--r-- root/root include/fnmatch.h
+-rw-r--r-- root/root include/ftw.h
+-rw-r--r-- root/root include/getopt.h
+-rw-r--r-- root/root include/glob.h
+-rw-r--r-- root/root include/grp.h
+-rw-r--r-- root/root include/iconv.h
+-rw-r--r-- root/root include/ifaddrs.h
+-rw-r--r-- root/root include/inttypes.h
+-rw-r--r-- root/root include/iso646.h
+-rw-r--r-- root/root include/langinfo.h
+-rw-r--r-- root/root include/lastlog.h
+-rw-r--r-- root/root include/libgen.h
+-rw-r--r-- root/root include/libintl.h
+-rw-r--r-- root/root include/limits.h
+-rw-r--r-- root/root include/link.h
+-rw-r--r-- root/root include/locale.h
+-rw-r--r-- root/root include/malloc.h
+-rw-r--r-- root/root include/math.h
+-rw-r--r-- root/root include/memory.h
+-rw-r--r-- root/root include/mntent.h
+-rw-r--r-- root/root include/monetary.h
+-rw-r--r-- root/root include/mqueue.h
+-rw-r--r-- root/root include/netdb.h
+-rw-r--r-- root/root include/nl_types.h
+-rw-r--r-- root/root include/paths.h
+-rw-r--r-- root/root include/poll.h
+-rw-r--r-- root/root include/pthread.h
+-rw-r--r-- root/root include/pty.h
+-rw-r--r-- root/root include/pwd.h
+-rw-r--r-- root/root include/regex.h
+-rw-r--r-- root/root include/resolv.h
+-rw-r--r-- root/root include/sched.h
+-rw-r--r-- root/root include/search.h
+-rw-r--r-- root/root include/semaphore.h
+-rw-r--r-- root/root include/setjmp.h
+-rw-r--r-- root/root include/shadow.h
+-rw-r--r-- root/root include/signal.h
+-rw-r--r-- root/root include/spawn.h
+-rw-r--r-- root/root include/stdalign.h
+-rw-r--r-- root/root include/stdarg.h
+-rw-r--r-- root/root include/stdbool.h
+-rw-r--r-- root/root include/stdc-predef.h
+-rw-r--r-- root/root include/stddef.h
+-rw-r--r-- root/root include/stdint.h
+-rw-r--r-- root/root include/stdio.h
+-rw-r--r-- root/root include/stdio_ext.h
+-rw-r--r-- root/root include/stdlib.h
+-rw-r--r-- root/root include/stdnoreturn.h
+-rw-r--r-- root/root include/string.h
+-rw-r--r-- root/root include/strings.h
+-rw-r--r-- root/root include/stropts.h
+-rw-r--r-- root/root include/syscall.h
+-rw-r--r-- root/root include/sysexits.h
+-rw-r--r-- root/root include/syslog.h
+-rw-r--r-- root/root include/tar.h
+-rw-r--r-- root/root include/termios.h
+-rw-r--r-- root/root include/tgmath.h
+-rw-r--r-- root/root include/threads.h
+-rw-r--r-- root/root include/time.h
+-rw-r--r-- root/root include/uchar.h
+-rw-r--r-- root/root include/ucontext.h
+-rw-r--r-- root/root include/ulimit.h
+-rw-r--r-- root/root include/unistd.h
+-rw-r--r-- root/root include/utime.h
+-rw-r--r-- root/root include/utmp.h
+-rw-r--r-- root/root include/utmpx.h
+-rw-r--r-- root/root include/values.h
+-rw-r--r-- root/root include/wait.h
+-rw-r--r-- root/root include/wchar.h
+-rw-r--r-- root/root include/wctype.h
+-rw-r--r-- root/root include/wordexp.h
+drwxr-xr-x root/root include/arpa/
+-rw-r--r-- root/root include/arpa/ftp.h
+-rw-r--r-- root/root include/arpa/inet.h
+-rw-r--r-- root/root include/arpa/nameser.h
+-rw-r--r-- root/root include/arpa/nameser_compat.h
+-rw-r--r-- root/root include/arpa/telnet.h
+-rw-r--r-- root/root include/arpa/tftp.h
+drwxr-xr-x root/root include/bits/
+-rw-r--r-- root/root include/bits/alltypes.h
+-rw-r--r-- root/root include/bits/dirent.h
+-rw-r--r-- root/root include/bits/errno.h
+-rw-r--r-- root/root include/bits/fcntl.h
+-rw-r--r-- root/root include/bits/fenv.h
+-rw-r--r-- root/root include/bits/float.h
+-rw-r--r-- root/root include/bits/hwcap.h (EMPTY)
+-rw-r--r-- root/root include/bits/io.h
+-rw-r--r-- root/root include/bits/ioctl.h
+-rw-r--r-- root/root include/bits/ioctl_fix.h (EMPTY)
+-rw-r--r-- root/root include/bits/ipc.h
+-rw-r--r-- root/root include/bits/ipcstat.h
+-rw-r--r-- root/root include/bits/kd.h
+-rw-r--r-- root/root include/bits/limits.h
+-rw-r--r-- root/root include/bits/link.h
+-rw-r--r-- root/root include/bits/mman.h
+-rw-r--r-- root/root include/bits/msg.h
+-rw-r--r-- root/root include/bits/poll.h (EMPTY)
+-rw-r--r-- root/root include/bits/ptrace.h
+-rw-r--r-- root/root include/bits/reg.h
+-rw-r--r-- root/root include/bits/resource.h (EMPTY)
+-rw-r--r-- root/root include/bits/sem.h
+-rw-r--r-- root/root include/bits/setjmp.h
+-rw-r--r-- root/root include/bits/shm.h
+-rw-r--r-- root/root include/bits/signal.h
+-rw-r--r-- root/root include/bits/socket.h (EMPTY)
+-rw-r--r-- root/root include/bits/soundcard.h
+-rw-r--r-- root/root include/bits/stat.h
+-rw-r--r-- root/root include/bits/statfs.h
+-rw-r--r-- root/root include/bits/stdint.h
+-rw-r--r-- root/root include/bits/syscall.h
+-rw-r--r-- root/root include/bits/termios.h
+-rw-r--r-- root/root include/bits/user.h
+-rw-r--r-- root/root include/bits/vt.h
+drwxr-xr-x root/root include/net/
+-rw-r--r-- root/root include/net/ethernet.h
+-rw-r--r-- root/root include/net/if.h
+-rw-r--r-- root/root include/net/if_arp.h
+-rw-r--r-- root/root include/net/route.h
+drwxr-xr-x root/root include/netinet/
+-rw-r--r-- root/root include/netinet/ether.h
+-rw-r--r-- root/root include/netinet/icmp6.h
+-rw-r--r-- root/root include/netinet/if_ether.h
+-rw-r--r-- root/root include/netinet/igmp.h
+-rw-r--r-- root/root include/netinet/in.h
+-rw-r--r-- root/root include/netinet/in_systm.h
+-rw-r--r-- root/root include/netinet/ip.h
+-rw-r--r-- root/root include/netinet/ip6.h
+-rw-r--r-- root/root include/netinet/ip_icmp.h
+-rw-r--r-- root/root include/netinet/tcp.h
+-rw-r--r-- root/root include/netinet/udp.h
+drwxr-xr-x root/root include/netpacket/
+-rw-r--r-- root/root include/netpacket/packet.h
+drwxr-xr-x root/root include/scsi/
+-rw-r--r-- root/root include/scsi/scsi.h
+-rw-r--r-- root/root include/scsi/scsi_ioctl.h
+-rw-r--r-- root/root include/scsi/sg.h
+drwxr-xr-x root/root include/sys/
+-rw-r--r-- root/root include/sys/acct.h
+-rw-r--r-- root/root include/sys/auxv.h
+-rw-r--r-- root/root include/sys/cachectl.h
+-rw-r--r-- root/root include/sys/dir.h
+-rw-r--r-- root/root include/sys/epoll.h
+-rw-r--r-- root/root include/sys/errno.h
+-rw-r--r-- root/root include/sys/eventfd.h
+-rw-r--r-- root/root include/sys/fanotify.h
+-rw-r--r-- root/root include/sys/fcntl.h
+-rw-r--r-- root/root include/sys/file.h
+-rw-r--r-- root/root include/sys/fsuid.h
+-rw-r--r-- root/root include/sys/inotify.h
+-rw-r--r-- root/root include/sys/io.h
+-rw-r--r-- root/root include/sys/ioctl.h
+-rw-r--r-- root/root include/sys/ipc.h
+-rw-r--r-- root/root include/sys/kd.h
+-rw-r--r-- root/root include/sys/klog.h
+-rw-r--r-- root/root include/sys/membarrier.h
+-rw-r--r-- root/root include/sys/mman.h
+-rw-r--r-- root/root include/sys/mount.h
+-rw-r--r-- root/root include/sys/msg.h
+-rw-r--r-- root/root include/sys/mtio.h
+-rw-r--r-- root/root include/sys/param.h
+-rw-r--r-- root/root include/sys/personality.h
+-rw-r--r-- root/root include/sys/poll.h
+-rw-r--r-- root/root include/sys/prctl.h
+-rw-r--r-- root/root include/sys/procfs.h
+-rw-r--r-- root/root include/sys/ptrace.h
+-rw-r--r-- root/root include/sys/quota.h
+-rw-r--r-- root/root include/sys/random.h
+-rw-r--r-- root/root include/sys/reboot.h
+-rw-r--r-- root/root include/sys/reg.h
+-rw-r--r-- root/root include/sys/resource.h
+-rw-r--r-- root/root include/sys/select.h
+-rw-r--r-- root/root include/sys/sem.h
+-rw-r--r-- root/root include/sys/sendfile.h
+-rw-r--r-- root/root include/sys/shm.h
+-rw-r--r-- root/root include/sys/signal.h
+-rw-r--r-- root/root include/sys/signalfd.h
+-rw-r--r-- root/root include/sys/socket.h
+-rw-r--r-- root/root include/sys/soundcard.h
+-rw-r--r-- root/root include/sys/stat.h
+-rw-r--r-- root/root include/sys/statfs.h
+-rw-r--r-- root/root include/sys/statvfs.h
+-rw-r--r-- root/root include/sys/stropts.h
+-rw-r--r-- root/root include/sys/swap.h
+-rw-r--r-- root/root include/sys/syscall.h
+-rw-r--r-- root/root include/sys/sysinfo.h
+-rw-r--r-- root/root include/sys/syslog.h
+-rw-r--r-- root/root include/sys/sysmacros.h
+-rw-r--r-- root/root include/sys/termios.h
+-rw-r--r-- root/root include/sys/time.h
+-rw-r--r-- root/root include/sys/timeb.h
+-rw-r--r-- root/root include/sys/timerfd.h
+-rw-r--r-- root/root include/sys/times.h
+-rw-r--r-- root/root include/sys/timex.h
+-rw-r--r-- root/root include/sys/ttydefaults.h
+-rw-r--r-- root/root include/sys/types.h
+-rw-r--r-- root/root include/sys/ucontext.h
+-rw-r--r-- root/root include/sys/uio.h
+-rw-r--r-- root/root include/sys/un.h
+-rw-r--r-- root/root include/sys/user.h
+-rw-r--r-- root/root include/sys/utsname.h
+-rw-r--r-- root/root include/sys/vfs.h
+-rw-r--r-- root/root include/sys/vt.h
+-rw-r--r-- root/root include/sys/wait.h
+-rw-r--r-- root/root include/sys/xattr.h
+drwxr-xr-x root/root lib/
+-rw-r--r-- root/root lib/Scrt1.o
+-rw-r--r-- root/root lib/crt1.o
+-rw-r--r-- root/root lib/crti.o
+-rw-r--r-- root/root lib/crtn.o
+-rw-r--r-- root/root lib/libc.a
+-rwxr-xr-x root/root lib/libc.so
+-rw-r--r-- root/root lib/libcrypt.a
+-rw-r--r-- root/root lib/libdl.a
+-rw-r--r-- root/root lib/libm.a
+-rw-r--r-- root/root lib/libpthread.a
+-rw-r--r-- root/root lib/libresolv.a
+-rw-r--r-- root/root lib/librt.a
+-rw-r--r-- root/root lib/libutil.a
+-rw-r--r-- root/root lib/libxnet.a
+-rw-r--r-- root/root lib/rcrt1.o
+lrwxrwxrwx root/root lib/ld-musl-x86_64.so.1 -> /lib/libc.so
diff --git a/core/musl/.signature b/core/musl/.signature
new file mode 100644
index 0000000..9ea0e0c
--- /dev/null
+++ b/core/musl/.signature
@@ -0,0 +1,12 @@
+RWTZ9IduCSQ/mAv94vrHB7zLW7p+eq/IEsava58afNULwTx8gOTEZkmx33m2WGxampPVpOXVDEBSi7LE31fIHjtCBNppn+K6Ig8=
+
+SHA256 (MAKEPKG) = 668235489d990b7873b1784dc7e03875525ecece3b85c94abd50613fe9185e3e
+SHA256 (.footprint) = f69e9387d6a3fd18eae0f6bd91d0fda9948af756de244a2099a50e91a403c491
+SHA256 (musl-1.2.6.tar.gz) = d585fd3b613c66151fc3249e8ed44f77020cb5e6c1e635a616d3f9f82460512a
+SHA256 (getconf.c) = d87d0cbb3690ae2c5d8cc218349fd8278b93855dd625deaf7ae50e320aad247c
+SHA256 (getent.c) = b25f32d306d542246e9358ef65cd67c12b3e3a77656bc467853d3b0c76b5fbbd
+SHA256 (iconv.c) = f79a2930a2e5bb0624321589edf8b889d1e9b603e01e6b7ae214616605b3fdd7
+SHA256 (ldd) = 2218e5f493a08cc981ef0888fb03d3b8f840d61e3025d9cc767d3963d3a55508
+SHA256 (CVE-2026-6042.patch) = 444fa70e52ca158fb7d4bad560637790bbf8f72e80b82fff840dd66fa83091e3
+SHA256 (CVE-2026-40200.patch) = 1ee29f64f9ca8e8ad7c349779d661ff6b52126a27575d3586981357a52c406fb
+SHA256 (musl#1.2.6-2.pkg.tar.gz) = 79e9b5e5ea46bae973feacbea7c03a814f62b829fa49cddd8574ec8d6c142862
diff --git a/core/musl/CVE-2026-40200.patch b/core/musl/CVE-2026-40200.patch
new file mode 100644
index 0000000..88298ca
--- /dev/null
+++ b/core/musl/CVE-2026-40200.patch
@@ -0,0 +1,179 @@
+>From 228da39e38c1cae13cbe637e771412c1984dba5d Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Thu, 9 Apr 2026 22:51:30 -0400
+Subject: [PATCH 1/3] qsort: fix leonardo heap corruption from bug in
+ doubleword ctz primitive
+
+the pntz function, implementing a "count trailing zeros" variant for a
+bit vector consisting of two size_t words, erroneously returned zero
+rather than the number of bits in the low word when the first bit set
+was the low bit of the high word.
+
+as a result, a loop in the trinkle function which should have a
+guaranteed small bound on the number of iterations, could run
+unboundedly, thereby overflowing a stack-based working-space array
+which was sized for the bound.
+
+CVE-2026-40200 has been assigned for this issue.
+---
+ src/stdlib/qsort.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
+index ab79dc6f..13219ab3 100644
+--- a/src/stdlib/qsort.c
++++ b/src/stdlib/qsort.c
+@@ -34,11 +34,11 @@
+
+ typedef int (*cmpfun)(const void *, const void *, void *);
+
++/* returns index of first bit set, excluding the low bit assumed to always
++ * be set, starting from low bit of p[0] up through high bit of p[1] */
+ static inline int pntz(size_t p[2]) {
+- int r = ntz(p[0] - 1);
+- if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
+- return r;
+- }
++ if (p[0] != 1) return ntz(p[0] - 1);
++ if (p[1]) return 8*sizeof(size_t) + ntz(p[1]);
+ return 0;
+ }
+
+--
+2.21.0
+
+
+>From b3291b9a9f77f1f993d2b4f8c68a26cf09221ae7 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Thu, 9 Apr 2026 23:40:53 -0400
+Subject: [PATCH 2/3] qsort: hard-preclude oob array writes independent of any
+ invariants
+
+while the root cause of CVE-2026-40200 was a faulty ctz primitive, the
+fallout of the bug would have been limited to erroneous sorting or
+infinite loop if not for the stores to a stack-based array that
+depended on trusting invariants in order not to go out of bounds.
+
+increase the size of the array to a power of two so that we can mask
+indices into it to force them into range. in the absence of any
+further bug, the masking is a no-op, but it does not have any
+measurable performance cost, and it makes spatial memory safety
+trivial to prove (and for readers not familiar with the algorithms to
+trust).
+---
+ src/stdlib/qsort.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
+index 13219ab3..e4bce9f7 100644
+--- a/src/stdlib/qsort.c
++++ b/src/stdlib/qsort.c
+@@ -89,10 +89,16 @@ static inline void shr(size_t p[2], int n)
+ p[1] >>= n;
+ }
+
++/* power-of-two length for working array so that we can mask indices and
++ * not depend on any invariant of the algorithm for spatial memory safety.
++ * the original size was just 14*sizeof(size_t)+1 */
++#define AR_LEN (16 * sizeof(size_t))
++#define AR_MASK (AR_LEN - 1)
++
+ static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[])
+ {
+ unsigned char *rt, *lf;
+- unsigned char *ar[14 * sizeof(size_t) + 1];
++ unsigned char *ar[AR_LEN];
+ int i = 1;
+
+ ar[0] = head;
+@@ -104,16 +110,16 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int p
+ break;
+ }
+ if(cmp(lf, rt, arg) >= 0) {
+- ar[i++] = lf;
++ ar[i++ & AR_MASK] = lf;
+ head = lf;
+ pshift -= 1;
+ } else {
+- ar[i++] = rt;
++ ar[i++ & AR_MASK] = rt;
+ head = rt;
+ pshift -= 2;
+ }
+ }
+- cycle(width, ar, i);
++ cycle(width, ar, i & AR_MASK);
+ }
+
+ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[])
+@@ -121,7 +127,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
+ unsigned char *stepson,
+ *rt, *lf;
+ size_t p[2];
+- unsigned char *ar[14 * sizeof(size_t) + 1];
++ unsigned char *ar[AR_LEN];
+ int i = 1;
+ int trail;
+
+@@ -142,7 +148,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
+ }
+ }
+
+- ar[i++] = stepson;
++ ar[i++ & AR_MASK] = stepson;
+ head = stepson;
+ trail = pntz(p);
+ shr(p, trail);
+@@ -150,7 +156,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
+ trusty = 0;
+ }
+ if(!trusty) {
+- cycle(width, ar, i);
++ cycle(width, ar, i & AR_MASK);
+ sift(head, width, cmp, arg, pshift, lp);
+ }
+ }
+--
+2.21.0
+
+
+>From 5122f9f3c99fee366167c5de98b31546312921ab Mon Sep 17 00:00:00 2001
+From: Luca Kellermann <mailto.luca.kellermann@gmail.com>
+Date: Fri, 10 Apr 2026 03:03:22 +0200
+Subject: [PATCH 3/3] qsort: fix shift UB in shl and shr
+
+if shl() or shr() are called with n==8*sizeof(size_t), n is adjusted
+to 0. the shift by (sizeof(size_t) * 8 - n) that then follows will
+consequently shift by the width of size_t, which is UB and in practice
+produces an incorrect result.
+
+return early in this case. the bitvector p was already shifted by the
+required amount.
+---
+ src/stdlib/qsort.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
+index e4bce9f7..28607450 100644
+--- a/src/stdlib/qsort.c
++++ b/src/stdlib/qsort.c
+@@ -71,6 +71,7 @@ static inline void shl(size_t p[2], int n)
+ n -= 8 * sizeof(size_t);
+ p[1] = p[0];
+ p[0] = 0;
++ if (!n) return;
+ }
+ p[1] <<= n;
+ p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
+@@ -83,6 +84,7 @@ static inline void shr(size_t p[2], int n)
+ n -= 8 * sizeof(size_t);
+ p[0] = p[1];
+ p[1] = 0;
++ if (!n) return;
+ }
+ p[0] >>= n;
+ p[0] |= p[1] << (sizeof(size_t) * 8 - n);
+--
+2.21.0
+
+
diff --git a/core/musl/CVE-2026-6042.patch b/core/musl/CVE-2026-6042.patch
new file mode 100644
index 0000000..9b39420
--- /dev/null
+++ b/core/musl/CVE-2026-6042.patch
@@ -0,0 +1,321 @@
+>From 67219f0130ec7c876ac0b299046460fad31caabf Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Mon, 30 Mar 2026 16:00:50 -0400
+Subject: [PATCH] fix pathological slowness & incorrect mappings in iconv
+ gb18030 decoder
+
+in order to implement the "UTF" aspect of gb18030 (ability to
+represent arbitrary unicode characters not present in the 2-byte
+mapping), we have to apply the index obtained from the encoded 4-byte
+sequence into the set of unmapped characters. this was done by
+scanning repeatedly over the table of mapped characters and counting
+off mapped characters below a running index by which to adjust the
+running index by on each iteration. this iterative process eventually
+leaves us with the value of the Nth unmapped character replacing the
+index, but depending on which particular character that is, the number
+of iterations needed to find it can be in the tens of thousands, and
+each iteration traverses the whole 126x190 table in the inner loop.
+this can lead to run times exceeding an entire second per character on
+moderate-speed machines.
+
+on top of that, the transformation logic produced wrong results for
+BMP characters above the the surrogate range, as a result of not
+correctly accounting for it being excluded, and for characters outside
+the BMP, as a result of a misunderstanding of how gb18030 encodes
+them.
+
+this patch replaces the unmapped character lookup with a single linear
+search of a list of unmapped ranges. there are only 206 such ranges,
+and these are permanently assigned and unchangeable as a consequence
+of the character encoding having to be stable, so a simple array of
+16-bit start/length values for each range consumes only 824 bytes, a
+very reasonable size cost here.
+
+this new table accounts for the previously-incorrect surrogate
+handling, and non-BMP characters are handled correctly by a single
+offset, without the need for any unmapped-range search.
+
+there are still a small number of mappings that are incorrect due to
+late changes made in the definition of gb18030, swapping PUA
+codepoints with proper Unicode characters. correcting these requires a
+postprocessing step that will be added later.
+---
+ src/locale/gb18030utf.h | 206 ++++++++++++++++++++++++++++++++++++++++
+ src/locale/iconv.c | 33 +++++--
+ 2 files changed, 230 insertions(+), 9 deletions(-)
+ create mode 100644 src/locale/gb18030utf.h
+
+diff --git a/src/locale/gb18030utf.h b/src/locale/gb18030utf.h
+new file mode 100644
+index 00000000..322a2440
+--- /dev/null
++++ b/src/locale/gb18030utf.h
+@@ -0,0 +1,206 @@
++{ 0x80, 36 },
++{ 0xa5, 2 },
++{ 0xa9, 7 },
++{ 0xb2, 5 },
++{ 0xb8, 31 },
++{ 0xd8, 8 },
++{ 0xe2, 6 },
++{ 0xeb, 1 },
++{ 0xee, 4 },
++{ 0xf4, 3 },
++{ 0xf8, 1 },
++{ 0xfb, 1 },
++{ 0xfd, 4 },
++{ 0x102, 17 },
++{ 0x114, 7 },
++{ 0x11c, 15 },
++{ 0x12c, 24 },
++{ 0x145, 3 },
++{ 0x149, 4 },
++{ 0x14e, 29 },
++{ 0x16c, 98 },
++{ 0x1cf, 1 },
++{ 0x1d1, 1 },
++{ 0x1d3, 1 },
++{ 0x1d5, 1 },
++{ 0x1d7, 1 },
++{ 0x1d9, 1 },
++{ 0x1db, 1 },
++{ 0x1dd, 28 },
++{ 0x1fa, 87 },
++{ 0x252, 15 },
++{ 0x262, 101 },
++{ 0x2c8, 1 },
++{ 0x2cc, 13 },
++{ 0x2da, 183 },
++{ 0x3a2, 1 },
++{ 0x3aa, 7 },
++{ 0x3c2, 1 },
++{ 0x3ca, 55 },
++{ 0x402, 14 },
++{ 0x450, 1 },
++{ 0x452, 7102 },
++{ 0x2011, 2 },
++{ 0x2017, 1 },
++{ 0x201a, 2 },
++{ 0x201e, 7 },
++{ 0x2027, 9 },
++{ 0x2031, 1 },
++{ 0x2034, 1 },
++{ 0x2036, 5 },
++{ 0x203c, 112 },
++{ 0x20ad, 86 },
++{ 0x2104, 1 },
++{ 0x2106, 3 },
++{ 0x210a, 12 },
++{ 0x2117, 10 },
++{ 0x2122, 62 },
++{ 0x216c, 4 },
++{ 0x217a, 22 },
++{ 0x2194, 2 },
++{ 0x219a, 110 },
++{ 0x2209, 6 },
++{ 0x2210, 1 },
++{ 0x2212, 3 },
++{ 0x2216, 4 },
++{ 0x221b, 2 },
++{ 0x2221, 2 },
++{ 0x2224, 1 },
++{ 0x2226, 1 },
++{ 0x222c, 2 },
++{ 0x222f, 5 },
++{ 0x2238, 5 },
++{ 0x223e, 10 },
++{ 0x2249, 3 },
++{ 0x224d, 5 },
++{ 0x2253, 13 },
++{ 0x2262, 2 },
++{ 0x2268, 6 },
++{ 0x2270, 37 },
++{ 0x2296, 3 },
++{ 0x229a, 11 },
++{ 0x22a6, 25 },
++{ 0x22c0, 82 },
++{ 0x2313, 333 },
++{ 0x246a, 10 },
++{ 0x249c, 100 },
++{ 0x254c, 4 },
++{ 0x2574, 13 },
++{ 0x2590, 3 },
++{ 0x2596, 10 },
++{ 0x25a2, 16 },
++{ 0x25b4, 8 },
++{ 0x25be, 8 },
++{ 0x25c8, 3 },
++{ 0x25cc, 2 },
++{ 0x25d0, 18 },
++{ 0x25e6, 31 },
++{ 0x2607, 2 },
++{ 0x260a, 54 },
++{ 0x2641, 1 },
++{ 0x2643, 2110 },
++{ 0x2e82, 2 },
++{ 0x2e85, 3 },
++{ 0x2e89, 2 },
++{ 0x2e8d, 10 },
++{ 0x2e98, 15 },
++{ 0x2ea8, 2 },
++{ 0x2eab, 3 },
++{ 0x2eaf, 4 },
++{ 0x2eb4, 2 },
++{ 0x2eb8, 3 },
++{ 0x2ebc, 14 },
++{ 0x2ecb, 293 },
++{ 0x2ffc, 4 },
++{ 0x3004, 1 },
++{ 0x3018, 5 },
++{ 0x301f, 2 },
++{ 0x302a, 20 },
++{ 0x303f, 2 },
++{ 0x3094, 7 },
++{ 0x309f, 2 },
++{ 0x30f7, 5 },
++{ 0x30ff, 6 },
++{ 0x312a, 246 },
++{ 0x322a, 7 },
++{ 0x3232, 113 },
++{ 0x32a4, 234 },
++{ 0x3390, 12 },
++{ 0x339f, 2 },
++{ 0x33a2, 34 },
++{ 0x33c5, 9 },
++{ 0x33cf, 2 },
++{ 0x33d3, 2 },
++{ 0x33d6, 113 },
++{ 0x3448, 43 },
++{ 0x3474, 298 },
++{ 0x359f, 111 },
++{ 0x360f, 11 },
++{ 0x361b, 765 },
++{ 0x3919, 85 },
++{ 0x396f, 96 },
++{ 0x39d1, 14 },
++{ 0x39e0, 147 },
++{ 0x3a74, 218 },
++{ 0x3b4f, 287 },
++{ 0x3c6f, 113 },
++{ 0x3ce1, 885 },
++{ 0x4057, 264 },
++{ 0x4160, 471 },
++{ 0x4338, 116 },
++{ 0x43ad, 4 },
++{ 0x43b2, 43 },
++{ 0x43de, 248 },
++{ 0x44d7, 373 },
++{ 0x464d, 20 },
++{ 0x4662, 193 },
++{ 0x4724, 5 },
++{ 0x472a, 82 },
++{ 0x477d, 16 },
++{ 0x478e, 441 },
++{ 0x4948, 50 },
++{ 0x497b, 2 },
++{ 0x497e, 4 },
++{ 0x4984, 1 },
++{ 0x4987, 20 },
++{ 0x499c, 3 },
++{ 0x49a0, 22 },
++{ 0x49b8, 703 },
++{ 0x4c78, 39 },
++{ 0x4ca4, 111 },
++{ 0x4d1a, 148 },
++{ 0x4daf, 81 },
++{ 0x9fa6, 14426 },
++{ 0xe76c, 1 },
++{ 0xe7c8, 1 },
++{ 0xe7e7, 13 },
++{ 0xe815, 1 },
++{ 0xe819, 5 },
++{ 0xe81f, 7 },
++{ 0xe827, 4 },
++{ 0xe82d, 4 },
++{ 0xe833, 8 },
++{ 0xe83c, 7 },
++{ 0xe844, 16 },
++{ 0xe856, 14 },
++{ 0xe865, 4295 },
++{ 0xf92d, 76 },
++{ 0xf97a, 27 },
++{ 0xf996, 81 },
++{ 0xf9e8, 9 },
++{ 0xf9f2, 26 },
++{ 0xfa10, 1 },
++{ 0xfa12, 1 },
++{ 0xfa15, 3 },
++{ 0xfa19, 6 },
++{ 0xfa22, 1 },
++{ 0xfa25, 2 },
++{ 0xfa2a, 1030 },
++{ 0xfe32, 1 },
++{ 0xfe45, 4 },
++{ 0xfe53, 1 },
++{ 0xfe58, 1 },
++{ 0xfe67, 1 },
++{ 0xfe6c, 149 },
++{ 0xff5f, 129 },
++{ 0xffe6, 26 },
+diff --git a/src/locale/iconv.c b/src/locale/iconv.c
+index 52178950..4151411d 100644
+--- a/src/locale/iconv.c
++++ b/src/locale/iconv.c
+@@ -74,6 +74,10 @@ static const unsigned short gb18030[126][190] = {
+ #include "gb18030.h"
+ };
+
++static const unsigned short gb18030utf[][2] = {
++#include "gb18030utf.h"
++};
++
+ static const unsigned short big5[89][157] = {
+ #include "big5.h"
+ };
+@@ -224,6 +228,8 @@ static unsigned uni_to_jis(unsigned c)
+ }
+ }
+
++#define countof(a) (sizeof (a) / sizeof *(a))
++
+ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb)
+ {
+ size_t x=0;
+@@ -430,15 +436,24 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
+ d = *((unsigned char *)*in + 3);
+ if (d-'0'>9) goto ilseq;
+ c += d-'0';
+- c += 128;
+- for (d=0; d<=c; ) {
+- k = 0;
+- for (int i=0; i<126; i++)
+- for (int j=0; j<190; j++)
+- if (gb18030[i][j]-d <= c-d)
+- k++;
+- d = c+1;
+- c += k;
++ /* Starting at 90 30 81 30 (189000), mapping is
++ * linear without gaps, to U+10000 and up. */
++ if (c >= 189000) {
++ c -= 189000;
++ c += 0x10000;
++ if (c >= 0x110000) goto ilseq;
++ break;
++ }
++ /* Otherwise we must process an index into set
++ * of characters unmapped by 2-byte table. */
++ for (int i=0; ; i++) {
++ if (i==countof(gb18030utf))
++ goto ilseq;
++ if (c<gb18030utf[i][1]) {
++ c += gb18030utf[i][0];
++ break;
++ }
++ c -= gb18030utf[i][1];
+ }
+ break;
+ }
+--
+2.21.0
+
+
diff --git a/core/musl/MAKEPKG b/core/musl/MAKEPKG
new file mode 100644
index 0000000..f5b9a7f
--- /dev/null
+++ b/core/musl/MAKEPKG
@@ -0,0 +1,67 @@
+#!/bin/mkpkg
+# description: musl C library
+# url: https://musl.libc.org/
+
+name=musl
+version=1.2.6
+release=2
+source=(https://musl.libc.org/releases/$name-$version.tar.gz
+ getconf.c
+ getent.c
+ iconv.c
+ ldd
+ CVE-2026-6042.patch
+ CVE-2026-40200.patch)
+
+sha256sums=(
+ "d585fd3b613c66151fc3249e8ed44f77020cb5e6c1e635a616d3f9f82460512a"
+ "d87d0cbb3690ae2c5d8cc218349fd8278b93855dd625deaf7ae50e320aad247c"
+ "b25f32d306d542246e9358ef65cd67c12b3e3a77656bc467853d3b0c76b5fbbd"
+ "f79a2930a2e5bb0624321589edf8b889d1e9b603e01e6b7ae214616605b3fdd7"
+ "2218e5f493a08cc981ef0888fb03d3b8f840d61e3025d9cc767d3963d3a55508"
+ "444fa70e52ca158fb7d4bad560637790bbf8f72e80b82fff840dd66fa83091e3"
+ "1ee29f64f9ca8e8ad7c349779d661ff6b52126a27575d3586981357a52c406fb"
+)
+
+patch() {
+ cd $name-$version
+
+ # CVE-2026-6042: gb18030 iconv decoder DoS + incorrect mappings
+ patch -p1 -i $SRC/CVE-2026-6042.patch
+
+ # CVE-2026-40200: qsort heap corruption (root cause + hardening + UB fix)
+ # The mbox contains 3 commits; GNU patch applies them all in one pass.
+ patch -p1 -i $SRC/CVE-2026-40200.patch
+}
+
+build() {
+ cd $name-$version
+
+ ./configure \
+ --prefix=/ \
+ --includedir=/include \
+ --libdir=/lib \
+ --syslibdir=/lib \
+ --disable-wrapper
+
+ make
+ make install DESTDIR=$PKG
+
+ # Build utilities
+ mkdir -p $PKG/bin
+ cc -Os -I$PKG/include -L$PKG/lib $SRC/getconf.c -o $PKG/bin/getconf
+ cc -Os -I$PKG/include -L$PKG/lib $SRC/getent.c -o $PKG/bin/getent
+ cc -Os -I$PKG/include -L$PKG/lib $SRC/iconv.c -o $PKG/bin/iconv
+ install -m755 $SRC/ldd $PKG/bin/ldd
+
+ # Strip
+ strip --strip-unneeded $PKG/bin/* 2>/dev/null || true
+}
+
+signify() {
+ untrusted comment: public key
+ RWTZ9IduCSQ/mL8337TEUinPwT92xFEUpD92hkS7IxcOnzTt9QdpohT3
+}
+
+# vim: filetype=sh
+
diff --git a/core/musl/getconf.c b/core/musl/getconf.c
new file mode 100644
index 0000000..c423524
--- /dev/null
+++ b/core/musl/getconf.c
@@ -0,0 +1,338 @@
+/*-
+ * Copyright (c) 1996, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * Mostly rewritten to be used in Alpine Linux (with musl c-library)
+ * by Timo Teräs.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <values.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+struct conf_variable {
+ const char *name;
+ enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT, UCONSTANT, NUM_TYPES } type;
+ long value;
+};
+
+static const struct conf_variable conf_table[] = {
+{ "PATH", CONFSTR, _CS_PATH },
+
+/* Utility Limit Minimum Values */
+{ "POSIX2_BC_BASE_MAX", CONSTANT, _POSIX2_BC_BASE_MAX },
+{ "POSIX2_BC_DIM_MAX", CONSTANT, _POSIX2_BC_DIM_MAX },
+{ "POSIX2_BC_SCALE_MAX", CONSTANT, _POSIX2_BC_SCALE_MAX },
+{ "POSIX2_BC_STRING_MAX", CONSTANT, _POSIX2_BC_STRING_MAX },
+{ "POSIX2_COLL_WEIGHTS_MAX", CONSTANT, _POSIX2_COLL_WEIGHTS_MAX },
+{ "POSIX2_EXPR_NEST_MAX", CONSTANT, _POSIX2_EXPR_NEST_MAX },
+{ "POSIX2_LINE_MAX", CONSTANT, _POSIX2_LINE_MAX },
+{ "POSIX2_RE_DUP_MAX", CONSTANT, _POSIX2_RE_DUP_MAX },
+{ "POSIX2_VERSION", CONSTANT, _POSIX2_VERSION },
+
+/* POSIX.1 Minimum Values */
+{ "_POSIX_AIO_LISTIO_MAX", CONSTANT, _POSIX_AIO_LISTIO_MAX },
+{ "_POSIX_AIO_MAX", CONSTANT, _POSIX_AIO_MAX },
+{ "_POSIX_ARG_MAX", CONSTANT, _POSIX_ARG_MAX },
+{ "_POSIX_CHILD_MAX", CONSTANT, _POSIX_CHILD_MAX },
+{ "_POSIX_LINK_MAX", CONSTANT, _POSIX_LINK_MAX },
+{ "_POSIX_MAX_CANON", CONSTANT, _POSIX_MAX_CANON },
+{ "_POSIX_MAX_INPUT", CONSTANT, _POSIX_MAX_INPUT },
+{ "_POSIX_MQ_OPEN_MAX", CONSTANT, _POSIX_MQ_OPEN_MAX },
+{ "_POSIX_MQ_PRIO_MAX", CONSTANT, _POSIX_MQ_PRIO_MAX },
+{ "_POSIX_NAME_MAX", CONSTANT, _POSIX_NAME_MAX },
+{ "_POSIX_NGROUPS_MAX", CONSTANT, _POSIX_NGROUPS_MAX },
+{ "_POSIX_OPEN_MAX", CONSTANT, _POSIX_OPEN_MAX },
+{ "_POSIX_PATH_MAX", CONSTANT, _POSIX_PATH_MAX },
+{ "_POSIX_PIPE_BUF", CONSTANT, _POSIX_PIPE_BUF },
+{ "_POSIX_SSIZE_MAX", CONSTANT, _POSIX_SSIZE_MAX },
+{ "_POSIX_STREAM_MAX", CONSTANT, _POSIX_STREAM_MAX },
+{ "_POSIX_TZNAME_MAX", CONSTANT, _POSIX_TZNAME_MAX },
+
+/* Symbolic Utility Limits */
+{ "BC_BASE_MAX", SYSCONF, _SC_BC_BASE_MAX },
+{ "BC_DIM_MAX", SYSCONF, _SC_BC_DIM_MAX },
+{ "BC_SCALE_MAX", SYSCONF, _SC_BC_SCALE_MAX },
+{ "BC_STRING_MAX", SYSCONF, _SC_BC_STRING_MAX },
+{ "COLL_WEIGHTS_MAX", SYSCONF, _SC_COLL_WEIGHTS_MAX },
+{ "EXPR_NEST_MAX", SYSCONF, _SC_EXPR_NEST_MAX },
+{ "LINE_MAX", SYSCONF, _SC_LINE_MAX },
+{ "RE_DUP_MAX", SYSCONF, _SC_RE_DUP_MAX },
+
+/* Optional Facility Configuration Values */
+{ "_POSIX2_C_BIND", SYSCONF, _SC_2_C_BIND },
+{ "POSIX2_C_DEV", SYSCONF, _SC_2_C_DEV },
+{ "POSIX2_CHAR_TERM", SYSCONF, _SC_2_CHAR_TERM },
+{ "POSIX2_FORT_DEV", SYSCONF, _SC_2_FORT_DEV },
+{ "POSIX2_FORT_RUN", SYSCONF, _SC_2_FORT_RUN },
+{ "POSIX2_LOCALEDEF", SYSCONF, _SC_2_LOCALEDEF },
+{ "POSIX2_SW_DEV", SYSCONF, _SC_2_SW_DEV },
+{ "POSIX2_UPE", SYSCONF, _SC_2_UPE },
+
+/* POSIX.1 Configurable System Variables */
+{ "AIO_LISTIO_MAX", SYSCONF, _SC_AIO_LISTIO_MAX },
+{ "AIO_MAX", SYSCONF, _SC_AIO_MAX },
+{ "ARG_MAX", SYSCONF, _SC_ARG_MAX },
+{ "CHILD_MAX", SYSCONF, _SC_CHILD_MAX },
+{ "CLK_TCK", SYSCONF, _SC_CLK_TCK },
+{ "MQ_OPEN_MAX", SYSCONF, _SC_MQ_OPEN_MAX },
+{ "MQ_PRIO_MAX", SYSCONF, _SC_MQ_PRIO_MAX },
+{ "NGROUPS_MAX", SYSCONF, _SC_NGROUPS_MAX },
+{ "OPEN_MAX", SYSCONF, _SC_OPEN_MAX },
+{ "STREAM_MAX", SYSCONF, _SC_STREAM_MAX },
+{ "TZNAME_MAX", SYSCONF, _SC_TZNAME_MAX },
+{ "_POSIX_JOB_CONTROL", SYSCONF, _SC_JOB_CONTROL },
+{ "_POSIX_SAVED_IDS", SYSCONF, _SC_SAVED_IDS },
+{ "_POSIX_VERSION", SYSCONF, _SC_VERSION },
+
+{ "LINK_MAX", PATHCONF, _PC_LINK_MAX },
+{ "MAX_CANON", PATHCONF, _PC_MAX_CANON },
+{ "MAX_INPUT", PATHCONF, _PC_MAX_INPUT },
+{ "NAME_MAX", PATHCONF, _PC_NAME_MAX },
+{ "PATH_MAX", PATHCONF, _PC_PATH_MAX },
+{ "PIPE_BUF", PATHCONF, _PC_PIPE_BUF },
+{ "_POSIX_CHOWN_RESTRICTED", PATHCONF, _PC_CHOWN_RESTRICTED },
+{ "_POSIX_NO_TRUNC", PATHCONF, _PC_NO_TRUNC },
+{ "_POSIX_VDISABLE", PATHCONF, _PC_VDISABLE },
+
+/* POSIX.1b Configurable System Variables */
+{ "PAGESIZE", SYSCONF, _SC_PAGESIZE },
+{ "_POSIX_ASYNCHRONOUS_IO", SYSCONF, _SC_ASYNCHRONOUS_IO },
+{ "_POSIX_FSYNC", SYSCONF, _SC_FSYNC },
+{ "_POSIX_MAPPED_FILES", SYSCONF, _SC_MAPPED_FILES },
+{ "_POSIX_MEMLOCK", SYSCONF, _SC_MEMLOCK },
+{ "_POSIX_MEMLOCK_RANGE", SYSCONF, _SC_MEMLOCK_RANGE },
+{ "_POSIX_MEMORY_PROTECTION", SYSCONF, _SC_MEMORY_PROTECTION },
+{ "_POSIX_MESSAGE_PASSING", SYSCONF, _SC_MESSAGE_PASSING },
+{ "_POSIX_MONOTONIC_CLOCK", SYSCONF, _SC_MONOTONIC_CLOCK },
+{ "_POSIX_PRIORITY_SCHEDULING", SYSCONF, _SC_PRIORITY_SCHEDULING },
+{ "_POSIX_SEMAPHORES", SYSCONF, _SC_SEMAPHORES },
+{ "_POSIX_SHARED_MEMORY_OBJECTS", SYSCONF, _SC_SHARED_MEMORY_OBJECTS },
+{ "_POSIX_SYNCHRONIZED_IO", SYSCONF, _SC_SYNCHRONIZED_IO },
+{ "_POSIX_TIMERS", SYSCONF, _SC_TIMERS },
+
+{ "_POSIX_SYNC_IO", PATHCONF, _PC_SYNC_IO },
+
+/* POSIX.1c Configurable System Variables */
+{ "LOGIN_NAME_MAX", SYSCONF, _SC_LOGIN_NAME_MAX },
+{ "_POSIX_THREADS", SYSCONF, _SC_THREADS },
+
+/* POSIX.1j Configurable System Variables */
+{ "_POSIX_BARRIERS", SYSCONF, _SC_BARRIERS },
+{ "_POSIX_READER_WRITER_LOCKS", SYSCONF, _SC_READER_WRITER_LOCKS },
+{ "_POSIX_SPIN_LOCKS", SYSCONF, _SC_SPIN_LOCKS },
+
+/* XPG4.2 Configurable System Variables */
+{ "IOV_MAX", SYSCONF, _SC_IOV_MAX },
+{ "PAGE_SIZE", SYSCONF, _SC_PAGE_SIZE },
+{ "_XOPEN_SHM", SYSCONF, _SC_XOPEN_SHM },
+
+/* X/Open CAE Spec. Issue 5 Version 2 Configurable System Variables */
+{ "FILESIZEBITS", PATHCONF, _PC_FILESIZEBITS },
+
+/* POSIX.1-2001 XSI Option Group Configurable System Variables */
+{ "ATEXIT_MAX", SYSCONF, _SC_ATEXIT_MAX },
+
+/* POSIX.1-2001 TSF Configurable System Variables */
+{ "GETGR_R_SIZE_MAX", SYSCONF, _SC_GETGR_R_SIZE_MAX },
+{ "GETPW_R_SIZE_MAX", SYSCONF, _SC_GETPW_R_SIZE_MAX },
+
+/* Commonly provided extensions */
+{ "_PHYS_PAGES", SYSCONF, _SC_PHYS_PAGES },
+{ "_AVPHYS_PAGES", SYSCONF, _SC_AVPHYS_PAGES },
+{ "_NPROCESSORS_CONF", SYSCONF, _SC_NPROCESSORS_CONF },
+{ "_NPROCESSORS_ONLN", SYSCONF, _SC_NPROCESSORS_ONLN },
+
+/* Data type related extensions */
+{ "CHAR_BIT", CONSTANT, CHAR_BIT },
+{ "CHAR_MAX", CONSTANT, CHAR_MAX },
+{ "CHAR_MIN", CONSTANT, CHAR_MIN },
+{ "INT_MAX", CONSTANT, INT_MAX },
+{ "INT_MIN", CONSTANT, INT_MIN },
+{ "LONG_BIT", CONSTANT, LONG_BIT },
+{ "LONG_MAX", CONSTANT, LONG_MAX },
+{ "LONG_MIN", CONSTANT, LONG_MIN },
+{ "SCHAR_MAX", CONSTANT, SCHAR_MAX },
+{ "SCHAR_MIN", CONSTANT, SCHAR_MIN },
+{ "SHRT_MAX", CONSTANT, SHRT_MAX },
+{ "SHRT_MIN", CONSTANT, SHRT_MIN },
+{ "SSIZE_MAX", CONSTANT, SSIZE_MAX },
+{ "UCHAR_MAX", UCONSTANT, (long) UCHAR_MAX },
+{ "UINT_MAX", UCONSTANT, (long) UINT_MAX },
+{ "ULONG_MAX", UCONSTANT, (long) ULONG_MAX },
+{ "USHRT_MAX", UCONSTANT, (long) USHRT_MAX },
+{ "WORD_BIT", CONSTANT, WORD_BIT },
+
+{ NULL, CONSTANT, 0L }
+};
+
+static int all = 0;
+
+static void usage(const char *p)
+{
+ (void)fprintf(stderr, "Usage: %s system_var\n\t%s -a\n"
+ "\t%s path_var pathname\n\t%s -a pathname\n", p, p, p, p);
+ exit(EXIT_FAILURE);
+}
+
+static void print_long(const char *name, long val)
+{
+ if (all) printf("%s = %ld\n", name, val);
+ else printf("%ld\n", val);
+}
+
+static void print_ulong(const char *name, unsigned long val)
+{
+ if (all) printf("%s = %lu\n", name, val);
+ else printf("%lu\n", val);
+}
+
+static void print_string(const char *name, const char *val)
+{
+ if (all) printf("%s = %s\n", name, val);
+ else printf("%s\n", val);
+}
+
+static int print_constant(const struct conf_variable *cp, const char *pathname)
+{
+ print_long(cp->name, cp->value);
+ return 0;
+}
+
+static int print_uconstant(const struct conf_variable *cp, const char *pathname)
+{
+ print_ulong(cp->name, (unsigned long) cp->value);
+ return 0;
+}
+
+static int print_sysconf(const struct conf_variable *cp, const char *pathname)
+{
+ long val;
+
+ errno = 0;
+ if ((val = sysconf((int)cp->value)) == -1) {
+ if (errno != 0) err(EXIT_FAILURE, "sysconf(%ld)", cp->value);
+ return -1;
+ }
+ print_long(cp->name, val);
+ return 0;
+}
+
+static int print_confstr(const struct conf_variable *cp, const char *pathname)
+{
+ size_t len;
+ char *val;
+
+ errno = 0;
+ if ((len = confstr((int)cp->value, NULL, 0)) == 0) goto error;
+ if ((val = malloc(len)) == NULL) err(EXIT_FAILURE, "Can't allocate %zu bytes", len);
+ errno = 0;
+ if (confstr((int)cp->value, val, len) == 0) goto error;
+ print_string(cp->name, val);
+ free(val);
+ return 0;
+error:
+ if (errno != EINVAL) err(EXIT_FAILURE, "confstr(%ld)", cp->value);
+ return -1;
+}
+
+static int print_pathconf(const struct conf_variable *cp, const char *pathname)
+{
+ long val;
+
+ errno = 0;
+ if ((val = pathconf(pathname, (int)cp->value)) == -1) {
+ if (all && errno == EINVAL) return 0;
+ if (errno != 0) err(EXIT_FAILURE, "pathconf(%s, %ld)", pathname, cp->value);
+ return -1;
+ }
+ print_long(cp->name, val);
+ return 0;
+}
+
+typedef int (*handler_t)(const struct conf_variable *cp, const char *pathname);
+static const handler_t type_handlers[NUM_TYPES] = {
+ [SYSCONF] = print_sysconf,
+ [CONFSTR] = print_confstr,
+ [PATHCONF] = print_pathconf,
+ [CONSTANT] = print_constant,
+ [UCONSTANT] = print_uconstant,
+};
+
+int main(int argc, char **argv)
+{
+ const char *progname = argv[0];
+ const struct conf_variable *cp;
+ const char *varname, *pathname;
+ int ch, found = 0;
+
+ (void)setlocale(LC_ALL, "");
+ while ((ch = getopt(argc, argv, "a")) != -1) {
+ switch (ch) {
+ case 'a':
+ all = 1;
+ break;
+ case '?':
+ default:
+ usage(progname);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!all) {
+ if (argc == 0)
+ usage(progname);
+ varname = argv[0];
+ argc--;
+ argv++;
+ } else
+ varname = NULL;
+
+ if (argc > 1)
+ usage(progname);
+ pathname = argv[0]; /* may be NULL */
+
+ for (cp = conf_table; cp->name != NULL; cp++) {
+ if (!all && strcmp(varname, cp->name) != 0) continue;
+ if ((cp->type == PATHCONF) == (pathname != NULL)) {
+ if (type_handlers[cp->type](cp, pathname) < 0)
+ print_string(cp->name, "undefined");
+ found = 1;
+ } else if (!all)
+ errx(EXIT_FAILURE, "%s: invalid variable type", cp->name);
+ }
+ if (!all && !found) errx(EXIT_FAILURE, "%s: unknown variable", varname);
+ (void)fflush(stdout);
+ return ferror(stdout) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/core/musl/getent.c b/core/musl/getent.c
new file mode 100644
index 0000000..c2ed4c6
--- /dev/null
+++ b/core/musl/getent.c
@@ -0,0 +1,536 @@
+/*-
+ * Copyright (c) 2004-2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ * Timo Teräs cleaned up the code for use in Alpine Linux with musl libc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <paths.h>
+#include <err.h>
+
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <netinet/ether.h>
+#include <netinet/in.h>
+
+enum {
+ RV_OK = 0,
+ RV_USAGE = 1,
+ RV_NOTFOUND = 2,
+ RV_NOENUM = 3
+};
+
+static int usage(const char *);
+
+static int parsenum(const char *word, unsigned long *result)
+{
+ unsigned long num;
+ char *ep;
+
+ if (!isdigit((unsigned char)word[0]))
+ return 0;
+ errno = 0;
+ num = strtoul(word, &ep, 10);
+ if (num == ULONG_MAX && errno == ERANGE)
+ return 0;
+ if (*ep != '\0')
+ return 0;
+ *result = num;
+ return 1;
+}
+
+/*
+ * printfmtstrings --
+ * vprintf(format, ...),
+ * then the aliases (beginning with prefix, separated by sep),
+ * then a newline
+ */
+__attribute__ ((format (printf, 4, 5)))
+static void printfmtstrings(char *strings[], const char *prefix, const char *sep,
+ const char *fmt, ...)
+{
+ va_list ap;
+ const char *curpref;
+ size_t i;
+
+ va_start(ap, fmt);
+ (void)vprintf(fmt, ap);
+ va_end(ap);
+
+ curpref = prefix;
+ for (i = 0; strings[i] != NULL; i++) {
+ (void)printf("%s%s", curpref, strings[i]);
+ curpref = sep;
+ }
+ (void)printf("\n");
+}
+
+static int ethers(int argc, char *argv[])
+{
+ char hostname[MAXHOSTNAMELEN + 1], *hp;
+ struct ether_addr ea, *eap;
+ int i, rv;
+
+ if (argc == 2) {
+ warnx("Enumeration not supported on ethers");
+ return RV_NOENUM;
+ }
+
+ rv = RV_OK;
+ for (i = 2; i < argc; i++) {
+ if ((eap = ether_aton(argv[i])) == NULL) {
+ eap = &ea;
+ hp = argv[i];
+ if (ether_hostton(hp, eap) != 0) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ } else {
+ hp = hostname;
+ if (ether_ntohost(hp, eap) != 0) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ (void)printf("%-17s %s\n", ether_ntoa(eap), hp);
+ }
+ return rv;
+}
+
+static void groupprint(const struct group *gr)
+{
+ printfmtstrings(gr->gr_mem, "", ",", "%s:%s:%u:",
+ gr->gr_name, gr->gr_passwd, gr->gr_gid);
+}
+
+static int group(int argc, char *argv[])
+{
+ struct group *gr;
+ unsigned long id;
+ int i, rv;
+
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((gr = getgrent()) != NULL)
+ groupprint(gr);
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (parsenum(argv[i], &id))
+ gr = getgrgid((gid_t)id);
+ else
+ gr = getgrnam(argv[i]);
+ if (gr == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ groupprint(gr);
+ }
+ }
+ endgrent();
+ return rv;
+}
+
+static void hostsprint(const struct hostent *he)
+{
+ char buf[INET6_ADDRSTRLEN];
+
+ if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
+ (void)strlcpy(buf, "# unknown", sizeof(buf));
+ printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name);
+}
+
+static int hosts(int argc, char *argv[])
+{
+ struct hostent *he;
+ char addr[IN6ADDRSZ];
+ int i, rv;
+
+ sethostent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((he = gethostent()) != NULL)
+ hostsprint(he);
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
+ he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
+ else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
+ he = gethostbyaddr(addr, INADDRSZ, AF_INET);
+ else if ((he = gethostbyname2(argv[i], AF_INET6)) == NULL)
+ he = gethostbyname2(argv[i], AF_INET);
+ if (he == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ hostsprint(he);
+ }
+ }
+ endhostent();
+ return rv;
+}
+
+static int ahosts_ex(int family, int flags, int argc, char *argv[])
+{
+ static const char *socktypes[] = {
+ [SOCK_STREAM] = "STREAM",
+ [SOCK_DGRAM] = "DGRAM",
+ [SOCK_RAW] = "RAW",
+ [SOCK_RDM] = "RDM",
+ [SOCK_SEQPACKET] = "SEQPACKET",
+ [SOCK_DCCP] = "DCCP",
+ [SOCK_PACKET] = "PACKET",
+ };
+ const char *sockstr;
+ char sockbuf[16], buf[INET6_ADDRSTRLEN];
+ struct addrinfo *res, *r, hint;
+ void *addr;
+ int i;
+
+ if (argc == 2)
+ return hosts(argc, argv);
+
+ hint = (struct addrinfo) {
+ .ai_family = family,
+ .ai_flags = AI_ADDRCONFIG | AI_CANONNAME | flags,
+ };
+
+ for (i = 2; i < argc; i++) {
+ if (getaddrinfo(argv[i], 0, &hint, &res) != 0)
+ return RV_NOTFOUND;
+
+ for (r = res; r; r = r->ai_next) {
+ sockstr = NULL;
+ if (r->ai_socktype >= 0 && r->ai_socktype < sizeof(socktypes)/sizeof(socktypes[0]))
+ sockstr = socktypes[r->ai_socktype];
+ if (!sockstr) {
+ sprintf(buf, "%d", r->ai_socktype);
+ sockstr = sockbuf;
+ }
+ switch (r->ai_family) {
+ case AF_INET:
+ addr = &((struct sockaddr_in*) r->ai_addr)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = &((struct sockaddr_in6*) r->ai_addr)->sin6_addr;
+ break;
+ default:
+ continue;
+ }
+ if (inet_ntop(r->ai_family, addr, buf, sizeof(buf)) == NULL)
+ (void)strlcpy(buf, "# unknown", sizeof(buf));
+ printf("%-15s %-6s %s\n", buf, sockstr, r->ai_canonname ?: "");
+ }
+ }
+
+ return RV_OK;
+}
+
+static int ahosts(int argc, char *argv[])
+{
+ return ahosts_ex(AF_UNSPEC, 0, argc, argv);
+}
+
+static int ahostsv4(int argc, char *argv[])
+{
+ return ahosts_ex(AF_INET, 0, argc, argv);
+}
+
+static int ahostsv6(int argc, char *argv[])
+{
+ return ahosts_ex(AF_INET6, AI_V4MAPPED, argc, argv);
+}
+
+static void networksprint(const struct netent *ne)
+{
+ char buf[INET6_ADDRSTRLEN];
+ struct in_addr ianet;
+
+ ianet = inet_makeaddr(ne->n_net, 0);
+ if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
+ (void)strlcpy(buf, "# unknown", sizeof(buf));
+ printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf);
+}
+
+static int networks(int argc, char *argv[])
+{
+ struct netent *ne;
+ in_addr_t net;
+ int i, rv;
+
+ setnetent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((ne = getnetent()) != NULL)
+ networksprint(ne);
+ } else {
+ for (i = 2; i < argc; i++) {
+ net = inet_network(argv[i]);
+ if (net != INADDR_NONE)
+ ne = getnetbyaddr(net, AF_INET);
+ else
+ ne = getnetbyname(argv[i]);
+ if (ne != NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ networksprint(ne);
+ }
+ }
+ endnetent();
+ return rv;
+}
+
+static void passwdprint(struct passwd *pw)
+{
+ (void)printf("%s:%s:%u:%u:%s:%s:%s\n",
+ pw->pw_name, pw->pw_passwd, pw->pw_uid,
+ pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell);
+}
+
+static int passwd(int argc, char *argv[])
+{
+ struct passwd *pw;
+ unsigned long id;
+ int i, rv;
+
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((pw = getpwent()) != NULL)
+ passwdprint(pw);
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (parsenum(argv[i], &id))
+ pw = getpwuid((uid_t)id);
+ else
+ pw = getpwnam(argv[i]);
+ if (pw == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ passwdprint(pw);
+ }
+ }
+ endpwent();
+ return rv;
+}
+
+static void protocolsprint(struct protoent *pe)
+{
+ printfmtstrings(pe->p_aliases, " ", " ",
+ "%-16s %5d", pe->p_name, pe->p_proto);
+}
+
+static int protocols(int argc, char *argv[])
+{
+ struct protoent *pe;
+ unsigned long id;
+ int i, rv;
+
+ setprotoent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((pe = getprotoent()) != NULL)
+ protocolsprint(pe);
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (parsenum(argv[i], &id))
+ pe = getprotobynumber((int)id);
+ else
+ pe = getprotobyname(argv[i]);
+ if (pe == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ protocolsprint(pe);
+ }
+ }
+ endprotoent();
+ return rv;
+}
+
+static void servicesprint(struct servent *se)
+{
+ printfmtstrings(se->s_aliases, " ", " ",
+ "%-16s %5d/%s",
+ se->s_name, ntohs(se->s_port), se->s_proto);
+
+}
+
+static int services(int argc, char *argv[])
+{
+ struct servent *se;
+ unsigned long id;
+ char *proto;
+ int i, rv;
+
+ setservent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((se = getservent()) != NULL)
+ servicesprint(se);
+ } else {
+ for (i = 2; i < argc; i++) {
+ proto = strchr(argv[i], '/');
+ if (proto != NULL)
+ *proto++ = '\0';
+ if (parsenum(argv[i], &id))
+ se = getservbyport(htons(id), proto);
+ else
+ se = getservbyname(argv[i], proto);
+ if (se == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ servicesprint(se);
+ }
+ }
+ endservent();
+ return rv;
+}
+
+static int shadow(int argc, char *argv[])
+{
+ struct spwd *sp;
+ int i, rv;
+
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((sp = getspent()) != NULL)
+ putspent(sp, stdout);
+ } else {
+ for (i = 2; i < argc; i++) {
+ sp = getspnam(argv[i]);
+ if (sp == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ putspent(sp, stdout);
+ }
+ }
+ endspent();
+ return rv;
+}
+
+static int shells(int argc, char *argv[])
+{
+ const char *sh;
+ int i, rv;
+
+ setusershell();
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((sh = getusershell()) != NULL)
+ (void)printf("%s\n", sh);
+ } else {
+ for (i = 2; i < argc; i++) {
+ setusershell();
+ while ((sh = getusershell()) != NULL) {
+ if (strcmp(sh, argv[i]) == 0) {
+ (void)printf("%s\n", sh);
+ break;
+ }
+ }
+ if (sh == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endusershell();
+ return rv;
+}
+
+static struct getentdb {
+ const char *name;
+ int (*callback)(int, char *[]);
+} databases[] = {
+ { "ethers", ethers, },
+ { "group", group, },
+ { "hosts", hosts, },
+ { "ahosts", ahosts, },
+ { "ahostsv4", ahostsv4, },
+ { "ahostsv6", ahostsv6, },
+ { "networks", networks, },
+ { "passwd", passwd, },
+ { "protocols", protocols, },
+ { "services", services, },
+ { "shadow", shadow, },
+ { "shells", shells, },
+
+ { NULL, NULL, },
+};
+
+static int usage(const char *arg0)
+{
+ struct getentdb *curdb;
+ size_t i;
+
+ (void)fprintf(stderr, "Usage: %s database [key ...]\n", arg0);
+ (void)fprintf(stderr, "\tdatabase may be one of:");
+ for (i = 0, curdb = databases; curdb->name != NULL; curdb++, i++) {
+ if (i % 7 == 0)
+ (void)fputs("\n\t\t", stderr);
+ (void)fprintf(stderr, "%s%s", i % 7 == 0 ? "" : " ",
+ curdb->name);
+ }
+ (void)fprintf(stderr, "\n");
+ exit(RV_USAGE);
+ /* NOTREACHED */
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct getentdb *curdb;
+
+ if (argc < 2)
+ usage(argv[0]);
+ for (curdb = databases; curdb->name != NULL; curdb++)
+ if (strcmp(curdb->name, argv[1]) == 0)
+ return (*curdb->callback)(argc, argv);
+
+ warn("Unknown database `%s'", argv[1]);
+ usage(argv[0]);
+ /* NOTREACHED */
+}
diff --git a/core/musl/iconv.c b/core/musl/iconv.c
new file mode 100644
index 0000000..f5d5ce2
--- /dev/null
+++ b/core/musl/iconv.c
@@ -0,0 +1,110 @@
+/*
+ * iconv.c
+ * Implementation of SUSv4 XCU iconv utility
+ * Copyright © 2011 Rich Felker
+ * Licensed under the terms of the GNU General Public License, v2 or later
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iconv.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+int main(int argc, char **argv)
+{
+ const char *from=0, *to=0;
+ int b;
+ iconv_t cd;
+ char buf[BUFSIZ];
+ char outbuf[BUFSIZ*4];
+ char *in, *out;
+ size_t inb;
+ size_t l;
+ size_t unitsize=0;
+ int err=0;
+ FILE *f;
+
+ while ((b = getopt(argc, argv, "f:t:csl")) != EOF) switch(b) {
+ case 'l':
+ puts("UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF32-LE, UCS-2BE, UCS-2LE, WCHAR_T,\n"
+ "US_ASCII, ISO8859-1, ISO8859-2, ISO8859-3, ISO8859-4, ISO8859-5,\n"
+ "ISO8859-6, ISO8859-7, ...");
+ exit(0);
+ case 'c': case 's': break;
+ case 'f': from=optarg; break;
+ case 't': to=optarg; break;
+ default: exit(1);
+ }
+
+ if (!from || !to) {
+ setlocale(LC_CTYPE, "");
+ if (!to) to = nl_langinfo(CODESET);
+ if (!from) from = nl_langinfo(CODESET);
+ }
+ cd = iconv_open(to, from);
+ if (cd == (iconv_t)-1) {
+ if (iconv_open(to, "WCHAR_T") == (iconv_t)-1)
+ fprintf(stderr, "iconv: destination charset %s: ", to);
+ else
+ fprintf(stderr, "iconv: source charset %s: ", from);
+ perror("");
+ exit(1);
+ }
+ if (optind == argc) argv[argc++] = "-";
+
+ for (; optind < argc; optind++) {
+ if (argv[optind][0]=='-' && !argv[optind][1]) {
+ f = stdin;
+ argv[optind] = "(stdin)";
+ } else if (!(f = fopen(argv[optind], "rb"))) {
+ fprintf(stderr, "iconv: %s: ", argv[optind]);
+ perror("");
+ err = 1;
+ continue;
+ }
+ inb = 0;
+ for (;;) {
+ in = buf;
+ out = outbuf;
+ l = fread(buf+inb, 1, sizeof(buf)-inb, f);
+ inb += l;
+ if (!inb) break;
+ if (iconv(cd, &in, &inb, &out, (size_t [1]){sizeof outbuf})==-1
+ && errno == EILSEQ) {
+ if (!unitsize) {
+ wchar_t wc='0';
+ char dummy[4], *dummyp=dummy;
+ iconv_t cd2 = iconv_open(from, "WCHAR_T");
+ if (cd == (iconv_t)-1) {
+ unitsize = 1;
+ } else {
+ iconv(cd2,
+ (char *[1]){(char *)&wc},
+ (size_t[1]){1},
+ &dummyp, (size_t[1]){4});
+ unitsize = dummyp-dummy;
+ if (!unitsize) unitsize=1;
+ }
+ }
+ inb-=unitsize;
+ in+=unitsize;
+ }
+ if (inb && !l && errno==EINVAL) break;
+ if (out>outbuf && !fwrite(outbuf, out-outbuf, 1, stdout)) {
+ perror("iconv: write error");
+ exit(1);
+ }
+ if (inb) memmove(buf, in, inb);
+ }
+ if (ferror(f)) {
+ fprintf(stderr, "iconv: %s: ", argv[optind]);
+ perror("");
+ err = 1;
+ }
+ }
+ return err;
+}
diff --git a/core/musl/ldd b/core/musl/ldd
new file mode 100644
index 0000000..f522968
--- /dev/null
+++ b/core/musl/ldd
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+if [ $# -gt 1 ] && [ "$1" = "--" ]; then
+ shift
+elif [ $# -eq 0 ] || [ "${1#-}" != "$1" ]; then
+ echo "Usage: ${0##*/} [--] FILE..." >&2
+ exit 64
+fi
+
+ERRORS=0
+for PROGRAM in "$@"; do
+ LIBRARIES=$(/lib/ld-musl-x86_64.so.1 --list "$PROGRAM")
+ if [ -n "$LIBRARIES" ]; then
+ printf '%s:\n%s\n' "$PROGRAM" "$LIBRARIES"
+ else
+ ERRORS=1
+ fi
+done
+exit $ERRORS