From f00ea22784d28a92b14dd5b570eda217c7d9a462 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Thu, 11 Jul 2013 05:38:46 +0000
Subject: [PATCH] main/musl: various fixes from git master, and packaging fixes

- use upstream commits for all arm pie/unwind fixes
- replace getopt with BSD licensed GNU compatible getopt
- set proper SONAME for the libc generated for packaging purposes
- rename libc.so to be ld-musl-$ARCH.so.1 and point the SONAME
  and ldd links to it. this allows libc.so to go to -dev package
  as it will be used for compiling only.
- move specs file to musl-crosstool subpackage
---
 ...make-install-works-before-include-bi.patch |   4 +-
 ...-additional-legacy-ether.h-functions.patch |   4 +-
 ...-add-legacy-scsi-scsi_ioctl.h-header.patch |  30 +
 ...-add-legacy-sys-ttydefaults.h-header.patch |  58 ++
 ...s-select.h-with-appropriate-feature.patch} |   5 +-
 ...-off-by-one-array-bound-in-strsignal.patch |  25 +
 ...ary-phdr-pointers-passed-to-callback.patch |  81 +++
 ...I-specific-exception-handling-infras.patch |  66 ++
 main/musl/0009-add-PIE-support-for-ARM.patch  |  49 ++
 main/musl/APKBUILD                            |  79 ++-
 main/musl/crt-arm-Scrt1.s                     |  34 -
 main/musl/getopt_long.c                       | 618 ++++++++++++++++++
 12 files changed, 992 insertions(+), 61 deletions(-)
 create mode 100644 main/musl/0003-add-legacy-scsi-scsi_ioctl.h-header.patch
 create mode 100644 main/musl/0004-add-legacy-sys-ttydefaults.h-header.patch
 rename main/musl/{0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch => 0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch} (86%)
 create mode 100644 main/musl/0006-fix-off-by-one-array-bound-in-strsignal.patch
 create mode 100644 main/musl/0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch
 create mode 100644 main/musl/0008-add-some-ARM-EABI-specific-exception-handling-infras.patch
 create mode 100644 main/musl/0009-add-PIE-support-for-ARM.patch
 delete mode 100644 main/musl/crt-arm-Scrt1.s
 create mode 100644 main/musl/getopt_long.c

diff --git a/main/musl/0001-fix-Makefile-so-make-install-works-before-include-bi.patch b/main/musl/0001-fix-Makefile-so-make-install-works-before-include-bi.patch
index 5b080bd2f577..42d5be18bbdb 100644
--- a/main/musl/0001-fix-Makefile-so-make-install-works-before-include-bi.patch
+++ b/main/musl/0001-fix-Makefile-so-make-install-works-before-include-bi.patch
@@ -1,7 +1,7 @@
-From d66ab4f1409ad1a2093239ef48b7bca596acdf52 Mon Sep 17 00:00:00 2001
+From 997d58d8052fb9f8374afd2fb456785f53217f50 Mon Sep 17 00:00:00 2001
 From: Rich Felker <dalias@aerifal.cx>
 Date: Mon, 1 Jul 2013 13:43:43 -0400
-Subject: [PATCH 1/2] fix Makefile so "make install" works before include/bits
+Subject: [PATCH 1/9] fix Makefile so "make install" works before include/bits
  symlink exists
 
 previously, determination of the list of header files for installation
diff --git a/main/musl/0002-add-stubs-for-additional-legacy-ether.h-functions.patch b/main/musl/0002-add-stubs-for-additional-legacy-ether.h-functions.patch
index 4d23b32f961d..fb25c9ae1110 100644
--- a/main/musl/0002-add-stubs-for-additional-legacy-ether.h-functions.patch
+++ b/main/musl/0002-add-stubs-for-additional-legacy-ether.h-functions.patch
@@ -1,7 +1,7 @@
-From fbcd82040cb67ee14886c6ac4c200cde3662f986 Mon Sep 17 00:00:00 2001
+From 6e31b284fe98686f8a763de775a087da3be05024 Mon Sep 17 00:00:00 2001
 From: Rich Felker <dalias@aerifal.cx>
 Date: Mon, 1 Jul 2013 13:50:02 -0400
-Subject: [PATCH 2/2] add stubs for additional legacy ether.h functions
+Subject: [PATCH 2/9] add stubs for additional legacy ether.h functions
 
 these would not be expensive to actually implement, but reading
 /etc/ethers does not sound like a particularly useful feature, so for
diff --git a/main/musl/0003-add-legacy-scsi-scsi_ioctl.h-header.patch b/main/musl/0003-add-legacy-scsi-scsi_ioctl.h-header.patch
new file mode 100644
index 000000000000..fe67990a4507
--- /dev/null
+++ b/main/musl/0003-add-legacy-scsi-scsi_ioctl.h-header.patch
@@ -0,0 +1,30 @@
+From 5ece469f37e5cdddb86871b56f4f74674690fbe4 Mon Sep 17 00:00:00 2001
+From: rofl0r <retnyg@gmx.net>
+Date: Wed, 3 Jul 2013 17:52:44 +0200
+Subject: [PATCH 3/9] add legacy scsi/scsi_ioctl.h header
+
+---
+ include/scsi/scsi_ioctl.h | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+ create mode 100644 include/scsi/scsi_ioctl.h
+
+diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
+new file mode 100644
+index 0000000..22df7fe
+--- /dev/null
++++ b/include/scsi/scsi_ioctl.h
+@@ -0,0 +1,11 @@
++#ifndef _SCSI_IOCTL_H
++#define _SCSI_IOCTL_H
++#define SCSI_IOCTL_SEND_COMMAND 1
++#define SCSI_IOCTL_TEST_UNIT_READY 2
++#define SCSI_IOCTL_BENCHMARK_COMMAND 3
++#define SCSI_IOCTL_SYNC 4
++#define SCSI_IOCTL_START_UNIT 5
++#define SCSI_IOCTL_STOP_UNIT 6
++#define SCSI_IOCTL_DOORLOCK 0x5380
++#define SCSI_IOCTL_DOORUNLOCK 0x5381
++#endif
+-- 
+1.8.3.2
+
diff --git a/main/musl/0004-add-legacy-sys-ttydefaults.h-header.patch b/main/musl/0004-add-legacy-sys-ttydefaults.h-header.patch
new file mode 100644
index 000000000000..e5d6f2cea44f
--- /dev/null
+++ b/main/musl/0004-add-legacy-sys-ttydefaults.h-header.patch
@@ -0,0 +1,58 @@
+From 129a34db6328cb13fec4d5f2d2703cb7922e8634 Mon Sep 17 00:00:00 2001
+From: rofl0r <retnyg@gmx.net>
+Date: Wed, 3 Jul 2013 17:55:37 +0200
+Subject: [PATCH 4/9] add legacy sys/ttydefaults.h header
+
+---
+ include/sys/ttydefaults.h | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+ create mode 100644 include/sys/ttydefaults.h
+
+diff --git a/include/sys/ttydefaults.h b/include/sys/ttydefaults.h
+new file mode 100644
+index 0000000..d251b71
+--- /dev/null
++++ b/include/sys/ttydefaults.h
+@@ -0,0 +1,39 @@
++#ifndef _SYS_TTYDEFAULTS_H
++#define _SYS_TTYDEFAULTS_H
++
++#define TTYDEF_IFLAG (BRKINT | ISTRIP | ICRNL | IMAXBEL | IXON | IXANY)
++#define TTYDEF_OFLAG (OPOST | ONLCR | XTABS)
++#define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
++#define TTYDEF_CFLAG (CREAD | CS7 | PARENB | HUPCL)
++#define TTYDEF_SPEED (B9600)
++#define CTRL(x) (x&037)
++#define CEOF CTRL('d')
++
++#ifdef _POSIX_VDISABLE
++#define CEOL _POSIX_VDISABLE
++#define CSTATUS _POSIX_VDISABLE
++#else
++#define CEOL '\0'
++#define CSTATUS '\0'
++#endif
++
++#define CERASE 0177
++#define CINTR CTRL('c')
++#define CKILL CTRL('u')
++#define CMIN 1
++#define CQUIT 034
++#define CSUSP CTRL('z')
++#define CTIME 0
++#define CDSUSP CTRL('y')
++#define CSTART CTRL('q')
++#define CSTOP CTRL('s')
++#define CLNEXT CTRL('v')
++#define CDISCARD CTRL('o')
++#define CWERASE CTRL('w')
++#define CREPRINT CTRL('r')
++#define CEOT CEOF
++#define CBRK CEOL
++#define CRPRNT CREPRINT
++#define CFLUSH CDISCARD
++
++#endif
+-- 
+1.8.3.2
+
diff --git a/main/musl/0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch b/main/musl/0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
similarity index 86%
rename from main/musl/0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
rename to main/musl/0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
index dc5cc287e4f3..3738bc5620f6 100644
--- a/main/musl/0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
+++ b/main/musl/0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
@@ -1,7 +1,8 @@
-From ca9aff6a1646c7fc106bfbb9399b3a1bcb14f18b Mon Sep 17 00:00:00 2001
+From 9b9dc74b67b9ecd30db9f3266a5ce309b0ffbfef Mon Sep 17 00:00:00 2001
 From: Rich Felker <dalias@aerifal.cx>
 Date: Sat, 6 Jul 2013 01:12:28 -0400
-Subject: [PATCH] add NFDBITS in sys/select.h with appropriate feature tests
+Subject: [PATCH 5/9] add NFDBITS in sys/select.h with appropriate feature
+ tests
 
 the main use for this macro seems to be knowing the correct allocation
 granularity for dynamic-sized fd_set objects. such usage is
diff --git a/main/musl/0006-fix-off-by-one-array-bound-in-strsignal.patch b/main/musl/0006-fix-off-by-one-array-bound-in-strsignal.patch
new file mode 100644
index 000000000000..e349d3b29b2e
--- /dev/null
+++ b/main/musl/0006-fix-off-by-one-array-bound-in-strsignal.patch
@@ -0,0 +1,25 @@
+From 9134a8ca79fa9c79eada278b10f4d6b1eaf271d3 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Tue, 9 Jul 2013 02:11:52 -0400
+Subject: [PATCH 6/9] fix off-by-one array bound in strsignal
+
+---
+ src/string/strsignal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/string/strsignal.c b/src/string/strsignal.c
+index 3b0ae6d..d70982a 100644
+--- a/src/string/strsignal.c
++++ b/src/string/strsignal.c
+@@ -48,7 +48,7 @@ static const char map[] = {
+ 	[SIGSYS]    = 31
+ };
+ 
+-#define sigmap(x) ((unsigned)(x) > sizeof map ? 0 : map[(unsigned)(x)])
++#define sigmap(x) ((unsigned)(x) >= sizeof map ? 0 : map[(unsigned)(x)])
+ 
+ #endif
+ 
+-- 
+1.8.3.2
+
diff --git a/main/musl/0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch b/main/musl/0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch
new file mode 100644
index 000000000000..1ebc977479bc
--- /dev/null
+++ b/main/musl/0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch
@@ -0,0 +1,81 @@
+From 0ccea50c697512b4bcbe76780260dfba09450327 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Wed, 10 Jul 2013 14:38:20 -0400
+Subject: [PATCH 7/9] fix invalid library phdr pointers passed to callback from
+ dl_iterate_phdr
+
+map_library was saving pointers to an automatic-storage buffer rather
+than pointers into the mapping. this should be a fairly simple fix,
+but the patch here is slightly complicated by two issues:
+
+1. supporting gratuitously obfuscated ELF files where the program
+headers are not right at the beginning of the file.
+
+2. cleaning up the map_library function so that data isn't clobbered
+by the time we need it.
+---
+ src/ldso/dynlink.c | 25 ++++++++++++++++---------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
+index 7031d03..ff5b738 100644
+--- a/src/ldso/dynlink.c
++++ b/src/ldso/dynlink.c
+@@ -309,7 +309,7 @@ static void *map_library(int fd, struct dso *dso)
+ 	size_t this_min, this_max;
+ 	off_t off_start;
+ 	Ehdr *eh;
+-	Phdr *ph;
++	Phdr *ph, *ph0;
+ 	unsigned prot;
+ 	unsigned char *map, *base;
+ 	size_t dyn;
+@@ -324,11 +324,10 @@ static void *map_library(int fd, struct dso *dso)
+ 	if (eh->e_phoff + phsize > l) {
+ 		l = pread(fd, buf+1, phsize, eh->e_phoff);
+ 		if (l != phsize) return 0;
+-		eh->e_phoff = sizeof *eh;
++		ph = ph0 = (void *)(buf + 1);
++	} else {
++		ph = ph0 = (void *)((char *)buf + eh->e_phoff);
+ 	}
+-	ph = (void *)((char *)buf + eh->e_phoff);
+-	dso->phdr = ph;
+-	dso->phnum = eh->e_phnum;
+ 	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
+ 		if (ph->p_type == PT_DYNAMIC)
+ 			dyn = ph->p_vaddr;
+@@ -363,9 +362,18 @@ static void *map_library(int fd, struct dso *dso)
+ 	map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
+ 	if (map==MAP_FAILED) return 0;
+ 	base = map - addr_min;
+-	ph = (void *)((char *)buf + eh->e_phoff);
+-	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
++	dso->phdr = 0;
++	dso->phnum = 0;
++	for (ph=ph0, i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
+ 		if (ph->p_type != PT_LOAD) continue;
++		/* Check if the programs headers are in this load segment, and
++		 * if so, record the address for use by dl_iterate_phdr. */
++		if (!dso->phdr && eh->e_phoff >= ph->p_offset
++		    && eh->e_phoff+phsize <= ph->p_offset+ph->p_filesz) {
++			dso->phdr = (void *)(base + ph->p_vaddr
++				+ (eh->e_phoff-ph->p_offset));
++			dso->phnum = eh->e_phnum;
++		}
+ 		/* Reuse the existing mapping for the lowest-address LOAD */
+ 		if ((ph->p_vaddr & -PAGE_SIZE) == addr_min) continue;
+ 		this_min = ph->p_vaddr & -PAGE_SIZE;
+@@ -390,8 +398,7 @@ static void *map_library(int fd, struct dso *dso)
+ 				goto error;
+ 			break;
+ 		}
+-	if (!runtime) reclaim_gaps(base, (void *)((char *)buf + eh->e_phoff),
+-		eh->e_phentsize, eh->e_phnum);
++	if (!runtime) reclaim_gaps(base, ph0, eh->e_phentsize, eh->e_phnum);
+ 	dso->map = map;
+ 	dso->map_len = map_len;
+ 	dso->base = base;
+-- 
+1.8.3.2
+
diff --git a/main/musl/0008-add-some-ARM-EABI-specific-exception-handling-infras.patch b/main/musl/0008-add-some-ARM-EABI-specific-exception-handling-infras.patch
new file mode 100644
index 000000000000..56b09d7cf2de
--- /dev/null
+++ b/main/musl/0008-add-some-ARM-EABI-specific-exception-handling-infras.patch
@@ -0,0 +1,66 @@
+From f39afb9ffb34b747bfc1ec9d77b239c0c32a754d Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Wed, 10 Jul 2013 16:11:01 -0400
+Subject: [PATCH 8/9] add some ARM EABI-specific exception handling
+ infrastructure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+patch by Timo Teräs
+---
+ arch/arm/src/find_exidx.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+ create mode 100644 arch/arm/src/find_exidx.c
+
+diff --git a/arch/arm/src/find_exidx.c b/arch/arm/src/find_exidx.c
+new file mode 100644
+index 0000000..77c4472
+--- /dev/null
++++ b/arch/arm/src/find_exidx.c
+@@ -0,0 +1,42 @@
++#define _GNU_SOURCE
++#include <link.h>
++#include <stdint.h>
++
++struct find_exidx_data {
++	uintptr_t pc, exidx_start;
++	int exidx_len;
++};
++
++static int find_exidx(struct dl_phdr_info *info, size_t size, void *ptr)
++{
++	struct find_exidx_data *data = ptr;
++	const ElfW(Phdr) *phdr = info->dlpi_phdr;
++	uintptr_t addr, exidx_start = 0;
++	int i, match = 0, exidx_len = 0;
++
++	for (i = info->dlpi_phnum; i > 0; i--, phdr++) {
++		addr = info->dlpi_addr + phdr->p_vaddr;
++		switch (phdr->p_type) {
++		case PT_LOAD:
++			match |= data->pc >= addr && data->pc < addr + phdr->p_memsz;
++			break;
++		case PT_ARM_EXIDX:
++			exidx_start = addr;
++			exidx_len = phdr->p_memsz;
++			break;
++		}
++	}
++	data->exidx_start = exidx_start;
++	data->exidx_len = exidx_len;
++	return match;
++}
++
++uintptr_t __gnu_Unwind_Find_exidx(uintptr_t pc, int *pcount)
++{
++	struct find_exidx_data data;
++	data.pc = pc;
++	if (dl_iterate_phdr(find_exidx, &data) <= 0)
++		return 0;
++	*pcount = data.exidx_len / 8;
++	return data.exidx_start;
++}
+-- 
+1.8.3.2
+
diff --git a/main/musl/0009-add-PIE-support-for-ARM.patch b/main/musl/0009-add-PIE-support-for-ARM.patch
new file mode 100644
index 000000000000..3ced0277a968
--- /dev/null
+++ b/main/musl/0009-add-PIE-support-for-ARM.patch
@@ -0,0 +1,49 @@
+From 84934ac8bcebb41ffca1703d97512682069c68ec Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Wed, 10 Jul 2013 16:58:27 -0400
+Subject: [PATCH 9/9] add PIE support for ARM
+
+---
+ crt/arm/Scrt1.s | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+ create mode 100644 crt/arm/Scrt1.s
+
+diff --git a/crt/arm/Scrt1.s b/crt/arm/Scrt1.s
+new file mode 100644
+index 0000000..a54859a
+--- /dev/null
++++ b/crt/arm/Scrt1.s
+@@ -0,0 +1,30 @@
++.weak _init
++.weak _fini
++.global _start
++_start:
++	mov fp,#0
++	mov lr,#0
++
++	ldr a2,[sp],#4
++	mov a3,sp
++	str fp,[sp,#-4]!
++	str a1,[sp,#-4]!
++
++	adr ip,2f
++	ldr a4,2f+4
++	add a4,a4,ip
++	str a4,[sp,#-4]!
++	ldr a4,2f+8
++	add a4,a4,ip
++
++	ldr a1,2f
++	add ip,ip,a1
++	ldr a1,2f+12
++	ldr a1,[ip,a1]
++
++	bl __libc_start_main(PLT)
++1:	b 1b
++2:	.word _GLOBAL_OFFSET_TABLE_-2b
++	.word _fini-2b
++	.word _init-2b
++	.word main(GOT)
+-- 
+1.8.3.2
+
diff --git a/main/musl/APKBUILD b/main/musl/APKBUILD
index f693d63f4b11..1a68391b102a 100644
--- a/main/musl/APKBUILD
+++ b/main/musl/APKBUILD
@@ -2,7 +2,7 @@
 # Maintainer: William Pitcock <nenolod@dereferenced.org>
 pkgname=musl
 pkgver=0.9.11
-pkgrel=1
+pkgrel=2
 pkgdesc="the musl c library (libc) implementation"
 url="http://www.musl-libc.org/"
 arch="x86 x86_64 arm armel"
@@ -16,8 +16,15 @@ subpackages="$pkgname-dev $pkgname-utils"
 source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz
 	0001-fix-Makefile-so-make-install-works-before-include-bi.patch
 	0002-add-stubs-for-additional-legacy-ether.h-functions.patch
-	0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
-	crt-arm-Scrt1.s
+	0003-add-legacy-scsi-scsi_ioctl.h-header.patch
+	0004-add-legacy-sys-ttydefaults.h-header.patch
+	0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
+	0006-fix-off-by-one-array-bound-in-strsignal.patch
+	0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch
+	0008-add-some-ARM-EABI-specific-exception-handling-infras.patch
+	0009-add-PIE-support-for-ARM.patch
+
+	getopt_long.c
 	getent
 	"
 
@@ -30,16 +37,17 @@ prepare() {
 		*.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
 		esac
 	done
-	cp "$srcdir"/crt-arm-Scrt1.s crt/arm/Scrt1.s
+
+	# use GNU compatible getopt() from BSD
+	rm -f src/misc/getopt*.c
+	cp "$srcdir"/getopt_long.c src/misc/
 }
 
 build() {
 	local _ldflags
 	cd "$_builddir"
-	[ "${CTARGET#*musl}" = "$CTARGET" ] && _ldflags="-Wl,-soname,libc-musl-${CARCH}.so"
-	LDFLAGS="$LDFLAGS $_ldflags" \
+	LDFLAGS="$LDFLAGS -Wl,-soname,libc.musl-${CARCH}.so.1" \
 	./configure --prefix=/usr \
-		--libdir=/lib \
 		--sysconfdir=/etc \
 		--mandir=/usr/share/man \
 		--infodir=/usr/share/info \
@@ -52,34 +60,63 @@ package() {
 	cd "$_builddir"
 	make DESTDIR="$pkgdir" install || return 1
 	rm -f "$pkgdir"/usr/lib/*.la
+
+	# make LDSO the be the real file, and libc the symlink (will be upstream change)
+	local LDSO=$(make -f Makefile --eval "$(echo -e 'print-ldso:\n\t@echo $$(basename $(LDSO_PATHNAME))')" print-ldso)
+	mv -f "$pkgdir"/usr/lib/libc.so "$pkgdir"/lib/"$LDSO" || return 1
+	ln -sf "$LDSO" "$pkgdir"/lib/libc.musl-${CARCH}.so.1 || return 1
+	ln -sf ../../lib/"$LDSO" "$pkgdir"/usr/lib/libc.so || return 1
+	mkdir -p "$pkgdir"/usr/bin
+	ln -sf ../../lib/"$LDSO" "$pkgdir"/usr/bin/ldd || return 1
 }
 
 utils() {
 	mkdir -p "$subpkgdir"/usr/bin
-	ln -s /lib/libc.so "$subpkgdir"/usr/bin/ldd
+	mv "$pkgdir"/usr/bin/ldd "$subpkgdir"/usr/bin
+	find "$pkgdir" -type d -delete 2>/dev/null
 	install -D "$srcdir"/getent "$subpkgdir"/usr/bin/getent
 }
 
 crosstool() {
-	mkdir -p "$subpkgdir"/usr/bin
+	mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/usr/lib
 	mv "$pkgdir"/usr/bin/musl-gcc "$subpkgdir"/usr/bin
+	mv "$pkgdir"/usr/lib/musl-gcc.specs "$subpkgdir"/usr/lib
+	find "$pkgdir" -type d -delete 2>/dev/null
 }
 
 md5sums="70b17ca5c847e74e1c77fe8284bb1fa4  musl-0.9.11.tar.gz
-1565f77513aa6779057ff184a2f91073  0001-fix-Makefile-so-make-install-works-before-include-bi.patch
-76e0b13d63a6665b3f9ea3d3b00fecdb  0002-add-stubs-for-additional-legacy-ether.h-functions.patch
-726f0c448aaf042157c83513c1b2faf0  0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
-da55f98744cdcdaf59efac116403c790  crt-arm-Scrt1.s
+aad8311afd9731c4fc0b233b2f8fbea6  0001-fix-Makefile-so-make-install-works-before-include-bi.patch
+784768d2852b9e92331b0e4a113885f0  0002-add-stubs-for-additional-legacy-ether.h-functions.patch
+68972594ee10388b927c4dab8752ff40  0003-add-legacy-scsi-scsi_ioctl.h-header.patch
+be8d8679592120ac58d8e8cd65955858  0004-add-legacy-sys-ttydefaults.h-header.patch
+7e34c5d8e8b2561a5c208f45914f5098  0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
+dc3391e1c71f054457a94e96b5c439da  0006-fix-off-by-one-array-bound-in-strsignal.patch
+2a34be5410b4b6f849ac65886fe512c0  0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch
+254ac95d521dd908739f2d9e361b9129  0008-add-some-ARM-EABI-specific-exception-handling-infras.patch
+1eb1f8e1574a70bc39cc66aad536236b  0009-add-PIE-support-for-ARM.patch
+acbb8a052228d9d5b89bc2ed55616fe3  getopt_long.c
 ef81489a6258501cf45db58dfc6d5211  getent"
 sha256sums="8b81fd9b71becb7b674ea93fd65d82a039fab79ab738957a5e9ee47ba08a13fd  musl-0.9.11.tar.gz
-60e38a633d35eb44c7b12b3a2b0ea570c9462af7f966a9fcea4382fe6e6e6c6f  0001-fix-Makefile-so-make-install-works-before-include-bi.patch
-6c916f34bb2dc89fc3de6786d9b7e2d2b829d9020e97097e46b97071be09405a  0002-add-stubs-for-additional-legacy-ether.h-functions.patch
-577307cae7d00ab2f5a9e2530f462b417bf7112f739a0a0cd3327d7f793edb65  0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
-636788dda68b3aed647b3a30b06401823c90c2cf8ce085b270ce27c77e8919f3  crt-arm-Scrt1.s
+55e07c49e420af16ee2783613b43cb2673b9f4006ede03d202faf53bd103a1c1  0001-fix-Makefile-so-make-install-works-before-include-bi.patch
+76b9e2f477ac9c536293f0b7e48d87fdc267e87bda8990c406af8e5314bdc93b  0002-add-stubs-for-additional-legacy-ether.h-functions.patch
+f0c51e603f9b45fbcf0a2a372a9867cda5d6a561367b6320dc9f221ac1d9f5d0  0003-add-legacy-scsi-scsi_ioctl.h-header.patch
+ac580e372f3f35ecbf56ad4a2a245a2f6717be2ddf545169d89b2c7a8c471996  0004-add-legacy-sys-ttydefaults.h-header.patch
+ebbb392854f4ff0bcf5687611c9d0793ebbcbd65824de1a8b861c6f35eeaa1ed  0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
+05b367fa68f444ab4722bddde88f01973fb850f696320a2a115626a5bff094d3  0006-fix-off-by-one-array-bound-in-strsignal.patch
+a3de225c2b0e325333ecdfdf015ece988e8f0533f3056cfcd0b855680d7c2264  0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch
+d5af7765f2ec1f92f42d6d9d94fd1a1fefa876760141a4701a57db1d5d71e21a  0008-add-some-ARM-EABI-specific-exception-handling-infras.patch
+25034a597d18f04fc371c97bc7ab014ff3ec2d185cfb3abc7d3bbcbc63fde3fc  0009-add-PIE-support-for-ARM.patch
+5427781da6c5877c017eeccba58c70bce3451536355ac949699ed807137a476a  getopt_long.c
 d6996273f5aaaed429058257e4646b243d9e3a4d8609522f802762453f5be4cb  getent"
 sha512sums="7ca852eda3be7b34bfdaf1eb9e7d435987d5177f865737b211e62f4037825cc322436e1ff49c3f875b3a20679f6f21ba5ffff271d03d3d03c7a97854f4f51832  musl-0.9.11.tar.gz
-80d9e3594c4f7471ea404216b40a44831bfa930f81792e566e83d7e1a158ee5d5f75129b67536c969f10fbe96aa549326ba461229fb0a08e0a3fd1bc569f95fc  0001-fix-Makefile-so-make-install-works-before-include-bi.patch
-24415afa48c9e918c4c7a0c1e5a38bd150d03e92cde6bf709460c713de49a61128ea93103af601a54a6cf164bcedd304aa34933e97053e1b4ab41584ce44f768  0002-add-stubs-for-additional-legacy-ether.h-functions.patch
-3e2164caf37f973e470832198dc8a4cdafe599cdd787c5e6e46a6a55367eb1db4032f56fb1165ddf1232df1468f276488c2d8269f530d93f249d659b62b76e8e  0003-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
-2bcc69f766e0d841938b7d357b54878597fed97a6b6401b666aa07834ca3c773b9d262103ab0b129e18df00f38e51244c9966e1c138b06cbbf181e32be3ae078  crt-arm-Scrt1.s
+02eee7261d28d2cac59910839dfc7b9389bec8bee3f68dc21a0b1d4fd112ffddaae8aadf4392528773dc0c5a48715cdc525a2ba3a51ac5f34fb49e9ceb49e644  0001-fix-Makefile-so-make-install-works-before-include-bi.patch
+4b71a25a539ee35a0183503ba28583a38fb96dffa38de63ff8ba0e62893f84e1832e22aca506e1d79e41e2b37c712acf38f479c6b46d5e3237c8158db2352b36  0002-add-stubs-for-additional-legacy-ether.h-functions.patch
+b4b3724b754ad3cf56ffbfe9bdd4cafbebb14e1d16a094793a0bf2e219f29e0a7547e123664bd1d7ffa3149f4a52be387e391b5903f967a2f57fbb3161b4fdaf  0003-add-legacy-scsi-scsi_ioctl.h-header.patch
+cab60cb2baf86128fd5d45d83ae0315afefce9e1d91b7c5fa3fffc02b1483f753eedae01f226fe339d693de44236292e7b79e3abcc25e823f955aab83889c629  0004-add-legacy-sys-ttydefaults.h-header.patch
+e9cd8c3994a22f48288279b2678e24415ab29a8f462df087de63b7415581059d6bd412d17b7d7008cd97ac09276f514fc4bd6cd4e39ee2fd4d7c8591e8478f4c  0005-add-NFDBITS-in-sys-select.h-with-appropriate-feature.patch
+20e91a56000ac53bf5d5db8e1f731a2f80824ee6e4a057d64e193601f3d45b1e3dbd836de82cf4c8d855eedb88e9a61f48c30b2b772840bdbd5c004c71cb0deb  0006-fix-off-by-one-array-bound-in-strsignal.patch
+a70092efce1fbd02fd8c82bef5bb4c51c98f8023a5fdd7ec3c64519ceb98b72745b375d002c85c29d1adef09ac06bc433505f358e8c3516828291b3f8503626d  0007-fix-invalid-library-phdr-pointers-passed-to-callback.patch
+20dd237aa8e9eda29fac0b443abe3ebb45692221425c31f4453d2f9a5394687d5befac00a755bf098b0ac3707ee8c5a52ebf78cc11c5d719f567afb626ddc2dd  0008-add-some-ARM-EABI-specific-exception-handling-infras.patch
+b739639e90c8d6c985732dee44e2eadf12195876e60f64437a147fbbd5c758d84fb5078ef0c48ccb560d2c8f0b849e3e4670a2f1cd7f15c075b7b8a95563e2c8  0009-add-PIE-support-for-ARM.patch
+e5e945f26daae5498e2a2e463d4bb3724294bc5dd4bf9a93a0f18e333f277e18e5977e144642bf45185d25ffa167316fe9914c9885d491a0034b2f4cccb0d07f  getopt_long.c
 4d92f934d760cf5157d80f19fd766be6b673c65317229b32ac824d9d192f6abcc414e2382b2416dfd5c2f757b46ced98c18e4762bf91f5a48647e0ee61813b06  getent"
diff --git a/main/musl/crt-arm-Scrt1.s b/main/musl/crt-arm-Scrt1.s
deleted file mode 100644
index b8fdfda9950c..000000000000
--- a/main/musl/crt-arm-Scrt1.s
+++ /dev/null
@@ -1,34 +0,0 @@
-.weak _init
-.weak _fini
-.text
-.global _start
-_start:
-        mov fp,#0
-        mov lr,#0
-
-        pop { a2 }
-        mov a3, sp
-        push { a3 }
-        push { a1 }
-
-        ldr sl, .L_GOT
-        adr a4, .L_GOT
-        add sl, sl, a4
-        ldr ip, .L_GOT+4
-        ldr ip, [sl, ip]
-        push { ip }
-        ldr a4, .L_GOT+8
-        ldr a4, [sl, a4]
-        ldr a1, .L_GOT+12
-        ldr a1, [sl, a1]
-
-        bl __libc_start_main(PLT)
-1:      b 1b
-
-        .align 2
-.L_GOT:
-        .word _GLOBAL_OFFSET_TABLE_ - .L_GOT
-        .word _fini(GOT)
-        .word _init(GOT)
-        .word main(GOT)
-
diff --git a/main/musl/getopt_long.c b/main/musl/getopt_long.c
new file mode 100644
index 000000000000..173fed347e2b
--- /dev/null
+++ b/main/musl/getopt_long.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define GNU_COMPATIBLE		/* Be more compatible, configure's use us! */
+
+int	opterr = 1;		/* if error message should be printed */
+int	optind = 1;		/* index into parent argv vector */
+int	optopt = '?';		/* character checked for validity */
+int	optreset;		/* reset getopt */
+char    *optarg;		/* argument associated with option */
+
+#define PRINT_ERROR	((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE	0x01	/* permute non-options to the end of argv */
+#define FLAG_ALLARGS	0x02	/* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY	0x04	/* operate as getopt_long_only */
+
+/* return values */
+#define	BADCH		(int)'?'
+#define	BADARG		((*options == ':') ? (int)':' : (int)'?')
+#define	INORDER 	(int)1
+
+#define	EMSG		""
+
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX	(-1)
+#define D_PREFIX	0
+#define DD_PREFIX	1
+#define W_PREFIX	2
+#endif
+
+static int getopt_internal(int, char * const *, const char *,
+			   const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+			      const struct option *, int *, int, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1;   /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c\n";
+static const char illoptchar[] = "illegal option -- %c\n"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c\n";
+
+static const char recargstring[] = "option `%s%s' requires an argument\n";
+static const char ambig[] = "option `%s%.*s' is ambiguous\n";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument\n";
+static const char illoptstring[] = "unrecognized option `%s%s'\n";
+#else
+static const char recargstring[] = "option requires an argument -- %s\n";
+static const char ambig[] = "ambiguous option -- %.*s\n";
+static const char noarg[] = "option doesn't take an argument -- %.*s\n";
+static const char illoptstring[] = "unknown option -- %s\n";
+#endif
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+	int c;
+
+	c = a % b;
+	while (c != 0) {
+		a = b;
+		b = c;
+		c = a % b;
+	}
+
+	return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+	char * const *nargv)
+{
+	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+	char *swap;
+
+	/*
+	 * compute lengths of blocks and number and size of cycles
+	 */
+	nnonopts = panonopt_end - panonopt_start;
+	nopts = opt_end - panonopt_end;
+	ncycle = gcd(nnonopts, nopts);
+	cyclelen = (opt_end - panonopt_start) / ncycle;
+
+	for (i = 0; i < ncycle; i++) {
+		cstart = panonopt_end+i;
+		pos = cstart;
+		for (j = 0; j < cyclelen; j++) {
+			if (pos >= panonopt_end)
+				pos -= nnonopts;
+			else
+				pos += nopts;
+			swap = nargv[pos];
+			/* LINTED const cast */
+			((char **) nargv)[pos] = nargv[cstart];
+			/* LINTED const cast */
+			((char **)nargv)[cstart] = swap;
+		}
+	}
+}
+
+/*
+ * parse_long_options --
+ *	Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int short_too, int flags)
+{
+	char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+	char *current_dash;
+#endif
+	size_t current_argv_len;
+	int i, match, exact_match, second_partial_match;
+
+	current_argv = place;
+#ifdef GNU_COMPATIBLE
+	switch (dash_prefix) {
+		case D_PREFIX:
+			current_dash = "-";
+			break;
+		case DD_PREFIX:
+			current_dash = "--";
+			break;
+		case W_PREFIX:
+			current_dash = "-W ";
+			break;
+		default:
+			current_dash = "";
+			break;
+	}
+#endif
+	match = -1;
+	exact_match = 0;
+	second_partial_match = 0;
+
+	optind++;
+
+	if ((has_equal = strchr(current_argv, '=')) != NULL) {
+		/* argument found (--option=arg) */
+		current_argv_len = has_equal - current_argv;
+		has_equal++;
+	} else
+		current_argv_len = strlen(current_argv);
+
+	for (i = 0; long_options[i].name; i++) {
+		/* find matching long option */
+		if (strncmp(current_argv, long_options[i].name,
+		    current_argv_len))
+			continue;
+
+		if (strlen(long_options[i].name) == current_argv_len) {
+			/* exact match */
+			match = i;
+			exact_match = 1;
+			break;
+		}
+		/*
+		 * If this is a known short option, don't allow
+		 * a partial match of a single character.
+		 */
+		if (short_too && current_argv_len == 1)
+			continue;
+
+		if (match == -1)        /* first partial match */
+			match = i;
+		else if ((flags & FLAG_LONGONLY) ||
+			 long_options[i].has_arg !=
+			     long_options[match].has_arg ||
+			 long_options[i].flag != long_options[match].flag ||
+			 long_options[i].val != long_options[match].val)
+			second_partial_match = 1;
+	}
+	if (!exact_match && second_partial_match) {
+		/* ambiguous abbreviation */
+		if (PRINT_ERROR) {
+			fprintf(stderr, ambig,
+#ifdef GNU_COMPATIBLE
+			     current_dash,
+#endif
+			     (int)current_argv_len,
+			     current_argv);
+		}
+		optopt = 0;
+		return (BADCH);
+	}
+	if (match != -1) {		/* option found */
+		if (long_options[match].has_arg == no_argument
+		    && has_equal) {
+			if (PRINT_ERROR) {
+				fprintf(stderr, noarg,
+#ifdef GNU_COMPATIBLE
+				     current_dash,
+#endif
+				     (int)current_argv_len,
+				     current_argv);
+			}
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+#ifdef GNU_COMPATIBLE
+			return (BADCH);
+#else
+			return (BADARG);
+#endif
+		}
+		if (long_options[match].has_arg == required_argument ||
+		    long_options[match].has_arg == optional_argument) {
+			if (has_equal)
+				optarg = has_equal;
+			else if (long_options[match].has_arg ==
+			    required_argument) {
+				/*
+				 * optional argument doesn't use next nargv
+				 */
+				optarg = nargv[optind++];
+			}
+		}
+		if ((long_options[match].has_arg == required_argument)
+		    && (optarg == NULL)) {
+			/*
+			 * Missing argument; leading ':' indicates no error
+			 * should be generated.
+			 */
+			if (PRINT_ERROR) {
+				fprintf(stderr, recargstring,
+#ifdef GNU_COMPATIBLE
+				    current_dash,
+#endif
+				    current_argv);
+			}
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+			--optind;
+			return (BADARG);
+		}
+	} else {			/* unknown option */
+		if (short_too) {
+			--optind;
+			return (-1);
+		}
+		if (PRINT_ERROR) {
+			fprintf(stderr, illoptstring,
+#ifdef GNU_COMPATIBLE
+			      current_dash,
+#endif
+			      current_argv);
+		}
+		optopt = 0;
+		return (BADCH);
+	}
+	if (idx)
+		*idx = match;
+	if (long_options[match].flag) {
+		*long_options[match].flag |= long_options[match].val;
+		return (0);
+	} else
+		return (long_options[match].val);
+}
+
+/*
+ * getopt_internal --
+ *	Parse argc/argv argument vector.  Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int flags)
+{
+	char *oli;				/* option letter list index */
+	int optchar, short_too;
+	int posixly_correct;	/* no static, can be changed on the fly */
+
+	if (options == NULL)
+		return (-1);
+
+	/*
+	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
+	 * string begins with a '+'.
+	 */
+	posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+	if (*options == '-')
+		flags |= FLAG_ALLARGS;
+	else if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
+#else
+	if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
+	else if (*options == '-')
+		flags |= FLAG_ALLARGS;
+#endif
+#if HAVE_STRICT_MODE >= 1
+	flags &= ~FLAG_PERMUTE;
+#endif
+	if (*options == '+' || *options == '-')
+		options++;
+
+	/*
+	 * XXX Some GNU programs (like cvs) set optind to 0 instead of
+	 * XXX using optreset.  Work around this braindamage.
+	 */
+	if (optind == 0)
+		optind = optreset = 1;
+
+	optarg = NULL;
+	if (optreset)
+		nonopt_start = nonopt_end = -1;
+start:
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc) {          /* end of argument vector */
+			place = EMSG;
+			if (nonopt_end != -1) {
+				/* do permutation, if we have to */
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			else if (nonopt_start != -1) {
+				/*
+				 * If we skipped non-options, set optind
+				 * to the first of them.
+				 */
+				optind = nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+		if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+		    place[1] == '\0') {
+#else
+		    (place[1] == '\0' && strchr(options, '-') == NULL)) {
+#endif
+			place = EMSG;		/* found non-option */
+			if (flags & FLAG_ALLARGS) {
+				/*
+				 * GNU extension:
+				 * return non-option as argument to option 1
+				 */
+				optarg = nargv[optind++];
+				return (INORDER);
+			}
+			if (!(flags & FLAG_PERMUTE)) {
+				/*
+				 * If no permutation wanted, stop parsing
+				 * at first non-option.
+				 */
+				return (-1);
+			}
+			/* do permutation */
+			if (nonopt_start == -1)
+				nonopt_start = optind;
+			else if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				nonopt_start = optind -
+				    (nonopt_end - nonopt_start);
+				nonopt_end = -1;
+			}
+			optind++;
+			/* process next argument */
+			goto start;
+		}
+		if (nonopt_start != -1 && nonopt_end == -1)
+			nonopt_end = optind;
+
+		/*
+		 * If we have "-" do nothing, if "--" we are done.
+		 */
+		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+			optind++;
+			place = EMSG;
+			/*
+			 * We found an option (--), so if we skipped
+			 * non-options, we have to permute.
+			 */
+			if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+	}
+
+	/*
+	 * Check long options if:
+	 *  1) we were passed some
+	 *  2) the arg is not just "-"
+	 *  3) either the arg starts with -- we are getopt_long_only()
+	 */
+	if (long_options != NULL && place != nargv[optind] &&
+	    (*place == '-' || (flags & FLAG_LONGONLY))) {
+		short_too = 0;
+#ifdef GNU_COMPATIBLE
+		dash_prefix = D_PREFIX;
+#endif
+		if (*place == '-') {
+			place++;		/* --foo long option */
+#ifdef GNU_COMPATIBLE
+			dash_prefix = DD_PREFIX;
+#endif
+		} else if (*place != ':' && strchr(options, *place) != NULL)
+			short_too = 1;		/* could be short option too */
+
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, short_too, flags);
+		if (optchar != -1) {
+			place = EMSG;
+			return (optchar);
+		}
+	}
+
+	if ((optchar = (int)*place++) == (int)':' ||
+	    (optchar == (int)'-' && *place != '\0') ||
+	    (oli = strchr(options, optchar)) == NULL) {
+		/*
+		 * If the user specified "-" and  '-' isn't listed in
+		 * options, return -1 (non-option) as per POSIX.
+		 * Otherwise, it is an unknown option character (or ':').
+		 */
+		if (optchar == (int)'-' && *place == '\0')
+			return (-1);
+		if (!*place)
+			++optind;
+#ifdef GNU_COMPATIBLE
+		if (PRINT_ERROR) {
+			fprintf(stderr, posixly_correct ? illoptchar : gnuoptchar,
+					optchar);
+		}
+#else
+		if (PRINT_ERROR) {
+			fprintf(stderr, illoptchar, optchar);
+		}
+#endif
+		optopt = optchar;
+		return (BADCH);
+	}
+	if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+		/* -W long-option */
+		if (*place)			/* no space */
+			/* NOTHING */;
+		else if (++optind >= nargc) {	/* no arg */
+			place = EMSG;
+			if (PRINT_ERROR) {
+				fprintf(stderr, recargchar, optchar);
+			}
+			optopt = optchar;
+			return (BADARG);
+		} else				/* white space */
+			place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+		dash_prefix = W_PREFIX;
+#endif
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, 0, flags);
+		place = EMSG;
+		return (optchar);
+	}
+	if (*++oli != ':') {			/* doesn't take argument */
+		if (!*place)
+			++optind;
+	} else {				/* takes (optional) argument */
+		optarg = NULL;
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (oli[1] != ':') {	/* arg not optional */
+			if (++optind >= nargc) {	/* no arg */
+				place = EMSG;
+				if (PRINT_ERROR) {
+					fprintf(stderr, recargchar, optchar);
+				}
+				optopt = optchar;
+				return (BADARG);
+			} else
+				optarg = nargv[optind];
+		}
+		place = EMSG;
+		++optind;
+	}
+	/* dump back option letter */
+	return (optchar);
+}
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+	/*
+	 * We don't pass FLAG_PERMUTE to getopt_internal() since
+	 * the BSD getopt(3) (unlike GNU) has never done this.
+	 *
+	 * Furthermore, since many privileged programs call getopt()
+	 * before dropping privileges it makes sense to keep things
+	 * as simple (and bug-free) as possible.
+	 */
+	return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+
+/*
+ * getopt_long --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE|FLAG_LONGONLY));
+}
-- 
GitLab