diff options
50 files changed, 8943 insertions, 41 deletions
diff --git a/system/cmake/APKBUILD b/system/cmake/APKBUILD index 9ea4e8c6f..672ed2e3d 100644 --- a/system/cmake/APKBUILD +++ b/system/cmake/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Valery Kartel <valery.kartel@gmail.com> # Maintainer: A. Wilcox <awilfox@adelielinux.org> pkgname=cmake -pkgver=3.12.1 +pkgver=3.12.3 pkgrel=0 pkgdesc="Cross-platform build system" url="https://cmake.org" @@ -55,4 +55,4 @@ package() { make DESTDIR="$pkgdir" install } -sha512sums="7a0a769ef060785a8dc8c6aa272435a90a07cc8079f6c83c916da0b79d8bcdefca0d7be21f55f408ab4dfa6a57caa9ff8dec4be993145f4e3337ff392481b692 cmake-3.12.1.tar.gz" +sha512sums="2b5b006bd0fa09431eb525a7f419c64b811afbe1cc81d34e6167e04112966d9f48f28652b21b5a04c889de6227315db57dd2099a17ea6329e27f3e97eac9051c cmake-3.12.3.tar.gz" diff --git a/system/debianutils/APKBUILD b/system/debianutils/APKBUILD index fbcdfe041..8e79a7eef 100644 --- a/system/debianutils/APKBUILD +++ b/system/debianutils/APKBUILD @@ -32,7 +32,7 @@ package() { } which() { - provides_priority="10" + provider_priority=10 mkdir -p "$subpkgdir"/usr/bin mv "$pkgdir"/usr/bin/which "$subpkgdir"/usr/bin/ # This will emit a warning about docs on abuild, but this is expected. diff --git a/system/musl/APKBUILD b/system/musl/APKBUILD index a3a0eb81c..08f4342dd 100644 --- a/system/musl/APKBUILD +++ b/system/musl/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: A. Wilcox <awilfox@adelielinux.org> pkgname=musl pkgver=1.1.20 -pkgrel=3 +pkgrel=4 pkgdesc="System library (libc) implementation" url="http://www.musl-libc.org/" arch="all" @@ -11,12 +11,17 @@ license="MIT" depends="" depends_dev="!uclibc-dev" makedepends="$depends_dev" -triggers="$pkgname-utils.trigger=/etc/ld.so.conf.d" subpackages="$pkgname-dev $pkgname-dbg" case "$BOOTSTRAP" in -nocc) pkgname="musl-dev"; subpackages=""; options="$options !dbg" builddir="$srcdir"/musl-$pkgver;; +nocc) pkgname="musl-dev" + subpackages="" + options="$options !dbg" + builddir="$srcdir"/musl-$pkgver + ;; nolibc) ;; -*) subpackages="$subpackages $pkgname-utils";; +*) subpackages="$subpackages $pkgname-utils" + triggers="$pkgname-utils.trigger=/etc/ld.so.conf.d" + ;; esac source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz amalgamation.patch diff --git a/user/dmenu/APKBUILD b/user/dmenu/APKBUILD new file mode 100644 index 000000000..39a27bc5a --- /dev/null +++ b/user/dmenu/APKBUILD @@ -0,0 +1,36 @@ +# Contributor: Eivind Uggedal <eivind@uggedal.com> +# Contributor: Sören Tempel <soeren+alpine@soeren-tempel.net> +# Maintainer: Dan Theisen <djt@hxx.in> +pkgname=dmenu +pkgver=4.8 +pkgrel=0 +pkgdesc="Dynamic menu for X" +url="https://tools.suckless.org/dmenu/" +arch="all" +license="MIT OR X11" +depends="" +makedepends="libx11-dev libxinerama-dev libxft-dev" +options="!check" # This package has no testsuite +subpackages="$pkgname-doc" +source="https://dl.suckless.org/tools/$pkgname-$pkgver.tar.gz" + +prepare() { + default_prepare + sed -i -e '/CFLAGS/{s/-Os//;s/=/+=/}' \ + -e '/LDFLAGS/{s/-s//;s/=/+=/}' \ + "$builddir"/config.mk +} + +build() { + make X11INC=/usr/include/X11 \ + X11LIB=/usr/lib/X11 \ + FREETYPEINC=/usr/include/freetype2 \ + -C "$builddir" +} + +package() { + make DESTDIR=$pkgdir PREFIX=/usr \ + -C "$builddir" install +} + +sha512sums="fa2700018cfb912a21f867ef3ca771a58a25c2cb8e1fb37acef046bb15d8d8b92dcc5bfce486befae0f143495d0283910988e181a9eb143be3bb1b5be9738d77 dmenu-4.8.tar.gz" diff --git a/user/fuse3/APKBUILD b/user/fuse3/APKBUILD index dd03d34e2..dc049071d 100644 --- a/user/fuse3/APKBUILD +++ b/user/fuse3/APKBUILD @@ -12,7 +12,7 @@ license="GPL-2.0-only AND LGPL-2.1-only AND BSD-2-Clause" depends="fuse-common" makedepends="linux-headers meson eudev-dev python3 py3-six py3-pluggy py3-attrs py3-py" -#checkdepends="py3-pytest debianutils-which" +#checkdepends="py3-pytest cmd:which" subpackages="$pkgname-dev $pkgname-doc $_pkgname-common:common:noarch $_pkgname-openrc:openrc:noarch" source="https://github.com/libfuse/libfuse/releases/download/fuse-$pkgver/fuse-$pkgver.tar.xz diff --git a/user/keepassxc/APKBUILD b/user/keepassxc/APKBUILD new file mode 100644 index 000000000..14d9235fc --- /dev/null +++ b/user/keepassxc/APKBUILD @@ -0,0 +1,40 @@ +# Contributor: Max Rees <maxcrees@me.com> +# Maintainer: Max Rees <maxcrees@me.com> +pkgname=keepassxc +pkgver=2.3.4 +pkgrel=0 +pkgdesc="A community revival of the KeePassX password manager" +url="https://keepassxc.org" +arch="all" +license="(GPL-2.0-only OR GPL-3.0-only) AND MIT AND BSD-4-Clause AND ISC AND (LGPL-2.1-only OR GPL-3.0-only) AND (LGPL-2.1-only OR LGPL-3.0-only) AND CC0-1.0 AND Public-Domain AND LGPL-2.1+ AND LGPL-3.0+" +depends="hicolor-icon-theme" +makedepends="cmake xz qt5-qtbase-dev qt5-qttools-dev libgcrypt-dev + zlib-dev libxi-dev libxtst-dev qt5-qtx11extras-dev argon2-dev" +subpackages="$pkgname-doc" +source="https://github.com/keepassxreboot/$pkgname/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz" + +prepare() { + cd "$builddir" + mkdir build + default_prepare +} + +build() { + cd "$builddir/build" + cmake -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=/usr/lib \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + make +} + +check() { + cd "$builddir/build" + make test +} + +package() { + cd "$builddir/build" + make DESTDIR="$pkgdir" install +} + +sha512sums="edca22ef9d7c553d21d8ea6115a5635265176acc56fdf055f1961a3e65046de49ed5b67eb68ecf4f925226fb5bca140d5d473a5082301168f6a8bb7979f562a8 keepassxc-2.3.4-src.tar.xz" diff --git a/user/libsoup/APKBUILD b/user/libsoup/APKBUILD index 3abfaec66..bc3c76754 100644 --- a/user/libsoup/APKBUILD +++ b/user/libsoup/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> # Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> pkgname=libsoup -pkgver=2.64.0 +pkgver=2.64.1 pkgrel=0 pkgdesc="GObject-based HTTP library" url="https://wiki.gnome.org/Projects/libsoup" @@ -12,7 +12,6 @@ makedepends="glib-dev libxml2-dev sqlite-dev libpsl-dev intltool vala-dev gobject-introspection-dev glib-networking" subpackages="$pkgname-dev $pkgname-doc" source="https://download.gnome.org/sources/libsoup/2.64/libsoup-$pkgver.tar.xz" -sha512sums="4ff3d16898bad5481d6abc4a7d2cdccc559e3d2a675128ccb61fba09a39c5c1736aeb7bda77dfd73f97a8660d11e25e88901fb6b957ab47b1e9e8a0fd6740424 libsoup-2.64.0.tar.xz" build() { cd "$builddir" @@ -36,3 +35,4 @@ package() { make DESTDIR="$pkgdir" install } +sha512sums="13d16457a443294020621df34205c570d25a6ff048ab68633cc504d70a8a1281a38dddb54110fd35a059bd69aebc3fd49b5ab0fc42abf4f4a19746a25050119d libsoup-2.64.1.tar.xz" diff --git a/user/llvm6/APKBUILD b/user/llvm6/APKBUILD index f3bc9acc7..5f7b04fad 100644 --- a/user/llvm6/APKBUILD +++ b/user/llvm6/APKBUILD @@ -12,7 +12,7 @@ arch="all" options="!checkroot !dbg" url="https://llvm.org/" license="NCSA" -depends_dev="$pkgname=$pkgver-r$pkgrel" +depends_dev="$pkgname=$pkgver-r$pkgrel libexecinfo-dev libxml2-dev" makedepends="binutils-dev chrpath cmake file libexecinfo-dev libffi-dev libxml2-dev python3 zlib-dev" subpackages="$pkgname-static $pkgname-libs $pkgname-dev @@ -24,6 +24,9 @@ source="http://llvm.org/releases/$pkgver/llvm-$pkgver.src.tar.xz disable-dlclose-test.patch musl-ppc64-elfv2.patch secure-plt.patch + more-secure-plt.patch + even-more-secure-plt.patch + ppc32-calling-convention.patch " builddir="$srcdir/$_pkgname-$pkgver.src" @@ -245,5 +248,8 @@ f84cd65d7042e89826ba6e8d48c4c302bf4980da369d7f19a55f217e51c00ca8ed178d453df3a3ce 6d1a716e5aa24e6b9a3acf4cc11e2504b1b01abf574074e9e5617b991de87d5e4e687eb18e85e73d5e632568afe2fc357771c4c96f9e136502071991496fb78c cmake-fix-libLLVM-name.patch 49c47f125014b60d0ea7870f981a2c1708ad705793f89287ed846ee881a837a4dc0170bf467e03f2ef56177473128945287749ac80dc2d13cfabcf8b929ba58a disable-FileSystemTest.CreateDir-perms-assert.patch caeec8e4dbd92f5f74940780b69075f3879a267a8623822cbdc193fd14706eb089071e3a5a20d60cc2eca59e4c5b2a61d29827a2f3362ee7c5f74f11d9ace200 disable-dlclose-test.patch -bde743960003a2a39868af9f665d86fadb0a7b1e7eb51c16ebbd74ce4c5220bbc400b1d5211c02fc2643863f49ee961e9a18dffa0eb813a0e1723613396512ab musl-ppc64-elfv2.patch -35d289641fa4d200b5a3f62f1d51da600a734641356b0dc6c54a3080dd89aec3b031e36af8b53be49c35346c1cbcce00268de7ec9b4f552bfd7bf84d3504d1c4 secure-plt.patch" +e5ddbc4b6c4928e79846dc3c022eb7928aaa8fed40515c78f5f03b8ab8264f34f1eb8aa8bfc0f436450932f4917e54ad261603032092ea271d9590f11a37cf1e musl-ppc64-elfv2.patch +35d289641fa4d200b5a3f62f1d51da600a734641356b0dc6c54a3080dd89aec3b031e36af8b53be49c35346c1cbcce00268de7ec9b4f552bfd7bf84d3504d1c4 secure-plt.patch +3d4a0a478bf800ea262c577451e22a1dbd5a4258226e49c66a697559263c8aa4fc0fff642a3c80ac3dfbb3efd6d9c0dbeb41dae1250fc7946de821cfef1ce1f0 more-secure-plt.patch +deb71762721ebc73bfdf23143b582f40c70eddcef3e337ed14499e8e336bee2906292d38d64fe98fa633430c1bcb66cf6a2e067258c8fbe6e931f99f6d10a6f7 even-more-secure-plt.patch +c3f596a1578a07ce0ee40c4e2576fe05ca6ca0c1b4f94b1f74c55cb09603afe7c846db9294fe28d83ca48633086bad422218e6d06e0d92173143fb298e06fb38 ppc32-calling-convention.patch" diff --git a/user/llvm6/even-more-secure-plt.patch b/user/llvm6/even-more-secure-plt.patch new file mode 100644 index 000000000..112e111b8 --- /dev/null +++ b/user/llvm6/even-more-secure-plt.patch @@ -0,0 +1,101 @@ +Index: lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +=================================================================== +--- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp ++++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +@@ -442,13 +442,22 @@ + // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must + // come at the _end_ of the expression. + const MCOperand &Op = MI->getOperand(OpNo); +- const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*Op.getExpr()); +- O << refExp.getSymbol().getName(); ++ const MCSymbolRefExpr *RefExp = nullptr; ++ const MCConstantExpr *ConstExp = nullptr; ++ if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Op.getExpr())) { ++ RefExp = cast<MCSymbolRefExpr>(BinExpr->getLHS()); ++ ConstExp = cast<MCConstantExpr>(BinExpr->getRHS()); ++ } else ++ RefExp = cast<MCSymbolRefExpr>(Op.getExpr()); ++ ++ O << RefExp->getSymbol().getName(); + O << '('; + printOperand(MI, OpNo+1, O); + O << ')'; +- if (refExp.getKind() != MCSymbolRefExpr::VK_None) +- O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind()); ++ if (RefExp->getKind() != MCSymbolRefExpr::VK_None) ++ O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind()); ++ if (ConstExp != nullptr) ++ O << '+' << ConstExp->getValue(); + } + + /// showRegistersWithPercentPrefix - Check if this register name should be +Index: lib/Target/PowerPC/PPCAsmPrinter.cpp +=================================================================== +--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp ++++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp +@@ -487,8 +487,14 @@ + if (!Subtarget->isPPC64() && !Subtarget->isDarwin() && + isPositionIndependent()) + Kind = MCSymbolRefExpr::VK_PLT; +- const MCSymbolRefExpr *TlsRef = ++ const MCExpr *TlsRef = + MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext); ++ ++ // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI. ++ if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt()) ++ TlsRef = MCBinaryExpr::createAdd(TlsRef, ++ MCConstantExpr::create(32768, OutContext), ++ OutContext); + const MachineOperand &MO = MI->getOperand(2); + const GlobalValue *GValue = MO.getGlobal(); + MCSymbol *MOSymbol = getSymbol(GValue); +Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp +=================================================================== +--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp ++++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +@@ -4054,7 +4054,20 @@ + if (trySETCC(N)) + return; + break; +- ++ // These nodes will be transformed into GETtlsADDR32 node, which ++ // later becomes BL_TLS __tls_get_addr(sym at tlsgd)@PLT ++ case PPCISD::ADDI_TLSLD_L_ADDR: ++ case PPCISD::ADDI_TLSGD_L_ADDR: { ++ const Module *Mod = MF->getFunction().getParent(); ++ if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || ++ !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || ++ Mod->getPICLevel() == PICLevel::SmallPIC) ++ break; ++ // Attach global base pointer on GETtlsADDR32 node in order to ++ // generate secure plt code for TLS symbols. ++ getGlobalBaseReg(); ++ } ++ break; + case PPCISD::CALL: { + const Module *M = MF->getFunction().getParent(); + +Index: test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll +=================================================================== +--- a/test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll ++++ b/test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll +@@ -0,0 +1,18 @@ ++; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=SECURE-PLT-TLS %s ++ ++@a = thread_local local_unnamed_addr global i32 6, align 4 ++define i32 @main() local_unnamed_addr #0 { ++entry: ++ %0 = load i32, i32* @a, align 4 ++ ret i32 %0 ++} ++ ++ ++!llvm.module.flags = !{!0} ++!0 = !{i32 7, !"PIC Level", i32 2} ++ ++; SECURE-PLT-TLS: mflr 30 ++; SECURE-PLT-TLS-NEXT: addis 30, 30, .LTOC-.L0$pb@ha ++; SECURE-PLT-TLS-NEXT: addi 30, 30, .LTOC-.L0$pb@l ++; SECURE-PLT-TLS-NEXT: bl .L{{.*}} ++; SECURE-PLT-TLS: bl __tls_get_addr(a@tlsgd)@PLT+32768 +\ No newline at end of file diff --git a/user/llvm6/more-secure-plt.patch b/user/llvm6/more-secure-plt.patch new file mode 100644 index 000000000..1cc08a9a8 --- /dev/null +++ b/user/llvm6/more-secure-plt.patch @@ -0,0 +1,38 @@ +diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp +index c0cbfd779cb..5d7a021c3e2 100644 +--- a/lib/Target/PowerPC/PPCSubtarget.cpp ++++ b/lib/Target/PowerPC/PPCSubtarget.cpp +@@ -106,6 +106,7 @@ + HasFloat128 = false; + IsISA3_0 = false; + UseLongCalls = false; ++ SecurePlt = false; + + HasPOPCNTD = POPCNTD_Unavailable; + } +@@ -136,6 +137,10 @@ + if (isDarwin()) + HasLazyResolverStubs = true; + ++ // Set up musl-specific properties. ++ if (TargetTriple.getEnvironment() == Triple::Musl) ++ SecurePlt = true; ++ + // QPX requires a 32-byte aligned stack. Note that we need to do this if + // we're compiling for a BG/Q system regardless of whether or not QPX + // is enabled because external functions will assume this alignment. +diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp +index c583fba8cab..6a9eedf89c5 100644 +--- a/lib/Target/PowerPC/PPCTargetMachine.cpp ++++ b/lib/Target/PowerPC/PPCTargetMachine.cpp +@@ -222,6 +222,10 @@ static Reloc::Model getEffectiveRelocModel(const Triple &TT, + if (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le) + return Reloc::PIC_; + ++ // musl needs SecurePlt, which depends on PIC. ++ if (TT.getEnvironment() == Triple::Musl) ++ return Reloc::PIC_; ++ + // 32-bit is static by default. + return Reloc::Static; + } diff --git a/user/llvm6/musl-ppc64-elfv2.patch b/user/llvm6/musl-ppc64-elfv2.patch index 6fa65526b..016be5dad 100644 --- a/user/llvm6/musl-ppc64-elfv2.patch +++ b/user/llvm6/musl-ppc64-elfv2.patch @@ -1,13 +1,43 @@ ---- llvm-6.0.1.src/lib/Target/PowerPC/PPCTargetMachine.cpp.orig 2018-09-13 03:51:11.900000000 +0000 -+++ llvm-6.0.1.src/lib/Target/PowerPC/PPCTargetMachine.cpp 2018-09-13 03:56:10.740000000 +0000 -@@ -191,6 +191,10 @@ - if (TT.isMacOSX()) - return PPCTargetMachine::PPC_ABI_UNKNOWN; - -+ // musl uses ELFv2 ABI on both endians. -+ if (TT.getEnvironment() == Triple::Musl) -+ return PPCTargetMachine::PPC_ABI_ELFv2; -+ - switch (TT.getArch()) { +From 750d323a6060ad92c3d247f85d6555041f55b4a5 Mon Sep 17 00:00:00 2001 +From: "A. Wilcox" <AWilcox@Wilcox-Tech.com> +Date: Thu, 4 Oct 2018 15:26:59 -0500 +Subject: [PATCH] Add support for powerpc64-*-linux-musl targets + +This patch ensures that 64-bit PowerPC musl targets use ELFv2 ABI on both +endians. It additionally adds a test that big endian PPC64 uses ELFv2 on +musl. +--- + lib/Target/PowerPC/PPCTargetMachine.cpp | 4 ++++ + test/CodeGen/PowerPC/ppc64-elf-abi.ll | 1 + + 2 files changed, 5 insertions(+) + +diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp +index 34410393ef6..c583fba8cab 100644 +--- a/lib/Target/PowerPC/PPCTargetMachine.cpp ++++ b/lib/Target/PowerPC/PPCTargetMachine.cpp +@@ -199,6 +199,10 @@ static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, case Triple::ppc64le: return PPCTargetMachine::PPC_ABI_ELFv2; + case Triple::ppc64: ++ // musl uses ELFv2 ABI on both endians. ++ if (TT.getEnvironment() == Triple::Musl) ++ return PPCTargetMachine::PPC_ABI_ELFv2; ++ + return PPCTargetMachine::PPC_ABI_ELFv1; + default: + return PPCTargetMachine::PPC_ABI_UNKNOWN; +diff --git a/test/CodeGen/PowerPC/ppc64-elf-abi.ll b/test/CodeGen/PowerPC/ppc64-elf-abi.ll +index 1e17930304b..aa594b37b47 100644 +--- a/test/CodeGen/PowerPC/ppc64-elf-abi.ll ++++ b/test/CodeGen/PowerPC/ppc64-elf-abi.ll +@@ -1,6 +1,7 @@ + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu < %s | FileCheck %s -check-prefix=CHECK-ELFv1 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -target-abi elfv1 < %s | FileCheck %s -check-prefix=CHECK-ELFv1 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -target-abi elfv2 < %s | FileCheck %s -check-prefix=CHECK-ELFv2 ++; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-musl < %s | FileCheck %s -check-prefix=CHECK-ELFv2 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s -check-prefix=CHECK-ELFv2 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -target-abi elfv1 < %s | FileCheck %s -check-prefix=CHECK-ELFv1 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -target-abi elfv2 < %s | FileCheck %s -check-prefix=CHECK-ELFv2 +-- +2.18.0 + diff --git a/user/llvm6/ppc32-calling-convention.patch b/user/llvm6/ppc32-calling-convention.patch new file mode 100644 index 000000000..2e6d66427 --- /dev/null +++ b/user/llvm6/ppc32-calling-convention.patch @@ -0,0 +1,69 @@ +Index: trunk/lib/Target/PowerPC/PPCISelLowering.cpp +=================================================================== +--- trunk/lib/Target/PowerPC/PPCISelLowering.cpp ++++ trunk/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -3511,9 +3511,14 @@ + // Argument stored in memory. + assert(VA.isMemLoc()); + ++ // Get the extended size of the argument type in stack + unsigned ArgSize = VA.getLocVT().getStoreSize(); +- int FI = MFI.CreateFixedObject(ArgSize, VA.getLocMemOffset(), +- isImmutable); ++ // Get the actual size of the argument type ++ unsigned ObjSize = VA.getValVT().getStoreSize(); ++ unsigned ArgOffset = VA.getLocMemOffset(); ++ // Stack objects in PPC32 are right justified. ++ ArgOffset += ArgSize - ObjSize; ++ int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, isImmutable); + + // Create load nodes to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, PtrVT); +@@ -5468,10 +5473,15 @@ + Arg = PtrOff; + } + +- if (VA.isRegLoc()) { +- if (Arg.getValueType() == MVT::i1) +- Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Arg); ++ // When useCRBits() is true, there can be i1 arguments. ++ // It is because getRegisterType(MVT::i1) => MVT::i1, ++ // and for other integer types getRegisterType() => MVT::i32. ++ // Extend i1 and ensure callee will get i32. ++ if (Arg.getValueType() == MVT::i1) ++ Arg = DAG.getNode(Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, ++ dl, MVT::i32, Arg); + ++ if (VA.isRegLoc()) { + seenFloatArg |= VA.getLocVT().isFloatingPoint(); + // Put argument in a physical register. + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); +Index: trunk/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll +=================================================================== +--- trunk/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll ++++ trunk/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll +@@ -0,0 +1,24 @@ ++; RUN: llc -verify-machineinstrs < %s -mcpu=ppc32 -mattr=+crbits | FileCheck %s ++target triple = "powerpc-unknown-linux-gnu" ++ ++define void @check_callee( ++ i32, i32, i32, i32, ++ i32, i32, i32, i32, ++ i1 zeroext %s1 ++) { ++ call void @check_caller( ++ i32 9, i32 9, i32 9, i32 9, ++ i32 9, i32 9, i32 9, i32 9, ++ i1 zeroext %s1) ++ ret void ++} ++ ++; CHECK-LABEL: @check_callee ++; CHECK: lbz {{[0-9]+}}, 27(1) ++; CHECK: stw {{[0-9]+}}, 8(1) ++ ++declare void @check_caller( ++ i32, i32, i32, i32, ++ i32, i32, i32, i32, ++ i1 zeroext ++) diff --git a/user/lsof/APKBUILD b/user/lsof/APKBUILD index 32fff3e16..a7e0c4768 100644 --- a/user/lsof/APKBUILD +++ b/user/lsof/APKBUILD @@ -8,7 +8,7 @@ url="https://people.freebsd.org/~abe" arch="all" license="zlib-acknowledgement" subpackages="$pkgname-doc" -makedepends="linux-headers debianutils-which utmps-dev" +makedepends="linux-headers cmd:which utmps-dev" source="ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/${pkgname}_${pkgver}.tar.gz utmps.patch test-enable-suite.patch diff --git a/user/lua-expat/APKBUILD b/user/lua-expat/APKBUILD new file mode 100644 index 000000000..9c8a6713a --- /dev/null +++ b/user/lua-expat/APKBUILD @@ -0,0 +1,32 @@ +# Contributor: Mika Havela <mika.havela@gmail.com> +# Contribtor: Natanael Copa <ncopa@alpinelinux.org> +# Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> +pkgname=lua-expat +_name=expat +pkgver=1.3.0 +pkgrel=0 +pkgdesc="SAX XML parser based on the Expat library" +url="https://matthewwild.co.uk/projects/luaexpat/" +arch="all" +license="MIT" +depends="lua5.3" +makedepends="lua5.3-dev expat-dev" +source="http://matthewwild.co.uk/projects/luaexpat/luaexpat-$pkgver.tar.gz" +builddir="$srcdir/luaexpat-$pkgver" + +build() { + cd "$builddir" + make LUA_V=5.3 +} + +check() { + cd "$builddir" + LUA_CPATH="./src/?.so" lua tests/test.lua +} + +package() { + cd "$builddir" + make LUA_V=5.3 DESTDIR="$pkgdir" install +} + +sha512sums="91884653310e2dc89ade6d1653875ac8607640a21853d3ccb1fd0f833812e41981fad5c40101732ec249104d2c50c9a332208d1e44423b8428065a223c60b4ae luaexpat-1.3.0.tar.gz" diff --git a/user/lua-filesystem/APKBUILD b/user/lua-filesystem/APKBUILD new file mode 100644 index 000000000..e809a654f --- /dev/null +++ b/user/lua-filesystem/APKBUILD @@ -0,0 +1,36 @@ +# Contributor: Natanael Copa <ncopa@alpinelinux.org> +# Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> +pkgname=lua-filesystem +_pkgname=luafilesystem +pkgver=1.7.0.2 +_pkgver=${pkgver//./_} +_rockver=${pkgver%.*}-${pkgver##*.} +pkgrel=0 +pkgdesc="Filesystem functions for Lua" +url="http://keplerproject.github.io/luafilesystem/" +arch="all" +license="MIT" +depends="lua5.3" +makedepends="lua5.3-dev" +source="$_pkgname-$pkgver.tar.gz::https://github.com/keplerproject/$_pkgname/archive/v$_pkgver.tar.gz" +builddir="$srcdir/$_pkgname-$_pkgver" + +build() { + cd "$builddir" + make CFLAGS="$CFLAGS $(pkg-config lua --cflags) -fPIC" +} + +check() { + cd "$builddir" + LUA_CPATH=./src/?.so lua tests/test.lua +} + +package() { + local rockdir="$pkgdir"/usr/lib/luarocks/rocks-5.3/$_rockname/$_rockver + cd "$builddir" + make LUA_LIBDIR="$pkgdir"/$(pkg-config --variable=INSTALL_CMOD lua5.3) install + mkdir -p "$rockdir" + echo 'rock_manifest = {}' > "$rockdir"/rock_manifest +} + +sha512sums="a1d4d077776e57cd878dbcd21656da141ea3686c587b5420a2b039aeaf086b7e7d05d531ee1cc2bbd7d06660d1315b09593e52143f6711f033ce8eecdc550511 luafilesystem-1.7.0.2.tar.gz" diff --git a/user/lua-sec/APKBUILD b/user/lua-sec/APKBUILD new file mode 100644 index 000000000..6732105ef --- /dev/null +++ b/user/lua-sec/APKBUILD @@ -0,0 +1,32 @@ +# Contributor: Natanael Copa <ncopa@alpinelinux.org> +# Maintainer: Natanael Copa <ncopa@alpinelinux.org> +pkgname=lua-sec +pkgver=0.7 +pkgrel=0 +pkgdesc="TLS/SSL Support for Lua" +url="https://github.com/brunoos/luasec/wiki" +arch="all" +options="!check" # no tests +license="MIT" +depends="lua5.3 lua-socket" +makedepends="lua5.3-dev openssl-dev" +subpackages="$pkgname-doc" +source="luasec-$pkgver.tar.gz::https://github.com/brunoos/luasec/archive/luasec-$pkgver.tar.gz" +builddir="$srcdir/luasec-luasec-$pkgver" + +build() { + cd "$builddir" + make linux INC_PATH="$(pkg-config --cflags lua)" LD="${CC:-gcc}" +} + +package() { + cd "$builddir" + make \ + LUAPATH="$pkgdir"/usr/share/lua/5.3 \ + LUACPATH="$pkgdir"/usr/lib/lua/5.3 \ + install + mkdir -p "$pkgdir"/usr/share/doc/$pkgname + cp -r samples "$pkgdir"/usr/share/doc/$pkgname/ +} + +sha512sums="6adf5241aa5a0d92c9dd7fc7f7e426969475548f47979ccc28187471b3bad4132c215de6da1f471d21b05c6558d36309264512c9c4ac70a53d6f6e204cac1358 luasec-0.7.tar.gz" diff --git a/user/lua-socket/0001-Create-socket-on-first-sendto-if-family-agnostic-udp.patch b/user/lua-socket/0001-Create-socket-on-first-sendto-if-family-agnostic-udp.patch new file mode 100644 index 000000000..61bae6fbf --- /dev/null +++ b/user/lua-socket/0001-Create-socket-on-first-sendto-if-family-agnostic-udp.patch @@ -0,0 +1,49 @@ +From 3041a808c3797e3c87272d71666e7b2f7c7a9f46 Mon Sep 17 00:00:00 2001 +From: Natanael Copa <ncopa@alpinelinux.org> +Date: Wed, 25 Jan 2017 12:43:29 +0100 +Subject: [PATCH] Create socket on first sendto if family agnostic udp() was + used + +Create socket and set family on first sendto() if udp() was created +without address family. + +Signed-off-by: Natanael Copa <ncopa@alpinelinux.org> +--- + src/udp.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/src/udp.c b/src/udp.c +index ec97252..605c195 100644 +--- a/src/udp.c ++++ b/src/udp.c +@@ -189,6 +189,27 @@ static int meth_sendto(lua_State *L) { + lua_pushstring(L, gai_strerror(err)); + return 2; + } ++ ++ /* create socket if on first sendto if AF_UNSPEC was set */ ++ if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) { ++ struct addrinfo *ap; ++ const char *errstr = NULL; ++ for (ap = ai; ap != NULL; ap = ap->ai_next) { ++ errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); ++ if (errstr == NULL) { ++ socket_setnonblocking(&udp->sock); ++ udp->family = ap->ai_family; ++ break; ++ } ++ } ++ if (errstr != NULL) { ++ lua_pushnil(L); ++ lua_pushstring(L, errstr); ++ freeaddrinfo(ai); ++ return 2; ++ } ++ } ++ + timeout_markstart(tm); + err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, + (socklen_t) ai->ai_addrlen, tm); +-- +2.11.0 + diff --git a/user/lua-socket/APKBUILD b/user/lua-socket/APKBUILD new file mode 100644 index 000000000..16bfbcf40 --- /dev/null +++ b/user/lua-socket/APKBUILD @@ -0,0 +1,41 @@ +# Contributor: Mika Havela <mika.havela@gmail.com> +# Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> +pkgname=lua-socket +_name=luasocket +pkgver=3.0_rc1_git20160306 +pkgrel=0 +_ver=${pkgver%_git*} +_ver=${_ver/_rc/-rc} +pkgdesc="Networking library for Lua" +url="http://luaforge.net/projects/luasocket/" +arch="all" +license="MIT" +depends="lua5.3" +makedepends="lua5.3-dev" +source="luasocket-$_ver.tar.gz::https://github.com/diegonehab/luasocket/archive/v$_ver.tar.gz + git.patch + lua-cflags.patch + 0001-Create-socket-on-first-sendto-if-family-agnostic-udp.patch" +builddir="$srcdir/$_name-$_ver" + +build() { + cd "$builddir" + make LUAV="" +} + +check() { + cd "$builddir" + mkdir -p src/socket && cp src/socket-$_ver.so src/socket/core.so + mkdir -p src/mime && cp src/mime-1.0.3.so src/mime/core.so + LUA_CPATH=./src/?.so LUA_PATH="./src/?.lua;;" lua test/hello.lua +} + +package() { + cd "$builddir" + make prefix=/usr DESTDIR="$pkgdir" LUAV="5.3" install-unix +} + +sha512sums="f6efce259aaacaa11472911471f8a13b118fe009b8953a82c6aa18b9ec829cd1293180904e56935cb130d36d267e3f27c91db2d78e03f7488f3e100571ed0540 luasocket-3.0-rc1.tar.gz +45c80e488fedc879f0217bc8a654d80da003039f5d1ff21b0dea0eb769151787dbe793e44a3dfd72cb07ff2697eceaf4fc7b55b4634cd170fa71281f19f025a5 git.patch +61c15238a2f116b7239fdbdb8f617c82dbbecd0117c6e8389b12015bf07f3978299a8e8995e93a45a23530c747662b08d161073cdb6a8e07c4f449e45856e8cb lua-cflags.patch +c45a12e17771a1b3b71154b5415421f524cd10b7969b4649a5f37b652cdc826721e117edb8fe64758d3520e59946e2f755b814f72cbb39ff42bf59bbcf9a64e9 0001-Create-socket-on-first-sendto-if-family-agnostic-udp.patch" diff --git a/user/lua-socket/git.patch b/user/lua-socket/git.patch new file mode 100644 index 000000000..d665fc232 --- /dev/null +++ b/user/lua-socket/git.patch @@ -0,0 +1,6609 @@ +diff --git a/doc/http.html b/doc/http.html +index cd41c0d..3b7a8b1 100644 +--- a/doc/http.html ++++ b/doc/http.html +@@ -112,12 +112,15 @@ the HTTP module: + </p> + + <ul> +-<li> <tt>PORT</tt>: default port used for connections; +-<li> <tt>PROXY</tt>: default proxy used for connections; ++<li> <tt>PROXY</tt>: default proxy used for connections; + <li> <tt>TIMEOUT</tt>: sets the timeout for all I/O operations; + <li> <tt>USERAGENT</tt>: default user agent reported to server. + </ul> + ++<p class=note id="post"> ++Note: These constants are global. Changing them will also ++change the behavior other code that might be using LuaSocket. ++</p> + + <!-- http.request ++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +diff --git a/doc/mime.html b/doc/mime.html +index ae136fd..8cb3507 100644 +--- a/doc/mime.html ++++ b/doc/mime.html +@@ -72,34 +72,6 @@ local mime = require("mime") + + <h3 id=high>High-level filters</h3> + +-<!-- normalize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class=name id="normalize"> +-mime.<b>normalize(</b>[marker]<b>)</b> +-</p> +- +-<p class=description> +-Converts most common end-of-line markers to a specific given marker. +-</p> +- +-<p class=parameters> +-<tt>Marker</tt> is the new marker. It defaults to CRLF, the canonic +-end-of-line marker defined by the MIME standard. +-</p> +- +-<p class=return> +-The function returns a filter that performs the conversion. +-</p> +- +-<p class=note> +-Note: There is no perfect solution to this problem. Different end-of-line +-markers are an evil that will probably plague developers forever. +-This function, however, will work perfectly for text created with any of +-the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF), +-or the DOS (CRLF) conventions. Even if the data has mixed end-of-line +-markers, the function will still work well, although it doesn't +-guarantee that the number of empty lines will be correct. +-</p> + + <!-- decode +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +@@ -159,6 +131,35 @@ base64 = ltn12.filter.chain( + ) + </pre> + ++<!-- normalize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="normalize"> ++mime.<b>normalize(</b>[marker]<b>)</b> ++</p> ++ ++<p class=description> ++Converts most common end-of-line markers to a specific given marker. ++</p> ++ ++<p class=parameters> ++<tt>Marker</tt> is the new marker. It defaults to CRLF, the canonic ++end-of-line marker defined by the MIME standard. ++</p> ++ ++<p class=return> ++The function returns a filter that performs the conversion. ++</p> ++ ++<p class=note> ++Note: There is no perfect solution to this problem. Different end-of-line ++markers are an evil that will probably plague developers forever. ++This function, however, will work perfectly for text created with any of ++the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF), ++or the DOS (CRLF) conventions. Even if the data has mixed end-of-line ++markers, the function will still work well, although it doesn't ++guarantee that the number of empty lines will be correct. ++</p> ++ + <!-- stuff +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id="stuff"> +@@ -466,7 +467,7 @@ marker. + <p> + <small> + Last modified by Diego Nehab on <br> +-Thu Apr 20 00:25:44 EDT 2006 ++Fri Mar 4 15:19:17 BRT 2016 + </small> + </p> + </center> +diff --git a/doc/reference.css b/doc/reference.css +index b1dd25d..04e38cf 100644 +--- a/doc/reference.css ++++ b/doc/reference.css +@@ -2,6 +2,7 @@ body { + margin-left: 1em; + margin-right: 1em; + font-family: "Verdana", sans-serif; ++ background: #ffffff; + } + + tt { +diff --git a/doc/reference.html b/doc/reference.html +index e9bb5eb..287dc19 100644 +--- a/doc/reference.html ++++ b/doc/reference.html +@@ -147,6 +147,7 @@ Support, Manual"> + <a href="socket.html#connect">connect</a>, + <a href="socket.html#connect">connect4</a>, + <a href="socket.html#connect">connect6</a>, ++<a href="socket.html#datagramsize">_DATAGRAMSIZE</a>, + <a href="socket.html#debug">_DEBUG</a>, + <a href="dns.html#dns">dns</a>, + <a href="socket.html#gettime">gettime</a>, +@@ -158,11 +159,14 @@ Support, Manual"> + <a href="socket.html#skip">skip</a>, + <a href="socket.html#sleep">sleep</a>, + <a href="socket.html#setsize">_SETSIZE</a>, ++<a href="socket.html#socketinvalid">_SOCKETINVALID</a>, + <a href="socket.html#source">source</a>, + <a href="tcp.html#socket.tcp">tcp</a>, ++<a href="tcp.html#socket.tcp4">tcp4</a>, + <a href="tcp.html#socket.tcp6">tcp6</a>, + <a href="socket.html#try">try</a>, + <a href="udp.html#socket.udp">udp</a>, ++<a href="udp.html#socket.udp4">udp4</a>, + <a href="udp.html#socket.udp6">udp6</a>, + <a href="socket.html#version">_VERSION</a>. + </blockquote> +@@ -183,6 +187,7 @@ Support, Manual"> + <a href="tcp.html#getpeername">getpeername</a>, + <a href="tcp.html#getsockname">getsockname</a>, + <a href="tcp.html#getstats">getstats</a>, ++<a href="tcp.html#gettimeout">gettimeout</a>, + <a href="tcp.html#listen">listen</a>, + <a href="tcp.html#receive">receive</a>, + <a href="tcp.html#send">send</a>, +@@ -203,6 +208,7 @@ Support, Manual"> + <a href="udp.html#getoption">getoption</a>, + <a href="udp.html#getpeername">getpeername</a>, + <a href="udp.html#getsockname">getsockname</a>, ++<a href="udp.html#gettimeout">gettimeout</a>, + <a href="udp.html#receive">receive</a>, + <a href="udp.html#receivefrom">receivefrom</a>, + <a href="udp.html#send">send</a>, +diff --git a/doc/smtp.html b/doc/smtp.html +index bbbff80..600ec37 100644 +--- a/doc/smtp.html ++++ b/doc/smtp.html +@@ -114,6 +114,124 @@ the SMTP module: + <li> <tt>ZONE</tt>: default time zone. + </ul> + ++<!-- message ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id=message> ++smtp.<b>message(</b>mesgt<b>)</b> ++</p> ++ ++<p class=description> ++Returns a <em>simple</em> ++<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> source that sends an SMTP message body, possibly multipart (arbitrarily deep). ++</p> ++ ++<p class=parameters> ++The only parameter of the function is a table describing the message. ++<tt>Mesgt</tt> has the following form (notice the recursive structure): ++</p> ++ ++<blockquote> ++<table summary="Mesgt table structure"> ++<tr><td><tt> ++mesgt = {<br> ++ headers = <i>header-table</i>,<br> ++ body = <i>LTN12 source</i> or <i>string</i> or ++<i>multipart-mesgt</i><br> ++}<br> ++ <br> ++multipart-mesgt = {<br> ++ [preamble = <i>string</i>,]<br> ++ [1] = <i>mesgt</i>,<br> ++ [2] = <i>mesgt</i>,<br> ++ ...<br> ++ [<i>n</i>] = <i>mesgt</i>,<br> ++ [epilogue = <i>string</i>,]<br> ++}<br> ++</tt></td></tr> ++</table> ++</blockquote> ++ ++<p class=parameters> ++For a simple message, all that is needed is a set of <tt>headers</tt> ++and the <tt>body</tt>. The message <tt>body</tt> can be given as a string ++or as a <em>simple</em> ++<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> ++source. For multipart messages, the body is a table that ++recursively defines each part as an independent message, plus an optional ++<tt>preamble</tt> and <tt>epilogue</tt>. ++</p> ++ ++<p class=return> ++The function returns a <em>simple</em> ++<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> ++source that produces the ++message contents as defined by <tt>mesgt</tt>, chunk by chunk. ++Hopefully, the following ++example will make things clear. When in doubt, refer to the appropriate RFC ++as listed in the introduction. </p> ++ ++<pre class=example> ++-- load the smtp support and its friends ++local smtp = require("socket.smtp") ++local mime = require("mime") ++local ltn12 = require("ltn12") ++ ++-- creates a source to send a message with two parts. The first part is ++-- plain text, the second part is a PNG image, encoded as base64. ++source = smtp.message{ ++ headers = { ++ -- Remember that headers are *ignored* by smtp.send. ++ from = "Sicrano de Oliveira <sicrano@example.com>", ++ to = "Fulano da Silva <fulano@example.com>", ++ subject = "Here is a message with attachments" ++ }, ++ body = { ++ preamble = "If your client doesn't understand attachments, \r\n" .. ++ "it will still display the preamble and the epilogue.\r\n" .. ++ "Preamble will probably appear even in a MIME enabled client.", ++ -- first part: no headers means plain text, us-ascii. ++ -- The mime.eol low-level filter normalizes end-of-line markers. ++ [1] = { ++ body = mime.eol(0, [[ ++ Lines in a message body should always end with CRLF. ++ The smtp module will *NOT* perform translation. However, the ++ send function *DOES* perform SMTP stuffing, whereas the message ++ function does *NOT*. ++ ]]) ++ }, ++ -- second part: headers describe content to be a png image, ++ -- sent under the base64 transfer content encoding. ++ -- notice that nothing happens until the message is actually sent. ++ -- small chunks are loaded into memory right before transmission and ++ -- translation happens on the fly. ++ [2] = { ++ headers = { ++ ["content-type"] = 'image/png; name="image.png"', ++ ["content-disposition"] = 'attachment; filename="image.png"', ++ ["content-description"] = 'a beautiful image', ++ ["content-transfer-encoding"] = "BASE64" ++ }, ++ body = ltn12.source.chain( ++ ltn12.source.file(io.open("image.png", "rb")), ++ ltn12.filter.chain( ++ mime.encode("base64"), ++ mime.wrap() ++ ) ++ ) ++ }, ++ epilogue = "This might also show up, but after the attachments" ++ } ++} ++ ++-- finally send it ++r, e = smtp.send{ ++ from = "<sicrano@example.com>", ++ rcpt = "<fulano@example.com>", ++ source = source, ++} ++</pre> ++ ++ + <!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id=send> +@@ -275,123 +393,6 @@ r, e = smtp.send{ + } + </pre> + +-<!-- message ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class=name id=message> +-smtp.<b>message(</b>mesgt<b>)</b> +-</p> +- +-<p class=description> +-Returns a <em>simple</em> +-<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> source that sends an SMTP message body, possibly multipart (arbitrarily deep). +-</p> +- +-<p class=parameters> +-The only parameter of the function is a table describing the message. +-<tt>Mesgt</tt> has the following form (notice the recursive structure): +-</p> +- +-<blockquote> +-<table summary="Mesgt table structure"> +-<tr><td><tt> +-mesgt = {<br> +- headers = <i>header-table</i>,<br> +- body = <i>LTN12 source</i> or <i>string</i> or +-<i>multipart-mesgt</i><br> +-}<br> +- <br> +-multipart-mesgt = {<br> +- [preamble = <i>string</i>,]<br> +- [1] = <i>mesgt</i>,<br> +- [2] = <i>mesgt</i>,<br> +- ...<br> +- [<i>n</i>] = <i>mesgt</i>,<br> +- [epilogue = <i>string</i>,]<br> +-}<br> +-</tt></td></tr> +-</table> +-</blockquote> +- +-<p class=parameters> +-For a simple message, all that is needed is a set of <tt>headers</tt> +-and the <tt>body</tt>. The message <tt>body</tt> can be given as a string +-or as a <em>simple</em> +-<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> +-source. For multipart messages, the body is a table that +-recursively defines each part as an independent message, plus an optional +-<tt>preamble</tt> and <tt>epilogue</tt>. +-</p> +- +-<p class=return> +-The function returns a <em>simple</em> +-<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> +-source that produces the +-message contents as defined by <tt>mesgt</tt>, chunk by chunk. +-Hopefully, the following +-example will make things clear. When in doubt, refer to the appropriate RFC +-as listed in the introduction. </p> +- +-<pre class=example> +--- load the smtp support and its friends +-local smtp = require("socket.smtp") +-local mime = require("mime") +-local ltn12 = require("ltn12") +- +--- creates a source to send a message with two parts. The first part is +--- plain text, the second part is a PNG image, encoded as base64. +-source = smtp.message{ +- headers = { +- -- Remember that headers are *ignored* by smtp.send. +- from = "Sicrano de Oliveira <sicrano@example.com>", +- to = "Fulano da Silva <fulano@example.com>", +- subject = "Here is a message with attachments" +- }, +- body = { +- preamble = "If your client doesn't understand attachments, \r\n" .. +- "it will still display the preamble and the epilogue.\r\n" .. +- "Preamble will probably appear even in a MIME enabled client.", +- -- first part: no headers means plain text, us-ascii. +- -- The mime.eol low-level filter normalizes end-of-line markers. +- [1] = { +- body = mime.eol(0, [[ +- Lines in a message body should always end with CRLF. +- The smtp module will *NOT* perform translation. However, the +- send function *DOES* perform SMTP stuffing, whereas the message +- function does *NOT*. +- ]]) +- }, +- -- second part: headers describe content to be a png image, +- -- sent under the base64 transfer content encoding. +- -- notice that nothing happens until the message is actually sent. +- -- small chunks are loaded into memory right before transmission and +- -- translation happens on the fly. +- [2] = { +- headers = { +- ["content-type"] = 'image/png; name="image.png"', +- ["content-disposition"] = 'attachment; filename="image.png"', +- ["content-description"] = 'a beautiful image', +- ["content-transfer-encoding"] = "BASE64" +- }, +- body = ltn12.source.chain( +- ltn12.source.file(io.open("image.png", "rb")), +- ltn12.filter.chain( +- mime.encode("base64"), +- mime.wrap() +- ) +- ) +- }, +- epilogue = "This might also show up, but after the attachments" +- } +-} +- +--- finally send it +-r, e = smtp.send{ +- from = "<sicrano@example.com>", +- rcpt = "<fulano@example.com>", +- source = source, +-} +-</pre> +- + <!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <div class=footer> +diff --git a/doc/socket.html b/doc/socket.html +index b9303cb..35f8391 100644 +--- a/doc/socket.html ++++ b/doc/socket.html +@@ -51,6 +51,30 @@ To obtain the <tt>socket</tt> namespace, run: + local socket = require("socket") + </pre> + ++<!-- headers.canonic ++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="headers.canonic"> ++socket.headers.<b>canonic</b></p> ++ ++<p> The <tt>socket.headers.canonic</tt> table ++is used by the HTTP and SMTP modules to translate from ++lowercase field names back into their canonic ++capitalization. When a lowercase field name exists as a key ++in this table, the associated value is substituted in ++whenever the field name is sent out. ++</p> ++ ++<p> ++You can obtain the <tt>headers</tt> namespace if case run-time ++modifications are required by running: ++</p> ++ ++<pre class=example> ++-- loads the headers module ++local headers = require("headers") ++</pre> ++ ++ + <!-- bind ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id=bind> +@@ -90,7 +114,7 @@ of connect are defined as simple helper functions that restrict the + + <!-- debug ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id=debug> ++<p class=name id=debug> + socket.<b>_DEBUG</b> + </p> + +@@ -99,6 +123,19 @@ This constant is set to <tt><b>true</b></tt> if the library was compiled + with debug support. + </p> + ++<!-- datagramsize +++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id=debug> ++socket.<b>_DATAGRAMSIZE</b> ++</p> ++ ++<p class=description> ++Default datagram size used by calls to ++<a href="udp.html#receive"<tt>receive</tt></a> and ++<a href="udp.html#receivefrom"><tt>receivefrom</tt></a>. ++(Unless changed in compile time, the value is 8192.) ++</p> ++ + <!-- get time +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id=gettime> +@@ -106,8 +143,7 @@ socket.<b>gettime()</b> + </p> + + <p class=description> +-Returns the time in seconds, relative to the origin of the +-universe. You should subtract the values returned by this function ++Returns the UNIX time in seconds. You should subtract the values returned by this function + to get meaningful values. + </p> + +@@ -117,29 +153,6 @@ t = socket.gettime() + print(socket.gettime() - t .. " seconds elapsed") + </pre> + +-<!-- socket.headers ++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class=name id="headers.canonic"> +-socket.headers.<b>canonic</b></p> +- +-<p> The <tt>socket.headers.canonic</tt> table +-is used by the HTTP and SMTP modules to translate from +-lowercase field names back into their canonic +-capitalization. When a lowercase field name exists as a key +-in this table, the associated value is substituted in +-whenever the field name is sent out. +-</p> +- +-<p> +-You can obtain the <tt>headers</tt> namespace if case run-time +-modifications are required by running: +-</p> +- +-<pre class=example> +--- loads the headers module +-local headers = require("headers") +-</pre> +- + <!-- newtry +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id=newtry> +@@ -155,8 +168,7 @@ is raised. + + <p class=parameters> + <tt>Finalizer</tt> is a function that will be called before +-<tt>try</tt> throws the exception. It will be called +-in <em>protected</em> mode. ++<tt>try</tt> throws the exception. + </p> + + <p class=return> +@@ -204,15 +216,9 @@ to throw exceptions. + </p> + + <p class=return> +-Returns an equivalent function that instead of throwing exceptions, +-returns <tt><b>nil</b></tt> followed by an error message. +-</p> +- +-<p class=note> +-Note: Beware that if your function performs some illegal operation that +-raises an error, the protected function will catch the error and return it +-as a string. This is because the <a href=#try><tt>try</tt></a> function +-uses errors as the mechanism to throw exceptions. ++Returns an equivalent function that instead of throwing exceptions in case of ++a failed <a href=#try><tt>try</tt></a> call, returns <tt><b>nil</b></tt> ++followed by an error message. + </p> + + <!-- select +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +@@ -238,7 +244,9 @@ non-numeric indices) in the arrays will be silently ignored. + + <p class=return> The function returns a list with the sockets ready for + reading, a list with the sockets ready for writing and an error message. +-The error message is "<tt>timeout</tt>" if a timeout condition was met and ++The error message is "<tt>timeout</tt>" if a timeout ++condition was met, "<tt>select failed</tt>" if the call ++to <tt>select</tt> failed, and + <tt><b>nil</b></tt> otherwise. The returned tables are + doubly keyed both by integers and also by the sockets + themselves, to simplify the test if a specific socket has +@@ -246,7 +254,7 @@ changed status. + </p> + + <p class=note> +-<b>Note: </b>: <tt>select</tt> can monitor a limited number ++<b>Note:</b> <tt>select</tt> can monitor a limited number + of sockets, as defined by the constant <tt>socket._SETSIZE</tt>. This + number may be as high as 1024 or as low as 64 by default, + depending on the system. It is usually possible to change this +@@ -276,6 +284,18 @@ it to <tt>select</tt>, it will be ignored. + <b>Using select with non-socket objects</b>: Any object that implements <tt>getfd</tt> and <tt>dirty</tt> can be used with <tt>select</tt>, allowing objects from other libraries to be used within a <tt>socket.select</tt> driven loop. + </p> + ++<!-- setsize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id=setsize> ++socket.<b>_SETSIZE</b> ++</p> ++ ++<p class=description> ++The maximum number of sockets that the <a ++href=#select><tt>select</tt></a> function can handle. ++</p> ++ ++ + <!-- sink ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id=sink> +@@ -383,15 +403,14 @@ side closes the connection. + The function returns a source with the appropriate behavior. + </p> + +-<!-- setsize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++<!-- socketinvalid ++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id=setsize> +-socket.<b>_SETSIZE</b> ++<p class=name id=socketinvalid> ++socket.<b>_SOCKETINVALID</b> + </p> + + <p class=description> +-The maximum number of sockets that the <a +-href=#select><tt>select</tt></a> function can handle. ++The OS value for an invalid socket. + </p> + + <!-- try ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +@@ -401,9 +420,9 @@ socket.<b>try(</b>ret<sub>1</sub> [, ret<sub>2</sub> ... ret<sub>N</sub>]<b>)</b + </p> + + <p class=description> +-Throws an exception in case of error. The exception can only be caught +-by the <a href=#protect><tt>protect</tt></a> function. It does not explode +-into an error message. ++Throws an exception in case <tt>ret<sub>1</sub></tt> is falsy, using ++<tt>ret<sub>2</sub></tt> as the error message. The exception is supposed to be caught ++by a <a href=#protect><tt>protect</tt></a>ed function only. + </p> + + <p class=parameters> +@@ -414,7 +433,10 @@ nested with <tt>try</tt>. + + <p class=return> + The function returns <tt>ret</tt><sub>1</sub> to <tt>ret</tt><sub>N</sub> if +-<tt>ret</tt><sub>1</sub> is not <tt><b>nil</b></tt>. Otherwise, it calls <tt>error</tt> passing <tt>ret</tt><sub>2</sub>. ++<tt>ret</tt><sub>1</sub> is not <tt><b>nil</b></tt> or <tt><b>false</b></tt>. ++Otherwise, it calls <tt>error</tt> passing <tt>ret</tt><sub>2</sub> wrapped ++in a table with metatable used by <a href=#protect><tt>protect</tt></a> to ++distinguish exceptions from runtime errors. + </p> + + <pre class=example> +diff --git a/doc/tcp.html b/doc/tcp.html +index 4226d78..c6c6eb2 100644 +--- a/doc/tcp.html ++++ b/doc/tcp.html +@@ -1,10 +1,10 @@ +-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> + <html> + + <head> + <meta name="description" content="LuaSocket: The TCP/IP support"> +-<meta name="keywords" content="Lua, LuaSocket, Socket, TCP, Library, Network, Support"> ++<meta name="keywords" content="Lua, LuaSocket, Socket, TCP, Library, Network, Support"> + <title>LuaSocket: TCP/IP support</title> + <link rel="stylesheet" href="reference.css" type="text/css"> + </head> +@@ -28,7 +28,7 @@ + <a href="index.html#download">download</a> · + <a href="installation.html">installation</a> · + <a href="introduction.html">introduction</a> · +-<a href="reference.html">reference</a> ++<a href="reference.html">reference</a> + </p> + </center> + <hr> +@@ -36,56 +36,11 @@ + + <!-- tcp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<h2 id="tcp">TCP</h2> +- +-<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class=name id="socket.tcp"> +-socket.<b>tcp()</b> +-</p> +- +-<p class=description> +-Creates and returns an IPv4 TCP master object. A master object can +-be transformed into a server object with the method +-<a href=#listen><tt>listen</tt></a> (after a call to <a +-href=#bind><tt>bind</tt></a>) or into a client object with +-the method <a href=#connect><tt>connect</tt></a>. The only other +-method supported by a master object is the +-<a href=#close><tt>close</tt></a> method.</p> +- +-<p class=return> +-In case of success, a new master object is returned. In case of error, +-<b><tt>nil</tt></b> is returned, followed by an error message. +-</p> +- +-<!-- socket.tcp6 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class=name id="socket.tcp6"> +-socket.<b>tcp6()</b> +-</p> +- +-<p class=description> +-Creates and returns an IPv6 TCP master object. A master object can +-be transformed into a server object with the method +-<a href=#listen><tt>listen</tt></a> (after a call to <a +-href=#bind><tt>bind</tt></a>) or into a client object with +-the method <a href=#connect><tt>connect</tt></a>. The only other +-method supported by a master object is the +-<a href=#close><tt>close</tt></a> method.</p> +- +-<p class=return> +-In case of success, a new master object is returned. In case of error, +-<b><tt>nil</tt></b> is returned, followed by an error message. +-</p> +- +-<p class=note> +-Note: The TCP object returned will have the option +-"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>. +-</p> ++<h2 id="tcp">TCP</h2> + + <!-- accept +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id="accept"> ++<p class=name id="accept"> + server:<b>accept()</b> + </p> + +@@ -95,9 +50,9 @@ object and returns a client object representing that connection. + </p> + + <p class=return> +-If a connection is successfully initiated, a client object is returned. ++If a connection is successfully initiated, a client object is returned. + If a timeout condition is met, the method returns <b><tt>nil</tt></b> +-followed by the error string '<tt>timeout</tt>'. Other errors are ++followed by the error string '<tt>timeout</tt>'. Other errors are + reported by <b><tt>nil</tt></b> followed by a message describing the error. + </p> + +@@ -107,28 +62,28 @@ with a server object in + the <tt>recvt</tt> parameter before a call to <tt>accept</tt> does + <em>not</em> guarantee <tt>accept</tt> will return immediately. Use the <a + href=#settimeout><tt>settimeout</tt></a> method or <tt>accept</tt> +-might block until <em>another</em> client shows up. ++might block until <em>another</em> client shows up. + </p> + + <!-- bind +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id="bind"> ++<p class=name id="bind"> + master:<b>bind(</b>address, port<b>)</b> + </p> + + <p class=description> + Binds a master object to <tt>address</tt> and <tt>port</tt> on the +-local host. ++local host. + + <p class=parameters> +-<tt>Address</tt> can be an IP address or a host name. +-<tt>Port</tt> must be an integer number in the range [0..64K). ++<tt>Address</tt> can be an IP address or a host name. ++<tt>Port</tt> must be an integer number in the range [0..64K). + If <tt>address</tt> + is '<tt>*</tt>', the system binds to all local interfaces + using the <tt>INADDR_ANY</tt> constant or +-<tt>IN6ADDR_ANY_INIT</tt>, according to the family. ++<tt>IN6ADDR_ANY_INIT</tt>, according to the family. + If <tt>port</tt> is 0, the system automatically +-chooses an ephemeral port. ++chooses an ephemeral port. + </p> + + <p class=return> +@@ -137,13 +92,13 @@ method returns <b><tt>nil</tt></b> followed by an error message. + </p> + + <p class=note> +-Note: The function <a href=socket.html#bind><tt>socket.bind</tt></a> ++Note: The function <a href=socket.html#bind><tt>socket.bind</tt></a> + is available and is a shortcut for the creation of server sockets. + </p> + + <!-- close ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id="close"> ++<p class=name id="close"> + master:<b>close()</b><br> + client:<b>close()</b><br> + server:<b>close()</b> +@@ -154,14 +109,14 @@ Closes a TCP object. The internal socket used by the object is closed + and the local address to which the object was + bound is made available to other applications. No further operations + (except for further calls to the <tt>close</tt> method) are allowed on +-a closed socket. ++a closed socket. + </p> + + <p class=note> + Note: It is important to close all used sockets once they are not + needed, since, in many systems, each socket uses a file descriptor, + which are limited system resources. Garbage-collected objects are +-automatically closed before destruction, though. ++automatically closed before destruction, though. + </p> + + <!-- connect ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +@@ -172,19 +127,19 @@ master:<b>connect(</b>address, port<b>)</b> + + <p class=description> + Attempts to connect a master object to a remote host, transforming it into a +-client object. +-Client objects support methods ++client object. ++Client objects support methods + <a href=#send><tt>send</tt></a>, +-<a href=#receive><tt>receive</tt></a>, +-<a href=#getsockname><tt>getsockname</tt></a>, ++<a href=#receive><tt>receive</tt></a>, ++<a href=#getsockname><tt>getsockname</tt></a>, + <a href=#getpeername><tt>getpeername</tt></a>, +-<a href=#settimeout><tt>settimeout</tt></a>, ++<a href=#settimeout><tt>settimeout</tt></a>, + and <a href=#close><tt>close</tt></a>. + </p> + + <p class=parameters> +-<tt>Address</tt> can be an IP address or a host name. +-<tt>Port</tt> must be an integer number in the range [1..64K). ++<tt>Address</tt> can be an IP address or a host name. ++<tt>Port</tt> must be an integer number in the range [1..64K). + </p> + + <p class=return> +@@ -193,14 +148,14 @@ describing the error. In case of success, the method returns 1. + </p> + + <p class=note> +-Note: The function <a href=socket.html#connect><tt>socket.connect</tt></a> ++Note: The function <a href=socket.html#connect><tt>socket.connect</tt></a> + is available and is a shortcut for the creation of client sockets. + </p> + + <p class=note> +-Note: Starting with LuaSocket 2.0, ++Note: Starting with LuaSocket 2.0, + the <a href=#settimeout><tt>settimeout</tt></a> +-method affects the behavior of <tt>connect</tt>, causing it to return ++method affects the behavior of <tt>connect</tt>, causing it to return + with an error in case of a timeout. If that happens, you can still call <a + href=socket.html#select><tt>socket.select</tt></a> with the socket in the + <tt>sendt</tt> table. The socket will be writable when the connection is +@@ -209,13 +164,88 @@ established. + + <p class=note> + Note: Starting with LuaSocket 3.0, the host name resolution +-depends on whether the socket was created by <a +-href=#socket.tcp><tt>socket.tcp</tt></a> or <a +-href=#socket.tcp6><tt>socket.tcp6</tt></a>. Addresses from +-the appropriate family are tried in succession until the +-first success or until the last failure. ++depends on whether the socket was created by ++<a href=#socket.tcp><tt>socket.tcp</tt></a>, ++<a href=#socket.tcp4><tt>socket.tcp4</tt></a> or ++<a href=#socket.tcp6><tt>socket.tcp6</tt></a>. Addresses from ++the appropriate family (or both) are tried in the order ++returned by the resolver until the ++first success or until the last failure. If the timeout was ++set to zero, only the first address is tried. ++</p> ++ ++<!-- dirty +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="dirty"> ++master:<b>dirty()</b><br> ++client:<b>dirty()</b><br> ++server:<b>dirty()</b> ++</p> ++ ++<p class=description> ++Check the read buffer status. ++</p> ++ ++<p class=return> ++Returns <tt>true</tt> if there is any data in the read buffer, <tt>false</tt> otherwise. ++</p> ++ ++<p class=note> ++Note: <b>This is an internal method, use at your own risk.</b> ++</p> ++ ++ ++<!-- getfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="getfd"> ++master:<b>getfd()</b><br> ++client:<b>getfd()</b><br> ++server:<b>getfd()</b> ++</p> ++ ++<p class=description> ++Returns the underling socket descriptor or handle associated to the object. ++</p> ++ ++<p class=return> ++The descriptor or handle. In case the object has been closed, the return will be -1. ++</p> ++ ++<p class=note> ++Note: <b>This is an internal method. Unlikely to be ++portable. Use at your own risk. </b> ++</p> ++ ++ ++<!-- getoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="getoption"> ++client:<b>getoption(</b>option)</b><br> ++server:<b>getoption(</b>option)</b> ++</p> ++ ++<p class=description> ++Gets options for the TCP object. ++See <a href=#setoption><tt>setoption</tt></a> for description of the ++option names and values. ++</p> ++ ++<p class=parameters> ++<tt>Option</tt> is a string with the option name. ++<ul> ++ ++<li> '<tt>keepalive</tt>' ++<li> '<tt>linger</tt>' ++<li> '<tt>reuseaddr</tt>' ++<li> '<tt>tcp-nodelay</tt>' ++</ul> ++ ++<p class=return> ++The method returns the option <tt>value</tt> in case of success, or ++<b><tt>nil</tt></b> followed by an error message otherwise. + </p> + ++ + <!-- getpeername ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id="getpeername"> +@@ -227,10 +257,10 @@ Returns information about the remote side of a connected client object. + </p> + + <p class=return> +-Returns a string with the IP address of the peer, the +-port number that peer is using for the connection, +-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). +-In case of error, the method returns <b><tt>nil</tt></b>. ++Returns a string with the IP address of the peer, the ++port number that peer is using for the connection, ++and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). ++In case of error, the method returns <b><tt>nil</tt></b>. + </p> + + <p class=note> +@@ -246,13 +276,13 @@ server:<b>getsockname()</b> + </p> + + <p class=description> +-Returns the local address information associated to the object. ++Returns the local address information associated to the object. + </p> + + <p class=return> +-The method returns a string with local IP address, a number with +-the local port, +-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). ++The method returns a string with local IP address, a number with ++the local port, ++and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). + In case of error, the method returns <b><tt>nil</tt></b>. + </p> + +@@ -266,32 +296,46 @@ server:<b>getstats()</b><br> + + <p class=description> + Returns accounting information on the socket, useful for throttling +-of bandwidth. ++of bandwidth. + </p> + + <p class=return> + The method returns the number of bytes received, the number of bytes sent, +-and the age of the socket object in seconds. ++and the age of the socket object in seconds. + </p> + ++<!-- gettimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="gettimeout"> ++master:<b>gettimeout()</b><br> ++client:<b>gettimeout()</b><br> ++server:<b>gettimeout()</b> ++</p> ++ ++<p class=description> ++Returns the current block timeout followed by the curent ++total timeout. ++</p> ++ ++ + <!-- listen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id="listen"> ++<p class=name id="listen"> + master:<b>listen(</b>backlog<b>)</b> + </p> + + <p class=description> + Specifies the socket is willing to receive connections, transforming the +-object into a server object. Server objects support the +-<a href=#accept><tt>accept</tt></a>, +-<a href=#getsockname><tt>getsockname</tt></a>, +-<a href=#setoption><tt>setoption</tt></a>, +-<a href=#settimeout><tt>settimeout</tt></a>, +-and <a href=#close><tt>close</tt></a> methods. ++object into a server object. Server objects support the ++<a href=#accept><tt>accept</tt></a>, ++<a href=#getsockname><tt>getsockname</tt></a>, ++<a href=#setoption><tt>setoption</tt></a>, ++<a href=#settimeout><tt>settimeout</tt></a>, ++and <a href=#close><tt>close</tt></a> methods. + </p> + + <p class=parameters> +-The parameter <tt>backlog</tt> specifies the number of client ++The parameter <tt>backlog</tt> specifies the number of client + connections that can + be queued waiting for service. If the queue is full and another client + attempts connection, the connection is refused. +@@ -310,11 +354,11 @@ client:<b>receive(</b>[pattern [, prefix]]<b>)</b> + + <p class=description> + Reads data from a client object, according to the specified <em>read +-pattern</em>. Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible. ++pattern</em>. Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible. + </p> + + <p class=parameters> +-<tt>Pattern</tt> can be any of the following: ++<tt>Pattern</tt> can be any of the following: + </p> + + <ul> +@@ -325,7 +369,7 @@ terminated by a LF character (ASCII 10), optionally preceded by a + CR character (ASCII 13). The CR and LF characters are not included in + the returned line. In fact, <em>all</em> CR characters are + ignored by the pattern. This is the default pattern; +-<li> <tt>number</tt>: causes the method to read a specified <tt>number</tt> ++<li> <tt>number</tt>: causes the method to read a specified <tt>number</tt> + of bytes from the socket. + </ul> + +@@ -347,10 +391,10 @@ closed before the transmission was completed or the string + <p class=note> + <b>Important note</b>: This function was changed <em>severely</em>. It used + to support multiple patterns (but I have never seen this feature used) and +-now it doesn't anymore. Partial results used to be returned in the same ++now it doesn't anymore. Partial results used to be returned in the same + way as successful results. This last feature violated the idea that all + functions should return <tt><b>nil</b></tt> on error. Thus it was changed +-too. ++too. + </p> + + <!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +@@ -366,7 +410,7 @@ Sends <tt>data</tt> through client object. + <p class=parameters> + <tt>Data</tt> is the string to be sent. The optional arguments + <tt>i</tt> and <tt>j</tt> work exactly like the standard +-<tt>string.sub</tt> Lua function to allow the selection of a ++<tt>string.sub</tt> Lua function to allow the selection of a + substring to be sent. + </p> + +@@ -385,10 +429,10 @@ there was a timeout during the operation. + </p> + + <p class=note> +-Note: Output is <em>not</em> buffered. For small strings, +-it is always better to concatenate them in Lua +-(with the '<tt>..</tt>' operator) and send the result in one call +-instead of calling the method several times. ++Note: Output is <em>not</em> buffered. For small strings, ++it is always better to concatenate them in Lua ++(with the '<tt>..</tt>' operator) and send the result in one call ++instead of calling the method several times. + </p> + + <!-- setoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +@@ -400,12 +444,12 @@ server:<b>setoption(</b>option [, value]<b>)</b> + + <p class=description> + Sets options for the TCP object. Options are only needed by low-level or +-time-critical applications. You should only modify an option if you +-are sure you need it. ++time-critical applications. You should only modify an option if you ++are sure you need it. + </p> + + <p class=parameters> +-<tt>Option</tt> is a string with the option name, and <tt>value</tt> ++<tt>Option</tt> is a string with the option name, and <tt>value</tt> + depends on the option being set: + + <ul> +@@ -413,7 +457,7 @@ depends on the option being set: + <li> '<tt>keepalive</tt>': Setting this option to <tt>true</tt> enables + the periodic transmission of messages on a connected socket. Should the + connected party fail to respond to these messages, the connection is +-considered broken and processes using the socket are notified; ++considered broken and processes using the socket are notified; + + <li> '<tt>linger</tt>': Controls the action taken when unsent data are + queued on a socket and a close is performed. The value is a table with a +@@ -424,13 +468,13 @@ it is able to transmit the data or until '<tt>timeout</tt>' has passed. If + '<tt>on</tt>' is <tt>false</tt> and a close is issued, the system will + process the close in a manner that allows the process to continue as + quickly as possible. I do not advise you to set this to anything other than +-zero; ++zero; + + <li> '<tt>reuseaddr</tt>': Setting this option indicates that the rules +-used in validating addresses supplied in a call to ++used in validating addresses supplied in a call to + <a href=#bind><tt>bind</tt></a> should allow reuse of local addresses; + +-<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt> ++<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt> + disables the Nagle's algorithm for the connection; + + <li> '<tt>ipv6-v6only</tt>': +@@ -447,34 +491,6 @@ followed by an error message otherwise. + Note: The descriptions above come from the man pages. + </p> + +-<!-- getoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class=name id="getoption"> +-client:<b>getoption(</b>option)</b><br> +-server:<b>getoption(</b>option)</b> +-</p> +- +-<p class=description> +-Gets options for the TCP object. +-See <a href=#setoption><tt>setoption</tt></a> for description of the +-option names and values. +-</p> +- +-<p class=parameters> +-<tt>Option</tt> is a string with the option name. +-<ul> +- +-<li> '<tt>keepalive</tt>' +-<li> '<tt>linger</tt>' +-<li> '<tt>reuseaddr</tt>' +-<li> '<tt>tcp-nodelay</tt>' +-</ul> +- +-<p class=return> +-The method returns the option <tt>value</tt> in case of success, or +-<b><tt>nil</tt></b> followed by an error message otherwise. +-</p> +- + <!-- setstats +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class=name id="setstats"> +@@ -485,7 +501,7 @@ server:<b>setstats(</b>received, sent, age<b>)</b><br> + + <p class=description> + Resets accounting information on the socket, useful for throttling +-of bandwidth. ++of bandwidth. + </p> + + <p class=parameters> +@@ -495,7 +511,7 @@ of bandwidth. + </p> + + <p class=return> +-The method returns 1 in case of success and <tt><b>nil</b></tt> otherwise. ++The method returns 1 in case of success and <tt><b>nil</b></tt> otherwise. + </p> + + <!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +@@ -509,8 +525,8 @@ server:<b>settimeout(</b>value [, mode]<b>)</b> + <p class=description> + Changes the timeout values for the object. By default, + all I/O operations are blocking. That is, any call to the methods +-<a href=#send><tt>send</tt></a>, +-<a href=#receive><tt>receive</tt></a>, and ++<a href=#send><tt>send</tt></a>, ++<a href=#receive><tt>receive</tt></a>, and + <a href=#accept><tt>accept</tt></a> + will block indefinitely, until the operation completes. The + <tt>settimeout</tt> method defines a limit on the amount of time the +@@ -521,7 +537,7 @@ time has elapsed, the affected methods give up and fail with an error code. + <p class=parameters> + The amount of time to wait is specified as the + <tt>value</tt> parameter, in seconds. There are two timeout modes and +-both can be used together for fine tuning: ++both can be used together for fine tuning: + </p> + + <ul> +@@ -532,7 +548,7 @@ default mode;</li> + + <li> '<tt>t</tt>': <em>total</em> timeout. Specifies the upper limit on + the amount of time LuaSocket can block a Lua script before returning from +-a call.</li> ++a call.</li> + </ul> + + <p class=parameters> +@@ -562,7 +578,7 @@ client:<b>shutdown(</b>mode<b>)</b><br> + </p> + + <p class=description> +-Shuts down part of a full-duplex connection. ++Shuts down part of a full-duplex connection. + </p> + + <p class=parameters> +@@ -579,66 +595,107 @@ This is the default mode; + This function returns 1. + </p> + +-<!-- dirty +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++<!-- setfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id="dirty"> +-master:<b>dirty()</b><br> +-client:<b>dirty()</b><br> +-server:<b>dirty()</b> ++<p class=name id="setfd"> ++master:<b>setfd(</b>fd<b>)</b><br> ++client:<b>setfd(</b>fd<b>)</b><br> ++server:<b>setfd(</b>fd<b>)</b> + </p> + + <p class=description> +-Check the read buffer status. ++Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made. + </p> + + <p class=return> +-Returns <tt>true</tt> if there is any data in the read buffer, <tt>false</tt> otherwise. ++No return value. + </p> + + <p class=note> +-Note: <b>This is an internal method, any use is unlikely to be portable.</b> ++Note: <b>This is an internal method. Unlikely to be ++portable. Use at your own risk. </b> + </p> + +-<!-- getfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<p class=name id="getfd"> +-master:<b>getfd()</b><br> +-client:<b>getfd()</b><br> +-server:<b>getfd()</b> ++<p class=name id="socket.tcp"> ++socket.<b>tcp()</b> + </p> + + <p class=description> +-Returns the underling socket descriptor or handle associated to the object. +-</p> ++Creates and returns an TCP master object. A master object can ++be transformed into a server object with the method ++<a href=#listen><tt>listen</tt></a> (after a call to <a ++href=#bind><tt>bind</tt></a>) or into a client object with ++the method <a href=#connect><tt>connect</tt></a>. The only other ++method supported by a master object is the ++<a href=#close><tt>close</tt></a> method.</p> + + <p class=return> +-The descriptor or handle. In case the object has been closed, the return will be -1. ++In case of success, a new master object is returned. In case of error, ++<b><tt>nil</tt></b> is returned, followed by an error message. + </p> + + <p class=note> +-Note: <b>This is an internal method, any use is unlikely to be portable.</b> ++Note: The choice between IPv4 and IPv6 happens during a call to ++<a href=#bind><tt>bind</tt></a> or <a ++href=#bind><tt>connect</tt></a>, depending on the address ++family obtained from the resolver. + </p> + +-<!-- setfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++<p class=note> ++Note: Before the choice between IPv4 and IPv6 happens, ++the internal socket object is invalid and therefore <a ++href=#setoption><tt>setoption</tt></a> will fail. ++</p> + +-<p class=name id="setfd"> +-master:<b>setfd(</b>fd<b>)</b><br> +-client:<b>setfd(</b>fd<b>)</b><br> +-server:<b>setfd(</b>fd<b>)</b> ++<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="socket.tcp4"> ++socket.<b>tcp4()</b> + </p> + + <p class=description> +-Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made. ++Creates and returns an IPv4 TCP master object. A master object can ++be transformed into a server object with the method ++<a href=#listen><tt>listen</tt></a> (after a call to <a ++href=#bind><tt>bind</tt></a>) or into a client object with ++the method <a href=#connect><tt>connect</tt></a>. The only other ++method supported by a master object is the ++<a href=#close><tt>close</tt></a> method.</p> ++ ++<p class=return> ++In case of success, a new master object is returned. In case of error, ++<b><tt>nil</tt></b> is returned, followed by an error message. ++</p> ++ ++<!-- socket.tcp6 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="socket.tcp6"> ++socket.<b>tcp6()</b> + </p> + ++<p class=description> ++Creates and returns an IPv6 TCP master object. A master object can ++be transformed into a server object with the method ++<a href=#listen><tt>listen</tt></a> (after a call to <a ++href=#bind><tt>bind</tt></a>) or into a client object with ++the method <a href=#connect><tt>connect</tt></a>. The only other ++method supported by a master object is the ++<a href=#close><tt>close</tt></a> method.</p> ++ + <p class=return> +-No return value. ++In case of success, a new master object is returned. In case of error, ++<b><tt>nil</tt></b> is returned, followed by an error message. + </p> + + <p class=note> +-Note: <b>This is an internal method, any use is unlikely to be portable.</b> ++Note: The TCP object returned will have the option ++"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>. + </p> + ++ ++ + <!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <div class=footer> +diff --git a/doc/udp.html b/doc/udp.html +index e5b0ad0..4618aad 100644 +--- a/doc/udp.html ++++ b/doc/udp.html +@@ -4,7 +4,7 @@ + + <head> + <meta name="description" content="LuaSocket: The UDP support"> +-<meta name="keywords" content="Lua, LuaSocket, Socket, UDP, Library, Network, Support"> ++<meta name="keywords" content="Lua, LuaSocket, Socket, UDP, Library, Network, Support"> + <title>LuaSocket: UDP support</title> + <link rel="stylesheet" href="reference.css" type="text/css"> + </head> +@@ -28,7 +28,7 @@ + <a href="index.html#download">download</a> · + <a href="installation.html">installation</a> · + <a href="introduction.html">introduction</a> · +-<a href="reference.html">reference</a> ++<a href="reference.html">reference</a> + </p> + </center> + <hr> +@@ -37,74 +37,7 @@ + + <!-- udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +-<h2 id="udp">UDP</h2> +- +-<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class="name" id="socket.udp"> +-socket.<b>udp()</b> +-</p> +- +-<p class="description"> +-Creates and returns an unconnected IPv4 UDP object. +-Unconnected objects support the +-<a href="#sendto"><tt>sendto</tt></a>, +-<a href="#receive"><tt>receive</tt></a>, +-<a href="#receivefrom"><tt>receivefrom</tt></a>, +-<a href="#getoption"><tt>getoption</tt></a>, +-<a href="#getsockname"><tt>getsockname</tt></a>, +-<a href="#setoption"><tt>setoption</tt></a>, +-<a href="#settimeout"><tt>settimeout</tt></a>, +-<a href="#setpeername"><tt>setpeername</tt></a>, +-<a href="#setsockname"><tt>setsockname</tt></a>, and +-<a href="#close"><tt>close</tt></a>. +-The <a href="#setpeername"><tt>setpeername</tt></a> +-is used to connect the object. +-</p> +- +-<p class="return"> +-In case of success, a new unconnected UDP object +-returned. In case of error, <b><tt>nil</tt></b> is returned, followed by +-an error message. +-</p> +- +-<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class="name" id="socket.udp6"> +-socket.<b>udp6()</b> +-</p> +- +-<p class="description"> +-Creates and returns an unconnected IPv6 UDP object. +-Unconnected objects support the +-<a href="#sendto"><tt>sendto</tt></a>, +-<a href="#receive"><tt>receive</tt></a>, +-<a href="#receivefrom"><tt>receivefrom</tt></a>, +-<a href="#getoption"><tt>getoption</tt></a>, +-<a href="#getsockname"><tt>getsockname</tt></a>, +-<a href="#setoption"><tt>setoption</tt></a>, +-<a href="#settimeout"><tt>settimeout</tt></a>, +-<a href="#setpeername"><tt>setpeername</tt></a>, +-<a href="#setsockname"><tt>setsockname</tt></a>, and +-<a href="#close"><tt>close</tt></a>. +-The <a href="#setpeername"><tt>setpeername</tt></a> +-is used to connect the object. +-</p> +- +-<p class="return"> +-In case of success, a new unconnected UDP object +-returned. In case of error, <b><tt>nil</tt></b> is returned, followed by +-an error message. +-</p> +- +-<p class=note> +-Note: The TCP object returned will have the option +-"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>. +-</p> +- +- +- +-<!-- close +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++<h2 id="udp">UDP</h2> + + <!-- close +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + +@@ -129,6 +62,40 @@ Garbage-collected objects are automatically closed before + destruction, though. + </p> + ++<!-- getoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class="name" id="getoption"> ++connected:<b>getoption()</b><br> ++unconnected:<b>getoption()</b> ++</p> ++ ++<p class="description"> ++Gets an option value from the UDP object. ++See <a href=#setoption><tt>setoption</tt></a> for ++description of the option names and values. ++</p> ++ ++<p class="parameters"><tt>Option</tt> is a string with the option name. ++<ul> ++<li> '<tt>dontroute</tt>' ++<li> '<tt>broadcast</tt>' ++<li> '<tt>reuseaddr</tt>' ++<li> '<tt>reuseport</tt>' ++<li> '<tt>ip-multicast-loop</tt>' ++<li> '<tt>ipv6-v6only</tt>' ++<li> '<tt>ip-multicast-if</tt>' ++<li> '<tt>ip-multicast-ttl</tt>' ++<li> '<tt>ip-add-membership</tt>' ++<li> '<tt>ip-drop-membership</tt>' ++</ul> ++</p> ++ ++<p class=return> ++The method returns the option <tt>value</tt> in case of ++success, or ++<b><tt>nil</tt></b> followed by an error message otherwise. ++</p> ++ + <!-- getpeername +++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class="name" id="getpeername"> +@@ -142,10 +109,10 @@ associated with a connected UDP object. + + + <p class=return> +-Returns a string with the IP address of the peer, the +-port number that peer is using for the connection, +-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). +-In case of error, the method returns <b><tt>nil</tt></b>. ++Returns a string with the IP address of the peer, the ++port number that peer is using for the connection, ++and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). ++In case of error, the method returns <b><tt>nil</tt></b>. + </p> + + <p class="note"> +@@ -165,9 +132,9 @@ Returns the local address information associated to the object. + + + <p class=return> +-The method returns a string with local IP address, a number with +-the local port, +-and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). ++The method returns a string with local IP address, a number with ++the local port, ++and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>"). + In case of error, the method returns <b><tt>nil</tt></b>. + </p> + +@@ -179,6 +146,18 @@ first time (in which case it is bound to an ephemeral port and the + wild-card address). + </p> + ++<!-- gettimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class=name id="gettimeout"> ++connected:<b>settimeout(</b>value<b>)</b><br> ++unconnected:<b>settimeout(</b>value<b>)</b> ++</p> ++ ++<p class=description> ++Returns the current timeout value. ++</p> ++ ++ + <!-- receive +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class="name" id="receive"> +@@ -199,9 +178,12 @@ specifies the maximum size of the datagram to be retrieved. If + there are more than <tt>size</tt> bytes available in the datagram, + the excess bytes are discarded. If there are less then + <tt>size</tt> bytes available in the current datagram, the +-available bytes are returned. If <tt>size</tt> is omitted, the +-maximum datagram size is used (which is currently limited by the +-implementation to 8192 bytes). ++available bytes are returned. ++If <tt>size</tt> is omitted, the ++compile-time constant <a ++href=socket.html#datagramsize><tt>socket._DATAGRAMSIZE</tt></a> is used ++(it defaults to 8192 bytes). Larger sizes will cause a ++temporary buffer to be allocated for the operation. + </p> + + <p class="return"> +@@ -217,46 +199,12 @@ unconnected:<b>receivefrom(</b>[size]<b>)</b> + </p> + + <p class="description"> +-Works exactly as the <a href="#receive"><tt>receive</tt></a> ++Works exactly as the <a href="#receive"><tt>receive</tt></a> + method, except it returns the IP + address and port as extra return values (and is therefore slightly less + efficient). + </p> + +-<!-- getoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class="name" id="getoption"> +-connected:<b>getoption()</b><br> +-unconnected:<b>getoption()</b> +-</p> +- +-<p class="description"> +-Gets an option value from the UDP object. +-See <a href=#setoption><tt>setoption</tt></a> for +-description of the option names and values. +-</p> +- +-<p class="parameters"><tt>Option</tt> is a string with the option name. +-<ul> +-<li> '<tt>dontroute</tt>' +-<li> '<tt>broadcast</tt>' +-<li> '<tt>reuseaddr</tt>' +-<li> '<tt>reuseport</tt>' +-<li> '<tt>ip-multicast-loop</tt>' +-<li> '<tt>ipv6-v6only</tt>' +-<li> '<tt>ip-multicast-if</tt>' +-<li> '<tt>ip-multicast-ttl</tt>' +-<li> '<tt>ip-add-membership</tt>' +-<li> '<tt>ip-drop-membership</tt>' +-</ul> +-</p> +- +-<p class=return> +-The method returns the option <tt>value</tt> in case of +-success, or +-<b><tt>nil</tt></b> followed by an error message otherwise. +-</p> +- + <!-- send ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class="name" id="send"> +@@ -268,7 +216,7 @@ Sends a datagram to the UDP peer of a connected object. + </p> + + <p class="parameters"> +-<tt>Datagram</tt> is a string with the datagram contents. ++<tt>Datagram</tt> is a string with the datagram contents. + The maximum datagram size for UDP is 64K minus IP layer overhead. + However datagrams larger than the link layer packet size will be + fragmented, which may deteriorate performance and/or reliability. +@@ -298,11 +246,11 @@ Sends a datagram to the specified IP address and port number. + + <p class="parameters"> + <tt>Datagram</tt> is a string with the +-datagram contents. ++datagram contents. + The maximum datagram size for UDP is 64K minus IP layer overhead. + However datagrams larger than the link layer packet size will be + fragmented, which may deteriorate performance and/or reliability. +-<tt>Ip</tt> is the IP address of the recipient. ++<tt>Ip</tt> is the IP address of the recipient. + Host names are <em>not</em> allowed for performance reasons. + + <tt>Port</tt> is the port number at the recipient. +@@ -320,6 +268,75 @@ refuses to send a message to the specified address (i.e. no + interface accepts the address). + </p> + ++<!-- setoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class="name" id="setoption"> ++connected:<b>setoption(</b>option [, value]<b>)</b><br> ++unconnected:<b>setoption(</b>option [, value]<b>)</b> ++</p> ++ ++<p class="description"> ++Sets options for the UDP object. Options are ++only needed by low-level or time-critical applications. You should ++only modify an option if you are sure you need it.</p> ++<p class="parameters"><tt>Option</tt> is a string with the option ++name, and <tt>value</tt> depends on the option being set: ++</p> ++ ++<ul> ++<li> '<tt>dontroute</tt>': Indicates that outgoing ++messages should bypass the standard routing facilities. ++Receives a boolean value; ++<li> '<tt>broadcast</tt>': Requests permission to send ++broadcast datagrams on the socket. ++Receives a boolean value; ++<li> '<tt>reuseaddr</tt>': Indicates that the rules used in ++validating addresses supplied in a <tt>bind()</tt> call ++should allow reuse of local addresses. ++Receives a boolean value; ++<li> '<tt>reuseport</tt>': Allows completely duplicate ++bindings by multiple processes if they all set ++'<tt>reuseport</tt>' before binding the port. ++Receives a boolean value; ++<li> '<tt>ip-multicast-loop</tt>': ++Specifies whether or not a copy of an outgoing multicast ++datagram is delivered to the sending host as long as it is a ++member of the multicast group. ++Receives a boolean value; ++<li> '<tt>ipv6-v6only</tt>': ++Specifies whether to restrict <tt>inet6</tt> sockets to ++sending and receiving only IPv6 packets. ++Receive a boolean value; ++<li> '<tt>ip-multicast-if</tt>': ++Sets the interface over which outgoing multicast datagrams ++are sent. ++Receives an IP address; ++<li> '<tt>ip-multicast-ttl</tt>': ++Sets the Time To Live in the IP header for outgoing ++multicast datagrams. ++Receives a number; ++<li> '<tt>ip-add-membership</tt>': ++Joins the multicast group specified. ++Receives a table with fields ++<tt>multiaddr</tt> and <tt>interface</tt>, each containing an ++IP address; ++<li> '<tt>ip-drop-membership</tt>': Leaves the multicast ++group specified. ++Receives a table with fields ++<tt>multiaddr</tt> and <tt>interface</tt>, each containing an ++IP address. ++</ul> ++ ++<p class="return"> ++The method returns 1 in case of success, or ++<b><tt>nil</tt></b> followed by an error message otherwise. ++</p> ++ ++<p class=note> ++Note: The descriptions above come from the man pages. ++</p> ++ ++ + <!-- setpeername +++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class="name" id="setpeername"> +@@ -337,9 +354,9 @@ object or vice versa. + For connected objects, outgoing datagrams + will be sent to the specified peer, and datagrams received from + other peers will be discarded by the OS. Connected UDP objects must +-use the <a href="#send"><tt>send</tt></a> and +-<a href="#receive"><tt>receive</tt></a> methods instead of +-<a href="#sendto"><tt>sendto</tt></a> and ++use the <a href="#send"><tt>send</tt></a> and ++<a href="#receive"><tt>receive</tt></a> methods instead of ++<a href="#sendto"><tt>sendto</tt></a> and + <a href="#receivefrom"><tt>receivefrom</tt></a>. + </p> + +@@ -406,74 +423,6 @@ system or explicitly by <tt>setsockname</tt>, it cannot be + changed. + </p> + +-<!-- setoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> +- +-<p class="name" id="setoption"> +-connected:<b>setoption(</b>option [, value]<b>)</b><br> +-unconnected:<b>setoption(</b>option [, value]<b>)</b> +-</p> +- +-<p class="description"> +-Sets options for the UDP object. Options are +-only needed by low-level or time-critical applications. You should +-only modify an option if you are sure you need it.</p> +-<p class="parameters"><tt>Option</tt> is a string with the option +-name, and <tt>value</tt> depends on the option being set: +-</p> +- +-<ul> +-<li> '<tt>dontroute</tt>': Indicates that outgoing +-messages should bypass the standard routing facilities. +-Receives a boolean value; +-<li> '<tt>broadcast</tt>': Requests permission to send +-broadcast datagrams on the socket. +-Receives a boolean value; +-<li> '<tt>reuseaddr</tt>': Indicates that the rules used in +-validating addresses supplied in a <tt>bind()</tt> call +-should allow reuse of local addresses. +-Receives a boolean value; +-<li> '<tt>reuseport</tt>': Allows completely duplicate +-bindings by multiple processes if they all set +-'<tt>reuseport</tt>' before binding the port. +-Receives a boolean value; +-<li> '<tt>ip-multicast-loop</tt>': +-Specifies whether or not a copy of an outgoing multicast +-datagram is delivered to the sending host as long as it is a +-member of the multicast group. +-Receives a boolean value; +-<li> '<tt>ipv6-v6only</tt>': +-Specifies whether to restrict <tt>inet6</tt> sockets to +-sending and receiving only IPv6 packets. +-Receive a boolean value; +-<li> '<tt>ip-multicast-if</tt>': +-Sets the interface over which outgoing multicast datagrams +-are sent. +-Receives an IP address; +-<li> '<tt>ip-multicast-ttl</tt>': +-Sets the Time To Live in the IP header for outgoing +-multicast datagrams. +-Receives a number; +-<li> '<tt>ip-add-membership</tt>': +-Joins the multicast group specified. +-Receives a table with fields +-<tt>multiaddr</tt> and <tt>interface</tt>, each containing an +-IP address; +-<li> '<tt>ip-drop-membership</tt>': Leaves the multicast +-group specified. +-Receives a table with fields +-<tt>multiaddr</tt> and <tt>interface</tt>, each containing an +-IP address. +-</ul> +- +-<p class="return"> +-The method returns 1 in case of success, or +-<b><tt>nil</tt></b> followed by an error message otherwise. +-</p> +- +-<p class=note> +-Note: The descriptions above come from the man pages. +-</p> +- + <!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <p class="name" id="settimeout"> +@@ -482,14 +431,14 @@ unconnected:<b>settimeout(</b>value<b>)</b> + </p> + + <p class="description"> +-Changes the timeout values for the object. By default, the +-<a href="#receive"><tt>receive</tt></a> and +-<a href="#receivefrom"><tt>receivefrom</tt></a> ++Changes the timeout values for the object. By default, the ++<a href="#receive"><tt>receive</tt></a> and ++<a href="#receivefrom"><tt>receivefrom</tt></a> + operations are blocking. That is, any call to the methods will block + indefinitely, until data arrives. The <tt>settimeout</tt> function defines + a limit on the amount of time the functions can block. When a timeout is + set and the specified amount of time has elapsed, the affected methods +-give up and fail with an error code. ++give up and fail with an error code. + </p> + + <p class="parameters"> +@@ -514,6 +463,114 @@ all other method names already contained verbs making their + imperative nature obvious. + </p> + ++<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class="name" id="socket.udp"> ++socket.<b>udp()</b> ++</p> ++ ++<p class="description"> ++Creates and returns an unconnected UDP object. ++Unconnected objects support the ++<a href="#sendto"><tt>sendto</tt></a>, ++<a href="#receive"><tt>receive</tt></a>, ++<a href="#receivefrom"><tt>receivefrom</tt></a>, ++<a href="#getoption"><tt>getoption</tt></a>, ++<a href="#getsockname"><tt>getsockname</tt></a>, ++<a href="#setoption"><tt>setoption</tt></a>, ++<a href="#settimeout"><tt>settimeout</tt></a>, ++<a href="#setpeername"><tt>setpeername</tt></a>, ++<a href="#setsockname"><tt>setsockname</tt></a>, and ++<a href="#close"><tt>close</tt></a>. ++The <a href="#setpeername"><tt>setpeername</tt></a> ++is used to connect the object. ++</p> ++ ++<p class="return"> ++In case of success, a new unconnected UDP object ++returned. In case of error, <b><tt>nil</tt></b> is returned, followed by ++an error message. ++</p> ++ ++<p class=note> ++Note: The choice between IPv4 and IPv6 happens during a call to ++<a href=#sendto><tt>sendto</tt></a>, <a ++href=#setpeername><tt>setpeername</tt></a>, or <a ++href=#setsockname><tt>sockname</tt></a>, depending on the address ++family obtained from the resolver. ++</p> ++ ++<p class=note> ++Note: Before the choice between IPv4 and IPv6 happens, ++the internal socket object is invalid and therefore <a ++href=#setoption><tt>setoption</tt></a> will fail. ++</p> ++ ++<!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class="name" id="socket.udp"> ++socket.<b>udp4()</b> ++</p> ++ ++<p class="description"> ++Creates and returns an unconnected IPv4 UDP object. ++Unconnected objects support the ++<a href="#sendto"><tt>sendto</tt></a>, ++<a href="#receive"><tt>receive</tt></a>, ++<a href="#receivefrom"><tt>receivefrom</tt></a>, ++<a href="#getoption"><tt>getoption</tt></a>, ++<a href="#getsockname"><tt>getsockname</tt></a>, ++<a href="#setoption"><tt>setoption</tt></a>, ++<a href="#settimeout"><tt>settimeout</tt></a>, ++<a href="#setpeername"><tt>setpeername</tt></a>, ++<a href="#setsockname"><tt>setsockname</tt></a>, and ++<a href="#close"><tt>close</tt></a>. ++The <a href="#setpeername"><tt>setpeername</tt></a> ++is used to connect the object. ++</p> ++ ++<p class="return"> ++In case of success, a new unconnected UDP object ++returned. In case of error, <b><tt>nil</tt></b> is returned, followed by ++an error message. ++</p> ++ ++<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> ++ ++<p class="name" id="socket.udp6"> ++socket.<b>udp6()</b> ++</p> ++ ++<p class="description"> ++Creates and returns an unconnected IPv6 UDP object. ++Unconnected objects support the ++<a href="#sendto"><tt>sendto</tt></a>, ++<a href="#receive"><tt>receive</tt></a>, ++<a href="#receivefrom"><tt>receivefrom</tt></a>, ++<a href="#getoption"><tt>getoption</tt></a>, ++<a href="#getsockname"><tt>getsockname</tt></a>, ++<a href="#setoption"><tt>setoption</tt></a>, ++<a href="#settimeout"><tt>settimeout</tt></a>, ++<a href="#setpeername"><tt>setpeername</tt></a>, ++<a href="#setsockname"><tt>setsockname</tt></a>, and ++<a href="#close"><tt>close</tt></a>. ++The <a href="#setpeername"><tt>setpeername</tt></a> ++is used to connect the object. ++</p> ++ ++<p class="return"> ++In case of success, a new unconnected UDP object ++returned. In case of error, <b><tt>nil</tt></b> is returned, followed by ++an error message. ++</p> ++ ++<p class=note> ++Note: The TCP object returned will have the option ++"<tt>ipv6-v6only</tt>" set to <tt><b>true</b></tt>. ++</p> ++ ++ ++ + <!-- footer ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> + + <div class=footer> +@@ -524,7 +581,7 @@ imperative nature obvious. + <a href="index.html#download">download</a> · + <a href="installation.html">installation</a> · + <a href="introduction.html">introduction</a> · +-<a href="reference.html">reference</a> ++<a href="reference.html">reference</a> + </p> + <p> + <small> +diff --git a/etc/dispatch.lua b/etc/dispatch.lua +index cab7f59..2485415 100644 +--- a/etc/dispatch.lua ++++ b/etc/dispatch.lua +@@ -5,6 +5,7 @@ + ----------------------------------------------------------------------------- + local base = _G + local table = require("table") ++local string = require("string") + local socket = require("socket") + local coroutine = require("coroutine") + module("dispatch") +@@ -43,26 +44,32 @@ end + ----------------------------------------------------------------------------- + -- Mega hack. Don't try to do this at home. + ----------------------------------------------------------------------------- +--- we can't yield across calls to protect, so we rewrite it with coxpcall ++-- we can't yield across calls to protect on Lua 5.1, so we rewrite it with ++-- coroutines + -- make sure you don't require any module that uses socket.protect before + -- loading our hack +-function socket.protect(f) +- return function(...) +- local co = coroutine.create(f) +- while true do +- local results = {coroutine.resume(co, ...)} +- local status = table.remove(results, 1) +- if not status then +- if base.type(results[1]) == 'table' then +- return nil, results[1][1] +- else base.error(results[1]) end +- end +- if coroutine.status(co) == "suspended" then +- arg = {coroutine.yield(base.unpack(results))} ++if string.sub(base._VERSION, -3) == "5.1" then ++ local function _protect(co, status, ...) ++ if not status then ++ local msg = ... ++ if base.type(msg) == 'table' then ++ return nil, msg[1] + else +- return base.unpack(results) ++ base.error(msg, 0) + end + end ++ if coroutine.status(co) == "suspended" then ++ return _protect(co, coroutine.resume(co, coroutine.yield(...))) ++ else ++ return ... ++ end ++ end ++ ++ function socket.protect(f) ++ return function(...) ++ local co = coroutine.create(f) ++ return _protect(co, coroutine.resume(co, ...)) ++ end + end + end + +diff --git a/linux.cmd b/linux.cmd +index bd59adc..6c6636b 100644 +--- a/linux.cmd ++++ b/linux.cmd +@@ -1 +1 @@ +-make PLAT=linux DEBUG=DEBUG LUAINC_linux_base=/home/diego/build/linux/include LUAPREFIX_linux=/home/diego/build/linux ++make PLAT=linux DEBUG=DEBUG LUAINC_linux_base=/home/diego/build/ubuntu/include LUAPREFIX_linux=/home/diego/build/ubuntu +diff --git a/luasocket-scm-0.rockspec b/luasocket-scm-0.rockspec +index f86567b..352a497 100644 +--- a/luasocket-scm-0.rockspec ++++ b/luasocket-scm-0.rockspec +@@ -50,13 +50,12 @@ local function make_plat(plat) + } + local modules = { + ["socket.core"] = { +- sources = { "src/luasocket.c", "src/timeout.c", "src/buffer.c", "src/io.c", "src/auxiliar.c", +- "src/options.c", "src/inet.c", "src/except.c", "src/select.c", "src/tcp.c", "src/udp.c" }, ++ sources = { "src/luasocket.c", "src/timeout.c", "src/buffer.c", "src/io.c", "src/auxiliar.c", "src/options.c", "src/inet.c", "src/except.c", "src/select.c", "src/tcp.c", "src/udp.c", "src/compat.c" }, + defines = defines[plat], + incdir = "/src" + }, +- ["mime.core"] = { +- sources = { "src/mime.c" }, ++ ["mime.core"] = { ++ sources = { "src/mime.c", "src/compat.c" }, + defines = defines[plat], + incdir = "/src" + }, +@@ -73,14 +72,12 @@ local function make_plat(plat) + if plat == "unix" or plat == "macosx" then + modules["socket.core"].sources[#modules["socket.core"].sources+1] = "src/usocket.c" + modules["socket.unix"] = { +- sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", +- "src/usocket.c", "src/unix.c" }, ++ sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", "src/usocket.c", "src/unix.c" }, + defines = defines[plat], + incdir = "/src" + } + modules["socket.serial"] = { +- sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", +- "src/io.c", "src/usocket.c", "src/serial.c" }, ++ sources = { "src/buffer.c", "src/auxiliar.c", "src/options.c", "src/timeout.c", "src/io.c", "src/usocket.c", "src/serial.c" }, + defines = defines[plat], + incdir = "/src" + } +diff --git a/makefile b/makefile +index 04cd894..cc15b4e 100644 +--- a/makefile ++++ b/makefile +@@ -5,12 +5,12 @@ + # Targets: + # install install system independent support + # install-unix also install unix-only support +-# install-both install for both lua5.1 and lua5.2 +-# install-both-unix also install unix-only ++# install-both install for lua51 lua52 lua53 ++# install-both-unix also install unix-only + # print print the build settings + + PLAT?= linux +-PLATS= macosx linux win32 mingw ++PLATS= macosx linux win32 mingw freebsd solaris + + all: $(PLAT) + +@@ -24,20 +24,26 @@ test: + lua test/hello.lua + + install-both: +- $(MAKE) clean ++ $(MAKE) clean + @cd src; $(MAKE) $(PLAT) LUAV=5.1 + @cd src; $(MAKE) install LUAV=5.1 +- $(MAKE) clean ++ $(MAKE) clean + @cd src; $(MAKE) $(PLAT) LUAV=5.2 + @cd src; $(MAKE) install LUAV=5.2 ++ $(MAKE) clean ++ @cd src; $(MAKE) $(PLAT) LUAV=5.3 ++ @cd src; $(MAKE) install LUAV=5.3 + + install-both-unix: +- $(MAKE) clean ++ $(MAKE) clean + @cd src; $(MAKE) $(PLAT) LUAV=5.1 + @cd src; $(MAKE) install-unix LUAV=5.1 +- $(MAKE) clean ++ $(MAKE) clean + @cd src; $(MAKE) $(PLAT) LUAV=5.2 + @cd src; $(MAKE) install-unix LUAV=5.2 ++ $(MAKE) clean ++ @cd src; $(MAKE) $(PLAT) LUAV=5.3 ++ @cd src; $(MAKE) install-unix LUAV=5.3 + + .PHONY: test + +diff --git a/src/auxiliar.c b/src/auxiliar.c +index de625e9..18fa8e4 100644 +--- a/src/auxiliar.c ++++ b/src/auxiliar.c +@@ -26,7 +26,7 @@ void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) { + luaL_newmetatable(L, classname); /* mt */ + /* create __index table to place methods */ + lua_pushstring(L, "__index"); /* mt,"__index" */ +- lua_newtable(L); /* mt,"__index",it */ ++ lua_newtable(L); /* mt,"__index",it */ + /* put class name into class metatable */ + lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ + lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ +@@ -84,7 +84,7 @@ int auxiliar_checkboolean(lua_State *L, int objidx) { + } + + /*-------------------------------------------------------------------------*\ +-* Return userdata pointer if object belongs to a given class, abort with ++* Return userdata pointer if object belongs to a given class, abort with + * error otherwise + \*-------------------------------------------------------------------------*/ + void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) { +@@ -98,7 +98,7 @@ void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) { + } + + /*-------------------------------------------------------------------------*\ +-* Return userdata pointer if object belongs to a given group, abort with ++* Return userdata pointer if object belongs to a given group, abort with + * error otherwise + \*-------------------------------------------------------------------------*/ + void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) { +@@ -121,7 +121,7 @@ void auxiliar_setclass(lua_State *L, const char *classname, int objidx) { + } + + /*-------------------------------------------------------------------------*\ +-* Get a userdata pointer if object belongs to a given group. Return NULL ++* Get a userdata pointer if object belongs to a given group. Return NULL + * otherwise + \*-------------------------------------------------------------------------*/ + void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { +@@ -139,7 +139,7 @@ void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { + } + + /*-------------------------------------------------------------------------*\ +-* Get a userdata pointer if object belongs to a given class. Return NULL ++* Get a userdata pointer if object belongs to a given class. Return NULL + * otherwise + \*-------------------------------------------------------------------------*/ + void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { +@@ -151,7 +151,7 @@ void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { + * Used to be part of lauxlib in Lua 5.1, was dropped from 5.2. + \*-------------------------------------------------------------------------*/ + int auxiliar_typeerror (lua_State *L, int narg, const char *tname) { +- const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, ++ const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, + luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); + } +diff --git a/src/auxiliar.h b/src/auxiliar.h +index ea99013..65511d4 100644 +--- a/src/auxiliar.h ++++ b/src/auxiliar.h +@@ -4,12 +4,12 @@ + * Auxiliar routines for class hierarchy manipulation + * LuaSocket toolkit (but completely independent of other LuaSocket modules) + * +-* A LuaSocket class is a name associated with Lua metatables. A LuaSocket +-* group is a name associated with a class. A class can belong to any number ++* A LuaSocket class is a name associated with Lua metatables. A LuaSocket ++* group is a name associated with a class. A class can belong to any number + * of groups. This module provides the functionality to: + * +-* - create new classes +-* - add classes to groups ++* - create new classes ++* - add classes to groups + * - set the class of objects + * - check if an object belongs to a given class or group + * - get the userdata associated to objects +@@ -26,11 +26,12 @@ + * "class" with the class name. + * + * The mapping from class name to the corresponding metatable and the +-* reverse mapping are done using lauxlib. ++* reverse mapping are done using lauxlib. + \*=========================================================================*/ + + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + int auxiliar_open(lua_State *L); + void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func); +diff --git a/src/buffer.c b/src/buffer.c +index 4ef4e8e..fff1634 100644 +--- a/src/buffer.c ++++ b/src/buffer.c +@@ -4,6 +4,7 @@ + \*=========================================================================*/ + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + #include "buffer.h" + +@@ -37,7 +38,7 @@ int buffer_open(lua_State *L) { + } + + /*-------------------------------------------------------------------------*\ +-* Initializes C structure ++* Initializes C structure + \*-------------------------------------------------------------------------*/ + void buffer_init(p_buffer buf, p_io io, p_timeout tm) { + buf->first = buf->last = 0; +@@ -61,8 +62,8 @@ int buffer_meth_getstats(lua_State *L, p_buffer buf) { + * object:setstats() interface + \*-------------------------------------------------------------------------*/ + int buffer_meth_setstats(lua_State *L, p_buffer buf) { +- buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); +- buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); ++ buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); ++ buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); + if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); + lua_pushnumber(L, 1); + return 1; +@@ -78,9 +79,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) { + const char *data = luaL_checklstring(L, 2, &size); + long start = (long) luaL_optnumber(L, 3, 1); + long end = (long) luaL_optnumber(L, 4, -1); +-#ifdef LUASOCKET_DEBUG +- p_timeout tm = timeout_markstart(buf->tm); +-#endif ++ timeout_markstart(buf->tm); + if (start < 0) start = (long) (size+start+1); + if (end < 0) end = (long) (size+end+1); + if (start < 1) start = (long) 1; +@@ -89,7 +88,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) { + /* check if there was an error */ + if (err != IO_DONE) { + lua_pushnil(L); +- lua_pushstring(L, buf->io->error(buf->io->ctx, err)); ++ lua_pushstring(L, buf->io->error(buf->io->ctx, err)); + lua_pushnumber(L, (lua_Number) (sent+start-1)); + } else { + lua_pushnumber(L, (lua_Number) (sent+start-1)); +@@ -98,7 +97,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) { + } + #ifdef LUASOCKET_DEBUG + /* push time elapsed during operation as the last return value */ +- lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm)); ++ lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); + #endif + return lua_gettop(L) - top; + } +@@ -111,10 +110,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) { + luaL_Buffer b; + size_t size; + const char *part = luaL_optlstring(L, 3, "", &size); +-#ifdef LUASOCKET_DEBUG +- p_timeout tm = timeout_markstart(buf->tm); +-#endif +- /* initialize buffer with optional extra prefix ++ timeout_markstart(buf->tm); ++ /* initialize buffer with optional extra prefix + * (useful for concatenating previous partial results) */ + luaL_buffinit(L, &b); + luaL_addlstring(&b, part, size); +@@ -122,12 +119,12 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) { + if (!lua_isnumber(L, 2)) { + const char *p= luaL_optstring(L, 2, "*l"); + if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); +- else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); ++ else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); + else luaL_argcheck(L, 0, 2, "invalid receive pattern"); +- /* get a fixed number of bytes (minus what was already partially ++ /* get a fixed number of bytes (minus what was already partially + * received) */ + } else { +- double n = lua_tonumber(L, 2); ++ double n = lua_tonumber(L, 2); + size_t wanted = (size_t) n; + luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); + if (size == 0 || wanted > size) +@@ -138,8 +135,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) { + /* we can't push anyting in the stack before pushing the + * contents of the buffer. this is the reason for the complication */ + luaL_pushresult(&b); +- lua_pushstring(L, buf->io->error(buf->io->ctx, err)); +- lua_pushvalue(L, -2); ++ lua_pushstring(L, buf->io->error(buf->io->ctx, err)); ++ lua_pushvalue(L, -2); + lua_pushnil(L); + lua_replace(L, -4); + } else { +@@ -149,7 +146,7 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) { + } + #ifdef LUASOCKET_DEBUG + /* push time elapsed during operation as the last return value */ +- lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm)); ++ lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); + #endif + return lua_gettop(L) - top; + } +@@ -222,7 +219,7 @@ static int recvall(p_buffer buf, luaL_Buffer *b) { + } + + /*-------------------------------------------------------------------------*\ +-* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF ++* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF + * are not returned by the function and are discarded from the buffer + \*-------------------------------------------------------------------------*/ + static int recvline(p_buffer buf, luaL_Buffer *b) { +@@ -252,7 +249,7 @@ static int recvline(p_buffer buf, luaL_Buffer *b) { + static void buffer_skip(p_buffer buf, size_t count) { + buf->received += count; + buf->first += count; +- if (buffer_isempty(buf)) ++ if (buffer_isempty(buf)) + buf->first = buf->last = 0; + } + +diff --git a/src/compat.c b/src/compat.c +new file mode 100644 +index 0000000..c2d99cb +--- /dev/null ++++ b/src/compat.c +@@ -0,0 +1,19 @@ ++#include "compat.h" ++ ++#if LUA_VERSION_NUM==501 ++/* ++** Adapted from Lua 5.2 ++*/ ++void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { ++ luaL_checkstack(L, nup+1, "too many upvalues"); ++ for (; l->name != NULL; l++) { /* fill the table with given functions */ ++ int i; ++ lua_pushstring(L, l->name); ++ for (i = 0; i < nup; i++) /* copy upvalues to the top */ ++ lua_pushvalue(L, -(nup+1)); ++ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ ++ lua_settable(L, -(nup + 3)); ++ } ++ lua_pop(L, nup); /* remove upvalues */ ++} ++#endif +diff --git a/src/compat.h b/src/compat.h +new file mode 100644 +index 0000000..7bf8010 +--- /dev/null ++++ b/src/compat.h +@@ -0,0 +1,11 @@ ++#ifndef COMPAT_H ++#define COMPAT_H ++ ++#include "lua.h" ++#include "lauxlib.h" ++ ++#if LUA_VERSION_NUM==501 ++void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); ++#endif ++ ++#endif +diff --git a/src/except.c b/src/except.c +index 002e701..60b5005 100644 +--- a/src/except.c ++++ b/src/except.c +@@ -6,9 +6,19 @@ + + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + #include "except.h" + ++#if LUA_VERSION_NUM < 502 ++#define lua_pcallk(L, na, nr, err, ctx, cont) \ ++ (((void)ctx),((void)cont),lua_pcall(L, na, nr, err)) ++#endif ++ ++#if LUA_VERSION_NUM < 503 ++typedef int lua_KContext; ++#endif ++ + /*=========================================================================*\ + * Internal function prototypes. + \*=========================================================================*/ +@@ -29,18 +39,17 @@ static luaL_Reg func[] = { + * Try factory + \*-------------------------------------------------------------------------*/ + static void wrap(lua_State *L) { +- lua_newtable(L); +- lua_pushnumber(L, 1); +- lua_pushvalue(L, -3); +- lua_settable(L, -3); +- lua_insert(L, -2); +- lua_pop(L, 1); ++ lua_createtable(L, 1, 0); ++ lua_pushvalue(L, -2); ++ lua_rawseti(L, -2, 1); ++ lua_pushvalue(L, lua_upvalueindex(1)); ++ lua_setmetatable(L, -2); + } + + static int finalize(lua_State *L) { + if (!lua_toboolean(L, 1)) { +- lua_pushvalue(L, lua_upvalueindex(1)); +- lua_pcall(L, 0, 0, 0); ++ lua_pushvalue(L, lua_upvalueindex(2)); ++ lua_call(L, 0, 0); + lua_settop(L, 2); + wrap(L); + lua_error(L); +@@ -48,15 +57,17 @@ static int finalize(lua_State *L) { + } else return lua_gettop(L); + } + +-static int do_nothing(lua_State *L) { ++static int do_nothing(lua_State *L) { + (void) L; +- return 0; ++ return 0; + } + + static int global_newtry(lua_State *L) { + lua_settop(L, 1); + if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); +- lua_pushcclosure(L, finalize, 1); ++ lua_pushvalue(L, lua_upvalueindex(1)); ++ lua_insert(L, -2); ++ lua_pushcclosure(L, finalize, 2); + return 1; + } + +@@ -64,27 +75,49 @@ static int global_newtry(lua_State *L) { + * Protect factory + \*-------------------------------------------------------------------------*/ + static int unwrap(lua_State *L) { +- if (lua_istable(L, -1)) { +- lua_pushnumber(L, 1); +- lua_gettable(L, -2); +- lua_pushnil(L); +- lua_insert(L, -2); +- return 1; +- } else return 0; ++ if (lua_istable(L, -1) && lua_getmetatable(L, -1)) { ++ int r = lua_rawequal(L, -1, lua_upvalueindex(1)); ++ lua_pop(L, 1); ++ if (r) { ++ lua_pushnil(L); ++ lua_rawgeti(L, -2, 1); ++ return 1; ++ } ++ } ++ return 0; + } + +-static int protected_(lua_State *L) { +- lua_pushvalue(L, lua_upvalueindex(1)); +- lua_insert(L, 1); +- if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) { ++static int protected_finish(lua_State *L, int status, lua_KContext ctx) { ++ (void)ctx; ++ if (status != 0 && status != LUA_YIELD) { + if (unwrap(L)) return 2; +- else lua_error(L); +- return 0; ++ else return lua_error(L); + } else return lua_gettop(L); + } + ++#if LUA_VERSION_NUM == 502 ++static int protected_cont(lua_State *L) { ++ int ctx = 0; ++ int status = lua_getctx(L, &ctx); ++ return protected_finish(L, status, ctx); ++} ++#else ++#define protected_cont protected_finish ++#endif ++ ++static int protected_(lua_State *L) { ++ int status; ++ lua_pushvalue(L, lua_upvalueindex(2)); ++ lua_insert(L, 1); ++ status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont); ++ return protected_finish(L, status, 0); ++} ++ + static int global_protect(lua_State *L) { +- lua_pushcclosure(L, protected_, 1); ++ lua_settop(L, 1); ++ lua_pushvalue(L, lua_upvalueindex(1)); ++ lua_insert(L, 1); ++ lua_pushcclosure(L, protected_, 2); + return 1; + } + +@@ -92,10 +125,9 @@ static int global_protect(lua_State *L) { + * Init module + \*-------------------------------------------------------------------------*/ + int except_open(lua_State *L) { +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) +- luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, NULL, func, 0); +-#endif ++ lua_newtable(L); /* metatable for wrapped exceptions */ ++ lua_pushboolean(L, 0); ++ lua_setfield(L, -2, "__metatable"); ++ luaL_setfuncs(L, func, 1); + return 0; + } +diff --git a/src/except.h b/src/except.h +index 1e7a245..2497c05 100644 +--- a/src/except.h ++++ b/src/except.h +@@ -9,21 +9,26 @@ + * error checking was taking a substantial amount of the coding. These + * function greatly simplify the task of checking errors. + * +-* The main idea is that functions should return nil as its first return +-* value when it finds an error, and return an error message (or value) ++* The main idea is that functions should return nil as their first return ++* values when they find an error, and return an error message (or value) + * following nil. In case of success, as long as the first value is not nil, + * the other values don't matter. + * + * The idea is to nest function calls with the "try" function. This function +-* checks the first value, and calls "error" on the second if the first is +-* nil. Otherwise, it returns all values it received. ++* checks the first value, and, if it's falsy, wraps the second value in a ++* table with metatable and calls "error" on it. Otherwise, it returns all ++* values it received. Basically, it works like the Lua "assert" function, ++* but it creates errors targeted specifically at "protect". + * +-* The protect function returns a new function that behaves exactly like the +-* function it receives, but the new function doesn't throw exceptions: it +-* returns nil followed by the error message instead. ++* The "newtry" function is a factory for "try" functions that call a ++* finalizer in protected mode before calling "error". + * +-* With these two function, it's easy to write functions that throw +-* exceptions on error, but that don't interrupt the user script. ++* The "protect" function returns a new function that behaves exactly like ++* the function it receives, but the new function catches exceptions thrown ++* by "try" functions and returns nil followed by the error message instead. ++* ++* With these three functions, it's easy to write functions that throw ++* exceptions on error, but that don't interrupt the user script. + \*=========================================================================*/ + + #include "lua.h" +diff --git a/src/ftp.lua b/src/ftp.lua +index ea1145b..e0c3cae 100644 +--- a/src/ftp.lua ++++ b/src/ftp.lua +@@ -268,11 +268,20 @@ _M.command = socket.protect(function(cmdt) + cmdt = override(cmdt) + socket.try(cmdt.host, "missing hostname") + socket.try(cmdt.command, "missing command") +- local f = open(cmdt.host, cmdt.port, cmdt.create) ++ local f = _M.open(cmdt.host, cmdt.port, cmdt.create) + f:greet() + f:login(cmdt.user, cmdt.password) +- f.try(f.tp:command(cmdt.command, cmdt.argument)) +- if cmdt.check then f.try(f.tp:check(cmdt.check)) end ++ if type(cmdt.command) == "table" then ++ local argument = cmdt.argument or {} ++ local check = cmdt.check or {} ++ for i,cmd in ipairs(cmdt.command) do ++ f.try(f.tp:command(cmd, argument[i])) ++ if check[i] then f.try(f.tp:check(check[i])) end ++ end ++ else ++ f.try(f.tp:command(cmdt.command, cmdt.argument)) ++ if cmdt.check then f.try(f.tp:check(cmdt.check)) end ++ end + f:quit() + return f:close() + end) +@@ -282,4 +291,4 @@ _M.get = socket.protect(function(gett) + else return tget(gett) end + end) + +-return _M +\ No newline at end of file ++return _M +diff --git a/src/http.lua b/src/http.lua +index ac4b2d6..d6bcc91 100644 +--- a/src/http.lua ++++ b/src/http.lua +@@ -22,12 +22,15 @@ local _M = socket.http + -- Program constants + ----------------------------------------------------------------------------- + -- connection timeout in seconds +-TIMEOUT = 60 +--- default port for document retrieval +-_M.PORT = 80 ++_M.TIMEOUT = 60 + -- user agent field sent in request + _M.USERAGENT = socket._VERSION + ++-- supported schemes ++local SCHEMES = { ["http"] = true } ++-- default port for document retrieval ++local PORT = 80 ++ + ----------------------------------------------------------------------------- + -- Reads MIME headers from a connection, unfolding where needed + ----------------------------------------------------------------------------- +@@ -114,7 +117,7 @@ function _M.open(host, port, create) + h.try = socket.newtry(function() h:close() end) + -- set timeout before connecting + h.try(c:settimeout(_M.TIMEOUT)) +- h.try(c:connect(host, port or _M.PORT)) ++ h.try(c:connect(host, port or PORT)) + -- here everything worked + return h + end +@@ -186,7 +189,7 @@ end + local function adjusturi(reqt) + local u = reqt + -- if there is a proxy, we need the full url. otherwise, just a part. +- if not reqt.proxy and not PROXY then ++ if not reqt.proxy and not _M.PROXY then + u = { + path = socket.try(reqt.path, "invalid path 'nil'"), + params = reqt.params, +@@ -198,7 +201,7 @@ local function adjusturi(reqt) + end + + local function adjustproxy(reqt) +- local proxy = reqt.proxy or PROXY ++ local proxy = reqt.proxy or _M.PROXY + if proxy then + proxy = url.parse(proxy) + return proxy.host, proxy.port or 3128 +@@ -209,17 +212,27 @@ end + + local function adjustheaders(reqt) + -- default headers ++ local host = string.gsub(reqt.authority, "^.-@", "") + local lower = { + ["user-agent"] = _M.USERAGENT, +- ["host"] = reqt.host, ++ ["host"] = host, + ["connection"] = "close, TE", + ["te"] = "trailers" + } + -- if we have authentication information, pass it along + if reqt.user and reqt.password then +- lower["authorization"] = ++ lower["authorization"] = + "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password)) + end ++ -- if we have proxy authentication information, pass it along ++ local proxy = reqt.proxy or _M.PROXY ++ if proxy then ++ proxy = url.parse(proxy) ++ if proxy.user and proxy.password then ++ lower["proxy-authorization"] = ++ "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password)) ++ end ++ end + -- override with user headers + for i,v in base.pairs(reqt.headers or lower) do + lower[string.lower(i)] = v +@@ -230,7 +243,7 @@ end + -- default url parts + local default = { + host = "", +- port = _M.PORT, ++ port = PORT, + path ="/", + scheme = "http" + } +@@ -240,22 +253,27 @@ local function adjustrequest(reqt) + local nreqt = reqt.url and url.parse(reqt.url, default) or {} + -- explicit components override url + for i,v in base.pairs(reqt) do nreqt[i] = v end +- if nreqt.port == "" then nreqt.port = 80 end +- socket.try(nreqt.host and nreqt.host ~= "", +- "invalid host '" .. base.tostring(nreqt.host) .. "'") ++ if nreqt.port == "" then nreqt.port = PORT end ++ if not (nreqt.host and nreqt.host ~= "") then ++ socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'") ++ end + -- compute uri if user hasn't overriden + nreqt.uri = reqt.uri or adjusturi(nreqt) +- -- ajust host and port if there is a proxy +- nreqt.host, nreqt.port = adjustproxy(nreqt) + -- adjust headers in request + nreqt.headers = adjustheaders(nreqt) ++ -- ajust host and port if there is a proxy ++ nreqt.host, nreqt.port = adjustproxy(nreqt) + return nreqt + end + + local function shouldredirect(reqt, code, headers) +- return headers.location and +- string.gsub(headers.location, "%s", "") ~= "" and +- (reqt.redirect ~= false) and ++ local location = headers.location ++ if not location then return false end ++ location = string.gsub(location, "%s", "") ++ if location == "" then return false end ++ local scheme = string.match(location, "^([%w][%w%+%-%.]*)%:") ++ if scheme and not SCHEMES[scheme] then return false end ++ return (reqt.redirect ~= false) and + (code == 301 or code == 302 or code == 303 or code == 307) and + (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") + and (not reqt.nredirects or reqt.nredirects < 5) +@@ -279,10 +297,10 @@ local trequest, tredirect + source = reqt.source, + sink = reqt.sink, + headers = reqt.headers, +- proxy = reqt.proxy, ++ proxy = reqt.proxy, + nredirects = (reqt.nredirects or 0) + 1, + create = reqt.create +- } ++ } + -- pass location header back as a hint we redirected + headers = headers or {} + headers.location = headers.location or location +@@ -299,7 +317,7 @@ end + h:sendheaders(nreqt.headers) + -- if there is a body, send it + if nreqt.source then +- h:sendbody(nreqt.headers, nreqt.source, nreqt.step) ++ h:sendbody(nreqt.headers, nreqt.source, nreqt.step) + end + local code, status = h:receivestatusline() + -- if it is an HTTP/0.9 server, simply get the body and we are done +@@ -309,13 +327,13 @@ end + end + local headers + -- ignore any 100-continue messages +- while code == 100 do ++ while code == 100 do + headers = h:receiveheaders() + code, status = h:receivestatusline() + end + headers = h:receiveheaders() + -- at this point we should have a honest reply from the server +- -- we can't redirect if we already used the source, so we report the error ++ -- we can't redirect if we already used the source, so we report the error + if shouldredirect(nreqt, code, headers) and not nreqt.source then + h:close() + return tredirect(reqt, headers.location) +@@ -351,4 +369,4 @@ _M.request = socket.protect(function(reqt, body) + else return trequest(reqt) end + end) + +-return _M +\ No newline at end of file ++return _M +diff --git a/src/inet.c b/src/inet.c +index 1a411f6..f4c8404 100644 +--- a/src/inet.c ++++ b/src/inet.c +@@ -8,6 +8,7 @@ + + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + #include "inet.h" + +@@ -41,11 +42,7 @@ int inet_open(lua_State *L) + { + lua_pushstring(L, "dns"); + lua_newtable(L); +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, NULL, func, 0); +-#endif + lua_settable(L, -3); + return 0; + } +@@ -97,7 +94,7 @@ static int inet_global_getnameinfo(lua_State *L) { + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; +- hints.ai_family = PF_UNSPEC; ++ hints.ai_family = AF_UNSPEC; + + ret = getaddrinfo(host, serv, &hints, &resolved); + if (ret != 0) { +@@ -108,8 +105,8 @@ static int inet_global_getnameinfo(lua_State *L) { + + lua_newtable(L); + for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) { +- getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, +- hbuf, host? (socklen_t) sizeof(hbuf): 0, ++ getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen, ++ hbuf, host? (socklen_t) sizeof(hbuf): 0, + sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0); + if (host) { + lua_pushnumber(L, i); +@@ -149,7 +146,7 @@ static int inet_global_toip(lua_State *L) + int inet_optfamily(lua_State* L, int narg, const char* def) + { + static const char* optname[] = { "unspec", "inet", "inet6", NULL }; +- static int optvalue[] = { PF_UNSPEC, PF_INET, PF_INET6, 0 }; ++ static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 }; + + return optvalue[luaL_checkoption(L, narg, def, optname)]; + } +@@ -170,7 +167,7 @@ static int inet_global_getaddrinfo(lua_State *L) + int i = 1, ret = 0; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; +- hints.ai_family = PF_UNSPEC; ++ hints.ai_family = AF_UNSPEC; + ret = getaddrinfo(hostname, NULL, &hints, &resolved); + if (ret != 0) { + lua_pushnil(L); +@@ -180,9 +177,10 @@ static int inet_global_getaddrinfo(lua_State *L) + lua_newtable(L); + for (iterator = resolved; iterator; iterator = iterator->ai_next) { + char hbuf[NI_MAXHOST]; +- ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, ++ ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, + hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); + if (ret){ ++ freeaddrinfo(resolved); + lua_pushnil(L); + lua_pushstring(L, socket_gaistrerror(ret)); + return 2; +@@ -200,6 +198,16 @@ static int inet_global_getaddrinfo(lua_State *L) + lua_pushliteral(L, "inet6"); + lua_settable(L, -3); + break; ++ case AF_UNSPEC: ++ lua_pushliteral(L, "family"); ++ lua_pushliteral(L, "unspec"); ++ lua_settable(L, -3); ++ break; ++ default: ++ lua_pushliteral(L, "family"); ++ lua_pushliteral(L, "unknown"); ++ lua_settable(L, -3); ++ break; + } + lua_pushliteral(L, "addr"); + lua_pushstring(L, hbuf); +@@ -256,12 +264,11 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) + } + lua_pushstring(L, name); + lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); +- if (family == PF_INET) { +- lua_pushliteral(L, "inet"); +- } else if (family == PF_INET6) { +- lua_pushliteral(L, "inet6"); +- } else { +- lua_pushliteral(L, "uknown family"); ++ switch (family) { ++ case AF_INET: lua_pushliteral(L, "inet"); break; ++ case AF_INET6: lua_pushliteral(L, "inet6"); break; ++ case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; ++ default: lua_pushliteral(L, "unknown"); break; + } + return 3; + } +@@ -281,7 +288,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) + lua_pushstring(L, socket_strerror(errno)); + return 2; + } +- err=getnameinfo((struct sockaddr *)&peer, peer_len, ++ err=getnameinfo((struct sockaddr *)&peer, peer_len, + name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV); + if (err) { + lua_pushnil(L); +@@ -290,12 +297,11 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) + } + lua_pushstring(L, name); + lua_pushstring(L, port); +- if (family == PF_INET) { +- lua_pushliteral(L, "inet"); +- } else if (family == PF_INET6) { +- lua_pushliteral(L, "inet6"); +- } else { +- lua_pushliteral(L, "uknown family"); ++ switch (family) { ++ case AF_INET: lua_pushliteral(L, "inet"); break; ++ case AF_INET6: lua_pushliteral(L, "inet6"); break; ++ case AF_UNSPEC: lua_pushliteral(L, "unspec"); break; ++ default: lua_pushliteral(L, "unknown"); break; + } + return 3; + } +@@ -346,8 +352,13 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp) + /*-------------------------------------------------------------------------*\ + * Tries to create a new inet socket + \*-------------------------------------------------------------------------*/ +-const char *inet_trycreate(p_socket ps, int family, int type) { +- return socket_strerror(socket_create(ps, family, type, 0)); ++const char *inet_trycreate(p_socket ps, int family, int type, int protocol) { ++ const char *err = socket_strerror(socket_create(ps, family, type, protocol)); ++ if (err == NULL && family == AF_INET6) { ++ int yes = 1; ++ setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes)); ++ } ++ return err; + } + + /*-------------------------------------------------------------------------*\ +@@ -356,21 +367,21 @@ const char *inet_trycreate(p_socket ps, int family, int type) { + const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) + { + switch (family) { +- case PF_INET: { ++ case AF_INET: { + struct sockaddr_in sin; + memset((char *) &sin, 0, sizeof(sin)); + sin.sin_family = AF_UNSPEC; + sin.sin_addr.s_addr = INADDR_ANY; +- return socket_strerror(socket_connect(ps, (SA *) &sin, ++ return socket_strerror(socket_connect(ps, (SA *) &sin, + sizeof(sin), tm)); + } +- case PF_INET6: { ++ case AF_INET6: { + struct sockaddr_in6 sin6; +- struct in6_addr addrany = IN6ADDR_ANY_INIT; ++ struct in6_addr addrany = IN6ADDR_ANY_INIT; + memset((char *) &sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_UNSPEC; + sin6.sin6_addr = addrany; +- return socket_strerror(socket_connect(ps, (SA *) &sin6, ++ return socket_strerror(socket_connect(ps, (SA *) &sin6, + sizeof(sin6), tm)); + } + } +@@ -385,6 +396,7 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address, + { + struct addrinfo *iterator = NULL, *resolved = NULL; + const char *err = NULL; ++ int current_family = *family; + /* try resolving */ + err = socket_gaistrerror(getaddrinfo(address, serv, + connecthints, &resolved)); +@@ -399,23 +411,23 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address, + * that shows up while iterating. if there was a + * bind, all families will be the same and we will + * not enter this branch. */ +- if (*family != iterator->ai_family) { ++ if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { + socket_destroy(ps); +- err = socket_strerror(socket_create(ps, iterator->ai_family, +- iterator->ai_socktype, iterator->ai_protocol)); +- if (err != NULL) { +- freeaddrinfo(resolved); +- return err; +- } +- *family = iterator->ai_family; +- /* all sockets initially non-blocking */ ++ err = inet_trycreate(ps, iterator->ai_family, ++ iterator->ai_socktype, iterator->ai_protocol); ++ if (err) continue; ++ current_family = iterator->ai_family; ++ /* set non-blocking before connect */ + socket_setnonblocking(ps); + } + /* try connecting to remote address */ +- err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, ++ err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, + (socklen_t) iterator->ai_addrlen, tm)); +- /* if success, break out of loop */ +- if (err == NULL) break; ++ /* if success or timeout is zero, break out of loop */ ++ if (err == NULL || timeout_iszero(tm)) { ++ *family = current_family; ++ break; ++ } + } + freeaddrinfo(resolved); + /* here, if err is set, we failed */ +@@ -425,29 +437,27 @@ const char *inet_tryconnect(p_socket ps, int *family, const char *address, + /*-------------------------------------------------------------------------*\ + * Tries to accept a socket + \*-------------------------------------------------------------------------*/ +-const char *inet_tryaccept(p_socket server, int family, p_socket client, +- p_timeout tm) +-{ ++const char *inet_tryaccept(p_socket server, int family, p_socket client, ++ p_timeout tm) { + socklen_t len; + t_sockaddr_storage addr; +- if (family == PF_INET6) { +- len = sizeof(struct sockaddr_in6); +- } else { +- len = sizeof(struct sockaddr_in); +- } +- return socket_strerror(socket_accept(server, client, (SA *) &addr, ++ switch (family) { ++ case AF_INET6: len = sizeof(struct sockaddr_in6); break; ++ case AF_INET: len = sizeof(struct sockaddr_in); break; ++ default: len = sizeof(addr); break; ++ } ++ return socket_strerror(socket_accept(server, client, (SA *) &addr, + &len, tm)); + } + + /*-------------------------------------------------------------------------*\ + * Tries to bind socket to (address, port) + \*-------------------------------------------------------------------------*/ +-const char *inet_trybind(p_socket ps, const char *address, const char *serv, +- struct addrinfo *bindhints) +-{ ++const char *inet_trybind(p_socket ps, int *family, const char *address, ++ const char *serv, struct addrinfo *bindhints) { + struct addrinfo *iterator = NULL, *resolved = NULL; + const char *err = NULL; +- t_socket sock = *ps; ++ int current_family = *family; + /* translate luasocket special values to C */ + if (strcmp(address, "*") == 0) address = NULL; + if (!serv) serv = "0"; +@@ -459,35 +469,32 @@ const char *inet_trybind(p_socket ps, const char *address, const char *serv, + } + /* iterate over resolved addresses until one is good */ + for (iterator = resolved; iterator; iterator = iterator->ai_next) { +- if(sock == SOCKET_INVALID) { +- err = socket_strerror(socket_create(&sock, iterator->ai_family, +- iterator->ai_socktype, iterator->ai_protocol)); +- if(err) +- continue; ++ if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) { ++ socket_destroy(ps); ++ err = inet_trycreate(ps, iterator->ai_family, ++ iterator->ai_socktype, iterator->ai_protocol); ++ if (err) continue; ++ current_family = iterator->ai_family; + } + /* try binding to local address */ +- err = socket_strerror(socket_bind(&sock, +- (SA *) iterator->ai_addr, ++ err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr, + (socklen_t) iterator->ai_addrlen)); +- + /* keep trying unless bind succeeded */ +- if (err) { +- if(sock != *ps) +- socket_destroy(&sock); +- } else { +- /* remember what we connected to, particularly the family */ +- *bindhints = *iterator; ++ if (err == NULL) { ++ *family = current_family; ++ /* set to non-blocking after bind */ ++ socket_setnonblocking(ps); + break; + } + } + /* cleanup and return error */ + freeaddrinfo(resolved); +- *ps = sock; ++ /* here, if err is set, we failed */ + return err; + } + + /*-------------------------------------------------------------------------*\ +-* Some systems do not provide these so that we provide our own. ++* Some systems do not provide these so that we provide our own. + \*-------------------------------------------------------------------------*/ + #ifdef LUASOCKET_INET_ATON + int inet_aton(const char *cp, struct in_addr *inp) +@@ -512,7 +519,7 @@ int inet_aton(const char *cp, struct in_addr *inp) + #endif + + #ifdef LUASOCKET_INET_PTON +-int inet_pton(int af, const char *src, void *dst) ++int inet_pton(int af, const char *src, void *dst) + { + struct addrinfo hints, *res; + int ret = 1; +@@ -529,7 +536,7 @@ int inet_pton(int af, const char *src, void *dst) + } else { + ret = -1; + } +- freeaddrinfo(res); ++ freeaddrinfo(res); + return ret; + } + +diff --git a/src/inet.h b/src/inet.h +index 1f1a96a..feb3541 100644 +--- a/src/inet.h ++++ b/src/inet.h +@@ -1,12 +1,12 @@ +-#ifndef INET_H +-#define INET_H ++#ifndef INET_H ++#define INET_H + /*=========================================================================*\ + * Internet domain functions + * LuaSocket toolkit + * + * This module implements the creation and connection of internet domain + * sockets, on top of the socket.h interface, and the interface of with the +-* resolver. ++* resolver. + * + * The function inet_aton is provided for the platforms where it is not + * available. The module also implements the interface of the internet +@@ -24,11 +24,11 @@ + + int inet_open(lua_State *L); + +-const char *inet_trycreate(p_socket ps, int family, int type); ++const char *inet_trycreate(p_socket ps, int family, int type, int protocol); + const char *inet_tryconnect(p_socket ps, int *family, const char *address, + const char *serv, p_timeout tm, struct addrinfo *connecthints); +-const char *inet_trybind(p_socket ps, const char *address, const char *serv, +- struct addrinfo *bindhints); ++const char *inet_trybind(p_socket ps, int *family, const char *address, ++ const char *serv, struct addrinfo *bindhints); + const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm); + const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm); + +diff --git a/src/io.c b/src/io.c +index 35f46f7..a4230ce 100644 +--- a/src/io.c ++++ b/src/io.c +@@ -25,6 +25,6 @@ const char *io_strerror(int err) { + case IO_DONE: return NULL; + case IO_CLOSED: return "closed"; + case IO_TIMEOUT: return "timeout"; +- default: return "unknown error"; ++ default: return "unknown error"; + } + } +diff --git a/src/io.h b/src/io.h +index 76a3e58..8cca08a 100644 +--- a/src/io.h ++++ b/src/io.h +@@ -22,7 +22,7 @@ enum { + IO_DONE = 0, /* operation completed successfully */ + IO_TIMEOUT = -1, /* operation timed out */ + IO_CLOSED = -2, /* the connection has been closed */ +- IO_UNKNOWN = -3 ++ IO_UNKNOWN = -3 + }; + + /* interface to error message function */ +diff --git a/src/ltn12.lua b/src/ltn12.lua +index 5b10f56..575c5a7 100644 +--- a/src/ltn12.lua ++++ b/src/ltn12.lua +@@ -9,6 +9,7 @@ + ----------------------------------------------------------------------------- + local string = require("string") + local table = require("table") ++local unpack = unpack or table.unpack + local base = _G + local _M = {} + if module then -- heuristic for exporting a global package table +@@ -21,6 +22,9 @@ _M.source = source + _M.sink = sink + _M.pump = pump + ++local unpack = unpack or table.unpack ++local select = base.select ++ + -- 2048 seems to be better in windows... + _M.BLOCKSIZE = 2048 + _M._VERSION = "LTN12 1.0.3" +@@ -42,7 +46,7 @@ end + -- (thanks to Wim Couwenberg) + function filter.chain(...) + local arg = {...} +- local n = select('#',...) ++ local n = base.select('#',...) + local top, index = 1, 1 + local retry = "" + return function(chunk) +@@ -139,7 +143,9 @@ function source.rewind(src) + end + end + +-function source.chain(src, f) ++-- chains a source with one or several filter(s) ++function source.chain(src, f, ...) ++ if ... then f=filter.chain(f, ...) end + base.assert(src and f) + local last_in, last_out = "", "" + local state = "feeding" +@@ -254,8 +260,13 @@ function sink.error(err) + end + end + +--- chains a sink with a filter +-function sink.chain(f, snk) ++-- chains a sink with one or several filter(s) ++function sink.chain(f, snk, ...) ++ if ... then ++ local args = { f, snk, ... } ++ snk = table.remove(args, #args) ++ f = filter.chain(unpack(args)) ++ end + base.assert(f and snk) + return function(chunk, err) + if chunk ~= "" then +diff --git a/src/luasocket.c b/src/luasocket.c +index e6ee747..7d9c802 100644 +--- a/src/luasocket.c ++++ b/src/luasocket.c +@@ -17,7 +17,7 @@ + \*=========================================================================*/ + #include "lua.h" + #include "lauxlib.h" +- ++#include "compat.h" + + /*=========================================================================*\ + * LuaSocket includes +@@ -64,7 +64,7 @@ static luaL_Reg func[] = { + * Skip a few arguments + \*-------------------------------------------------------------------------*/ + static int global_skip(lua_State *L) { +- int amount = luaL_checkint(L, 1); ++ int amount = luaL_checkinteger(L, 1); + int ret = lua_gettop(L) - amount - 1; + return ret >= 0 ? ret : 0; + } +@@ -78,26 +78,14 @@ static int global_unload(lua_State *L) { + return 0; + } + +-#if LUA_VERSION_NUM > 501 +-int luaL_typerror (lua_State *L, int narg, const char *tname) { +- const char *msg = lua_pushfstring(L, "%s expected, got %s", +- tname, luaL_typename(L, narg)); +- return luaL_argerror(L, narg, msg); +-} +-#endif +- + /*-------------------------------------------------------------------------*\ + * Setup basic stuff. + \*-------------------------------------------------------------------------*/ + static int base_open(lua_State *L) { + if (socket_open()) { + /* export functions (and leave namespace table on top of stack) */ +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + lua_newtable(L); + luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, "socket", func, 0); +-#endif + #ifdef LUASOCKET_DEBUG + lua_pushstring(L, "_DEBUG"); + lua_pushboolean(L, 1); +diff --git a/src/makefile b/src/makefile +index c24e61b..adf687f 100644 +--- a/src/makefile ++++ b/src/makefile +@@ -20,15 +20,17 @@ PLAT?=linux + # lua version to build against + LUAV?=5.1 + ++# MYCFLAGS: to be set by user if needed ++MYCFLAGS= ++ ++# MYLDFLAGS: to be set by user if needed ++MYLDFLAGS= ++ + # DEBUG: NODEBUG DEBUG + # debug mode causes luasocket to collect and returns timing information useful + # for testing and debugging luasocket itself + DEBUG?=NODEBUG + +-# COMPAT: COMPAT NOCOMPAT +-# when compiling for 5.2, use LUA_COMPAT_MODULE +-COMPAT?=NOCOMPAT +- + # where lua headers are found for macosx builds + # LUAINC_macosx: + # /opt/local/include +@@ -40,7 +42,6 @@ LUAPREFIX_macosx?=/opt/local + CDIR_macosx?=lib/lua/$(LUAV) + LDIR_macosx?=share/lua/$(LUAV) + +- + # LUAINC_linux: + # /usr/include/lua$(LUAV) + # /usr/local/include +@@ -52,8 +53,17 @@ LUAPREFIX_linux?=/usr/local + CDIR_linux?=lib/lua/$(LUAV) + LDIR_linux?=share/lua/$(LUAV) + ++# LUAINC_freebsd: ++# /usr/local/include/lua$(LUAV) ++# where lua headers are found for freebsd builds ++LUAINC_freebsd_base?=/usr/local/include/ ++LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua$(LUAV) ++LUAPREFIX_freebsd?=/usr/local/ ++CDIR_freebsd?=lib/lua/$(LUAV) ++LDIR_freebsd?=share/lua/$(LUAV) ++ + # where lua headers are found for mingw builds +-# LUAINC_mingw: ++# LUAINC_mingw: + # /opt/local/include + LUAINC_mingw_base?=/usr/include + LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV) +@@ -67,13 +77,21 @@ LDIR_mingw?=lua/$(LUAV)/lua + # LUAINC_win32: + # LUALIB_win32: + # where lua headers and libraries are found for win32 builds +-LUAINC_win32_base?= +-LUAINC_win32?=$(LUAINC_win32_base)/lua/$(LUAV) +-PLATFORM_win32?=Release + LUAPREFIX_win32?= +-CDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32) +-LDIR_win32?=lua/$(LUAV)/$(PLATFORM_win32)/lua +-LUALIB_win32?=$(LUAPREFIX_win32)/lua/$(LUAV)/$(PLATFORM_win32) ++LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV) ++PLATFORM_win32?=Release ++CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32) ++LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua ++LUALIB_win32?=$(LUAPREFIX_win32)/lib/lua/$(LUAV)/$(PLATFORM_win32) ++LUALIBNAME_win32?=lua$(subst .,,$(LUAV)).lib ++ ++ ++# LUAINC_solaris: ++LUAINC_solaris_base?=/usr/include ++LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV) ++LUAPREFIX_solaris?=/usr/local ++CDIR_solaris?=lib/lua/$(LUAV) ++LDIR_solaris?=share/lua/$(LUAV) + + # prefix: /usr/local /usr /opt/local /sw + # the top of the default install tree +@@ -121,7 +139,7 @@ print: + #------ + # Supported platforms + # +-PLATS= macosx linux win32 mingw ++PLATS= macosx linux win32 mingw solaris + + #------ + # Compiler and linker settings +@@ -129,11 +147,11 @@ PLATS= macosx linux win32 mingw + SO_macosx=so + O_macosx=o + CC_macosx=gcc +-DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN -DLUA_$(COMPAT)_MODULE \ ++DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN \ + -DLUASOCKET_API='__attribute__((visibility("default")))' \ + -DUNIX_API='__attribute__((visibility("default")))' \ + -DMIME_API='__attribute__((visibility("default")))' +-CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ ++CFLAGS_macosx= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \ + -fvisibility=hidden + LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o + LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc +@@ -145,11 +163,11 @@ SOCKET_macosx=usocket.o + SO_linux=so + O_linux=o + CC_linux=gcc +-DEF_linux=-DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \ ++DEF_linux=-DLUASOCKET_$(DEBUG) \ + -DLUASOCKET_API='__attribute__((visibility("default")))' \ + -DUNIX_API='__attribute__((visibility("default")))' \ + -DMIME_API='__attribute__((visibility("default")))' +-CFLAGS_linux= -I$(LUAINC) $(DEF) -pedantic -Wall -Wshadow -Wextra \ ++CFLAGS_linux= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ + -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden + LDFLAGS_linux=-O -shared -fpic -o + LD_linux=gcc +@@ -157,14 +175,46 @@ SOCKET_linux=usocket.o + + #------ + # Compiler and linker settings ++# for FreeBSD ++SO_freebsd=so ++O_freebsd=o ++CC_freebsd=gcc ++DEF_freebsd=-DLUASOCKET_$(DEBUG) \ ++ -DLUASOCKET_API='__attribute__((visibility("default")))' \ ++ -DUNIX_API='__attribute__((visibility("default")))' \ ++ -DMIME_API='__attribute__((visibility("default")))' ++CFLAGS_freebsd= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ ++ -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden ++LDFLAGS_freebsd=-O -shared -fpic -o ++LD_freebsd=gcc ++SOCKET_freebsd=usocket.o ++ ++#------ ++# Compiler and linker settings ++# for Solaris ++SO_solaris=so ++O_solaris=o ++CC_solaris=gcc ++DEF_solaris=-DLUASOCKET_$(DEBUG) \ ++ -DLUASOCKET_API='__attribute__((visibility("default")))' \ ++ -DUNIX_API='__attribute__((visibility("default")))' \ ++ -DMIME_API='__attribute__((visibility("default")))' ++CFLAGS_solaris=-I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ ++ -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden ++LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o ++LD_solaris=gcc ++SOCKET_solaris=usocket.o ++ ++#------ ++# Compiler and linker settings + # for MingW + SO_mingw=dll + O_mingw=o + CC_mingw=gcc +-DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) -DLUA_$(COMPAT)_MODULE \ ++DEF_mingw= -DLUASOCKET_INET_PTON -DLUASOCKET_$(DEBUG) \ + -DWINVER=0x0501 -DLUASOCKET_API='__declspec(dllexport)' \ + -DMIME_API='__declspec(dllexport)' +-CFLAGS_mingw= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ ++CFLAGS_mingw= -I$(LUAINC) $(DEF) -Wall -O2 -fno-common \ + -fvisibility=hidden + LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o + LD_mingw=gcc +@@ -179,8 +229,7 @@ O_win32=obj + CC_win32=cl + DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \ + //D "LUASOCKET_API=__declspec(dllexport)" //D "_CRT_SECURE_NO_WARNINGS" \ +- //D "_WINDLL" //D "LUA_$(COMPAT)_MODULE" \ +- //D "MIME_API=__declspec(dllexport)" \ ++ //D "_WINDLL" //D "MIME_API=__declspec(dllexport)" \ + //D "LUASOCKET_$(DEBUG)" + CFLAGS_win32=//I "$(LUAINC)" $(DEF) //O2 //Ot //MD //W3 //nologo + LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ +@@ -188,7 +237,7 @@ LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ + //MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ + //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \ + //MACHINE:X86 /LIBPATH:"$(shell cmd //c echo $(LUALIB))" \ +- lua$(subst .,,$(LUAV)).lib ws2_32.lib //OUT: ++ $(LUALIBNAME_win32) ws2_32.lib //OUT: + LD_win32=cl + SOCKET_win32=wsocket.obj + +@@ -204,8 +253,8 @@ SO=$(SO_$(PLAT)) + O=$(O_$(PLAT)) + SOCKET_V=3.0-rc1 + MIME_V=1.0.3 +-SOCKET_SO=socket.$(SO).$(SOCKET_V) +-MIME_SO=mime.$(SO).$(MIME_V) ++SOCKET_SO=socket-$(SOCKET_V).$(SO) ++MIME_SO=mime-$(MIME_V).$(SO) + UNIX_SO=unix.$(SO) + SERIAL_SO=serial.$(SO) + SOCKET=$(SOCKET_$(PLAT)) +@@ -215,8 +264,8 @@ SOCKET=$(SOCKET_$(PLAT)) + # + CC=$(CC_$(PLAT)) + DEF=$(DEF_$(PLAT)) +-CFLAGS=$(CFLAGS_$(PLAT)) +-LDFLAGS=$(LDFLAGS_$(PLAT)) ++CFLAGS=$(MYCFLAGS) $(CFLAGS_$(PLAT)) ++LDFLAGS=$(MYLDFLAGS) $(LDFLAGS_$(PLAT)) + LD=$(LD_$(PLAT)) + LUAINC= $(LUAINC_$(PLAT)) + LUALIB= $(LUALIB_$(PLAT)) +@@ -230,6 +279,7 @@ SOCKET_OBJS= \ + buffer.$(O) \ + io.$(O) \ + auxiliar.$(O) \ ++ compat.$(O) \ + options.$(O) \ + inet.$(O) \ + $(SOCKET) \ +@@ -242,7 +292,8 @@ SOCKET_OBJS= \ + # Modules belonging mime-core + # + MIME_OBJS= \ +- mime.$(O) ++ mime.$(O) \ ++ compat.$(O) + + #------ + # Modules belonging unix (local domain sockets) +@@ -259,7 +310,7 @@ UNIX_OBJS=\ + #------ + # Modules belonging to serial (device streams) + # +-SERIAL_OBJS:=\ ++SERIAL_OBJS=\ + buffer.$(O) \ + auxiliar.$(O) \ + options.$(O) \ +@@ -289,6 +340,10 @@ TO_TOP_LDIR= \ + # + default: $(PLAT) + ++ ++freebsd: ++ $(MAKE) all-unix PLAT=freebsd ++ + macosx: + $(MAKE) all-unix PLAT=macosx + +@@ -300,6 +355,9 @@ linux: + + mingw: + $(MAKE) all PLAT=mingw ++ ++solaris: ++ $(MAKE) all-unix PLAT=solaris + + none: + @echo "Please run" +@@ -349,6 +407,7 @@ clean: + #------ + # List of dependencies + # ++compat.$(O): compat.c compat.h + auxiliar.$(O): auxiliar.c auxiliar.h + buffer.$(O): buffer.c buffer.h io.h timeout.h + except.$(O): except.c except.h +diff --git a/src/mbox.lua b/src/mbox.lua +index 7724ae2..ed9e781 100644 +--- a/src/mbox.lua ++++ b/src/mbox.lua +@@ -61,7 +61,7 @@ function _M.parse_from(from) + end + + function _M.split_mbox(mbox_s) +- mbox = {} ++ local mbox = {} + mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" + local nj, i, j = 1, 1, 1 + while 1 do +diff --git a/src/mime.c b/src/mime.c +index dd37dcf..ed44104 100644 +--- a/src/mime.c ++++ b/src/mime.c +@@ -6,10 +6,7 @@ + + #include "lua.h" + #include "lauxlib.h" +- +-#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501) +-#include "compat-5.1.h" +-#endif ++#include "compat.h" + + #include "mime.h" + +@@ -41,7 +38,7 @@ static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer); + static void qpsetup(UC *class, UC *unbase); + static void qpquote(UC c, luaL_Buffer *buffer); + static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer); +-static size_t qpencode(UC c, UC *input, size_t size, ++static size_t qpencode(UC c, UC *input, size_t size, + const char *marker, luaL_Buffer *buffer); + static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer); + +@@ -81,12 +78,8 @@ static UC b64unbase[256]; + \*-------------------------------------------------------------------------*/ + MIME_API int luaopen_mime_core(lua_State *L) + { +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + lua_newtable(L); + luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, "mime", func, 0); +-#endif + /* make version string available to scripts */ + lua_pushstring(L, "_VERSION"); + lua_pushstring(L, MIME_VERSION); +@@ -103,15 +96,15 @@ MIME_API int luaopen_mime_core(lua_State *L) + /*-------------------------------------------------------------------------*\ + * Incrementaly breaks a string into lines. The string can have CRLF breaks. + * A, n = wrp(l, B, length) +-* A is a copy of B, broken into lines of at most 'length' bytes. +-* 'l' is how many bytes are left for the first line of B. +-* 'n' is the number of bytes left in the last line of A. ++* A is a copy of B, broken into lines of at most 'length' bytes. ++* 'l' is how many bytes are left for the first line of B. ++* 'n' is the number of bytes left in the last line of A. + \*-------------------------------------------------------------------------*/ + static int mime_global_wrp(lua_State *L) + { + size_t size = 0; + int left = (int) luaL_checknumber(L, 1); +- const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size); ++ const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size); + const UC *last = input + size; + int length = (int) luaL_optnumber(L, 3, 76); + luaL_Buffer buffer; +@@ -123,7 +116,7 @@ static int mime_global_wrp(lua_State *L) + else lua_pushnil(L); + lua_pushnumber(L, length); + return 2; +- } ++ } + luaL_buffinit(L, &buffer); + while (input < last) { + switch (*input) { +@@ -150,9 +143,9 @@ static int mime_global_wrp(lua_State *L) + } + + /*-------------------------------------------------------------------------*\ +-* Fill base64 decode map. ++* Fill base64 decode map. + \*-------------------------------------------------------------------------*/ +-static void b64setup(UC *unbase) ++static void b64setup(UC *unbase) + { + int i; + for (i = 0; i <= 255; i++) unbase[i] = (UC) 255; +@@ -161,11 +154,11 @@ static void b64setup(UC *unbase) + } + + /*-------------------------------------------------------------------------*\ +-* Acumulates bytes in input buffer until 3 bytes are available. ++* Acumulates bytes in input buffer until 3 bytes are available. + * Translate the 3 bytes into Base64 form and append to buffer. + * Returns new number of bytes in buffer. + \*-------------------------------------------------------------------------*/ +-static size_t b64encode(UC c, UC *input, size_t size, ++static size_t b64encode(UC c, UC *input, size_t size, + luaL_Buffer *buffer) + { + input[size++] = c; +@@ -174,7 +167,7 @@ static size_t b64encode(UC c, UC *input, size_t size, + unsigned long value = 0; + value += input[0]; value <<= 8; + value += input[1]; value <<= 8; +- value += input[2]; ++ value += input[2]; + code[3] = b64base[value & 0x3f]; value >>= 6; + code[2] = b64base[value & 0x3f]; value >>= 6; + code[1] = b64base[value & 0x3f]; value >>= 6; +@@ -186,11 +179,11 @@ static size_t b64encode(UC c, UC *input, size_t size, + } + + /*-------------------------------------------------------------------------*\ +-* Encodes the Base64 last 1 or 2 bytes and adds padding '=' ++* Encodes the Base64 last 1 or 2 bytes and adds padding '=' + * Result, if any, is appended to buffer. + * Returns 0. + \*-------------------------------------------------------------------------*/ +-static size_t b64pad(const UC *input, size_t size, ++static size_t b64pad(const UC *input, size_t size, + luaL_Buffer *buffer) + { + unsigned long value = 0; +@@ -203,7 +196,7 @@ static size_t b64pad(const UC *input, size_t size, + luaL_addlstring(buffer, (char *) code, 4); + break; + case 2: +- value = input[0]; value <<= 8; ++ value = input[0]; value <<= 8; + value |= input[1]; value <<= 2; + code[2] = b64base[value & 0x3f]; value >>= 6; + code[1] = b64base[value & 0x3f]; value >>= 6; +@@ -217,11 +210,11 @@ static size_t b64pad(const UC *input, size_t size, + } + + /*-------------------------------------------------------------------------*\ +-* Acumulates bytes in input buffer until 4 bytes are available. ++* Acumulates bytes in input buffer until 4 bytes are available. + * Translate the 4 bytes from Base64 form and append to buffer. + * Returns new number of bytes in buffer. + \*-------------------------------------------------------------------------*/ +-static size_t b64decode(UC c, UC *input, size_t size, ++static size_t b64decode(UC c, UC *input, size_t size, + luaL_Buffer *buffer) + { + /* ignore invalid characters */ +@@ -239,7 +232,7 @@ static size_t b64decode(UC c, UC *input, size_t size, + decoded[1] = (UC) (value & 0xff); value >>= 8; + decoded[0] = (UC) value; + /* take care of paddding */ +- valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3; ++ valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3; + luaL_addlstring(buffer, (char *) decoded, valid); + return 0; + /* need more data */ +@@ -251,7 +244,7 @@ static size_t b64decode(UC c, UC *input, size_t size, + * A, B = b64(C, D) + * A is the encoded version of the largest prefix of C .. D that is + * divisible by 3. B has the remaining bytes of C .. D, *without* encoding. +-* The easiest thing would be to concatenate the two strings and ++* The easiest thing would be to concatenate the two strings and + * encode the result, but we can't afford that or Lua would dupplicate + * every chunk we received. + \*-------------------------------------------------------------------------*/ +@@ -259,7 +252,7 @@ static int mime_global_b64(lua_State *L) + { + UC atom[3]; + size_t isize = 0, asize = 0; +- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize); ++ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); + const UC *last = input + isize; + luaL_Buffer buffer; + /* end-of-input blackhole */ +@@ -272,9 +265,9 @@ static int mime_global_b64(lua_State *L) + lua_settop(L, 2); + /* process first part of the input */ + luaL_buffinit(L, &buffer); +- while (input < last) ++ while (input < last) + asize = b64encode(*input++, atom, asize, &buffer); +- input = (UC *) luaL_optlstring(L, 2, NULL, &isize); ++ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); + /* if second part is nil, we are done */ + if (!input) { + size_t osize = 0; +@@ -288,7 +281,7 @@ static int mime_global_b64(lua_State *L) + } + /* otherwise process the second part */ + last = input + isize; +- while (input < last) ++ while (input < last) + asize = b64encode(*input++, atom, asize, &buffer); + luaL_pushresult(&buffer); + lua_pushlstring(L, (char *) atom, asize); +@@ -305,7 +298,7 @@ static int mime_global_unb64(lua_State *L) + { + UC atom[4]; + size_t isize = 0, asize = 0; +- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize); ++ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); + const UC *last = input + isize; + luaL_Buffer buffer; + /* end-of-input blackhole */ +@@ -318,9 +311,9 @@ static int mime_global_unb64(lua_State *L) + lua_settop(L, 2); + /* process first part of the input */ + luaL_buffinit(L, &buffer); +- while (input < last) ++ while (input < last) + asize = b64decode(*input++, atom, asize, &buffer); +- input = (UC *) luaL_optlstring(L, 2, NULL, &isize); ++ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); + /* if second is nil, we are done */ + if (!input) { + size_t osize = 0; +@@ -333,7 +326,7 @@ static int mime_global_unb64(lua_State *L) + } + /* otherwise, process the rest of the input */ + last = input + isize; +- while (input < last) ++ while (input < last) + asize = b64decode(*input++, atom, asize, &buffer); + luaL_pushresult(&buffer); + lua_pushlstring(L, (char *) atom, asize); +@@ -349,7 +342,7 @@ static int mime_global_unb64(lua_State *L) + * 9 and 32 can be plain, unless in the end of a line, where must be =XX + * encoded lines must be no longer than 76 not counting CRLF + * soft line-break are =CRLF +-* To encode one byte, we need to see the next two. ++* To encode one byte, we need to see the next two. + * Worst case is when we see a space, and wonder if a CRLF is comming + \*-------------------------------------------------------------------------*/ + /*-------------------------------------------------------------------------*\ +@@ -362,7 +355,7 @@ static void qpsetup(UC *cl, UC *unbase) + for (i = 0; i < 256; i++) cl[i] = QP_QUOTED; + for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN; + for (i = 62; i <= 126; i++) cl[i] = QP_PLAIN; +- cl['\t'] = QP_IF_LAST; ++ cl['\t'] = QP_IF_LAST; + cl[' '] = QP_IF_LAST; + cl['\r'] = QP_CR; + for (i = 0; i < 256; i++) unbase[i] = 255; +@@ -388,9 +381,9 @@ static void qpquote(UC c, luaL_Buffer *buffer) + + /*-------------------------------------------------------------------------*\ + * Accumulate characters until we are sure about how to deal with them. +-* Once we are sure, output to the buffer, in the correct form. ++* Once we are sure, output to the buffer, in the correct form. + \*-------------------------------------------------------------------------*/ +-static size_t qpencode(UC c, UC *input, size_t size, ++static size_t qpencode(UC c, UC *input, size_t size, + const char *marker, luaL_Buffer *buffer) + { + input[size++] = c; +@@ -431,7 +424,7 @@ static size_t qpencode(UC c, UC *input, size_t size, + } + + /*-------------------------------------------------------------------------*\ +-* Deal with the final characters ++* Deal with the final characters + \*-------------------------------------------------------------------------*/ + static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer) + { +@@ -448,8 +441,8 @@ static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer) + * Incrementally converts a string to quoted-printable + * A, B = qp(C, D, marker) + * Marker is the text to be used to replace CRLF sequences found in A. +-* A is the encoded version of the largest prefix of C .. D that +-* can be encoded without doubts. ++* A is the encoded version of the largest prefix of C .. D that ++* can be encoded without doubts. + * B has the remaining bytes of C .. D, *without* encoding. + \*-------------------------------------------------------------------------*/ + static int mime_global_qp(lua_State *L) +@@ -457,7 +450,7 @@ static int mime_global_qp(lua_State *L) + + size_t asize = 0, isize = 0; + UC atom[3]; +- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize); ++ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); + const UC *last = input + isize; + const char *marker = luaL_optstring(L, 3, CRLF); + luaL_Buffer buffer; +@@ -473,7 +466,7 @@ static int mime_global_qp(lua_State *L) + luaL_buffinit(L, &buffer); + while (input < last) + asize = qpencode(*input++, atom, asize, marker, &buffer); +- input = (UC *) luaL_optlstring(L, 2, NULL, &isize); ++ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); + /* if second part is nil, we are done */ + if (!input) { + asize = qppad(atom, asize, &buffer); +@@ -493,7 +486,7 @@ static int mime_global_qp(lua_State *L) + + /*-------------------------------------------------------------------------*\ + * Accumulate characters until we are sure about how to deal with them. +-* Once we are sure, output the to the buffer, in the correct form. ++* Once we are sure, output the to the buffer, in the correct form. + \*-------------------------------------------------------------------------*/ + static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) { + int d; +@@ -501,8 +494,8 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) { + /* deal with all characters we can deal */ + switch (input[0]) { + /* if we have an escape character */ +- case '=': +- if (size < 3) return size; ++ case '=': ++ if (size < 3) return size; + /* eliminate soft line break */ + if (input[1] == '\r' && input[2] == '\n') return 0; + /* decode quoted representation */ +@@ -512,7 +505,7 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) { + else luaL_addchar(buffer, (char) ((c << 4) + d)); + return 0; + case '\r': +- if (size < 2) return size; ++ if (size < 2) return size; + if (input[1] == '\n') luaL_addlstring(buffer, (char *)input, 2); + return 0; + default: +@@ -525,15 +518,15 @@ static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) { + /*-------------------------------------------------------------------------*\ + * Incrementally decodes a string in quoted-printable + * A, B = qp(C, D) +-* A is the decoded version of the largest prefix of C .. D that +-* can be decoded without doubts. ++* A is the decoded version of the largest prefix of C .. D that ++* can be decoded without doubts. + * B has the remaining bytes of C .. D, *without* decoding. + \*-------------------------------------------------------------------------*/ + static int mime_global_unqp(lua_State *L) + { + size_t asize = 0, isize = 0; + UC atom[3]; +- const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize); ++ const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize); + const UC *last = input + isize; + luaL_Buffer buffer; + /* end-of-input blackhole */ +@@ -548,14 +541,14 @@ static int mime_global_unqp(lua_State *L) + luaL_buffinit(L, &buffer); + while (input < last) + asize = qpdecode(*input++, atom, asize, &buffer); +- input = (UC *) luaL_optlstring(L, 2, NULL, &isize); ++ input = (const UC *) luaL_optlstring(L, 2, NULL, &isize); + /* if second part is nil, we are done */ + if (!input) { + luaL_pushresult(&buffer); + if (!(*lua_tostring(L, -1))) lua_pushnil(L); + lua_pushnil(L); + return 2; +- } ++ } + /* otherwise process rest of input */ + last = input + isize; + while (input < last) +@@ -568,9 +561,9 @@ static int mime_global_unqp(lua_State *L) + /*-------------------------------------------------------------------------*\ + * Incrementally breaks a quoted-printed string into lines + * A, n = qpwrp(l, B, length) +-* A is a copy of B, broken into lines of at most 'length' bytes. +-* 'l' is how many bytes are left for the first line of B. +-* 'n' is the number of bytes left in the last line of A. ++* A is a copy of B, broken into lines of at most 'length' bytes. ++* 'l' is how many bytes are left for the first line of B. ++* 'n' is the number of bytes left in the last line of A. + * There are two complications: lines can't be broken in the middle + * of an encoded =XX, and there might be line breaks already + \*-------------------------------------------------------------------------*/ +@@ -578,7 +571,7 @@ static int mime_global_qpwrp(lua_State *L) + { + size_t size = 0; + int left = (int) luaL_checknumber(L, 1); +- const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size); ++ const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size); + const UC *last = input + size; + int length = (int) luaL_optnumber(L, 3, 76); + luaL_Buffer buffer; +@@ -603,11 +596,11 @@ static int mime_global_qpwrp(lua_State *L) + if (left <= 3) { + left = length; + luaL_addstring(&buffer, EQCRLF); +- } ++ } + luaL_addchar(&buffer, *input); + left--; + break; +- default: ++ default: + if (left <= 1) { + left = length; + luaL_addstring(&buffer, EQCRLF); +@@ -635,7 +628,7 @@ static int mime_global_qpwrp(lua_State *L) + * last is the previous character + \*-------------------------------------------------------------------------*/ + #define eolcandidate(c) (c == '\r' || c == '\n') +-static int eolprocess(int c, int last, const char *marker, ++static int eolprocess(int c, int last, const char *marker, + luaL_Buffer *buffer) + { + if (eolcandidate(c)) { +@@ -653,15 +646,15 @@ static int eolprocess(int c, int last, const char *marker, + } + + /*-------------------------------------------------------------------------*\ +-* Converts a string to uniform EOL convention. ++* Converts a string to uniform EOL convention. + * A, n = eol(o, B, marker) + * A is the converted version of the largest prefix of B that can be +-* converted unambiguously. 'o' is the context returned by the previous ++* converted unambiguously. 'o' is the context returned by the previous + * call. 'n' is the new context. + \*-------------------------------------------------------------------------*/ + static int mime_global_eol(lua_State *L) + { +- int ctx = luaL_checkint(L, 1); ++ int ctx = luaL_checkinteger(L, 1); + size_t isize = 0; + const char *input = luaL_optlstring(L, 2, NULL, &isize); + const char *last = input + isize; +@@ -683,18 +676,18 @@ static int mime_global_eol(lua_State *L) + } + + /*-------------------------------------------------------------------------*\ +-* Takes one byte and stuff it if needed. ++* Takes one byte and stuff it if needed. + \*-------------------------------------------------------------------------*/ + static size_t dot(int c, size_t state, luaL_Buffer *buffer) + { + luaL_addchar(buffer, (char) c); + switch (c) { +- case '\r': ++ case '\r': + return 1; +- case '\n': +- return (state == 1)? 2: 0; +- case '.': +- if (state == 2) ++ case '\n': ++ return (state == 1)? 2: 0; ++ case '.': ++ if (state == 2) + luaL_addchar(buffer, '.'); + default: + return 0; +@@ -719,7 +712,7 @@ static int mime_global_dot(lua_State *L) + } + /* process all input */ + luaL_buffinit(L, &buffer); +- while (input < last) ++ while (input < last) + state = dot(*input++, state, &buffer); + luaL_pushresult(&buffer); + lua_pushnumber(L, (lua_Number) state); +diff --git a/src/options.c b/src/options.c +index 8ac2a14..20f4c28 100644 +--- a/src/options.c ++++ b/src/options.c +@@ -1,8 +1,8 @@ + /*=========================================================================*\ +-* Common option interface ++* Common option interface + * LuaSocket toolkit + \*=========================================================================*/ +-#include <string.h> ++#include <string.h> + + #include "lauxlib.h" + +@@ -20,9 +20,9 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); + static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); + static int opt_setint(lua_State *L, p_socket ps, int level, int name); + static int opt_getint(lua_State *L, p_socket ps, int level, int name); +-static int opt_set(lua_State *L, p_socket ps, int level, int name, ++static int opt_set(lua_State *L, p_socket ps, int level, int name, + void *val, int len); +-static int opt_get(lua_State *L, p_socket ps, int level, int name, ++static int opt_get(lua_State *L, p_socket ps, int level, int name, + void *val, int* len); + + /*=========================================================================*\ +@@ -60,29 +60,29 @@ int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps) + /* enables reuse of local address */ + int opt_set_reuseaddr(lua_State *L, p_socket ps) + { +- return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); ++ return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); + } + + int opt_get_reuseaddr(lua_State *L, p_socket ps) + { +- return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); ++ return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); + } + + /* enables reuse of local port */ + int opt_set_reuseport(lua_State *L, p_socket ps) + { +- return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); ++ return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); + } + + int opt_get_reuseport(lua_State *L, p_socket ps) + { +- return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); ++ return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); + } + + /* disables the Naggle algorithm */ + int opt_set_tcp_nodelay(lua_State *L, p_socket ps) + { +- return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); ++ return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); + } + + int opt_get_tcp_nodelay(lua_State *L, p_socket ps) +@@ -92,12 +92,12 @@ int opt_get_tcp_nodelay(lua_State *L, p_socket ps) + + int opt_set_keepalive(lua_State *L, p_socket ps) + { +- return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); ++ return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); + } + + int opt_get_keepalive(lua_State *L, p_socket ps) + { +- return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); ++ return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); + } + + int opt_set_dontroute(lua_State *L, p_socket ps) +@@ -105,11 +105,21 @@ int opt_set_dontroute(lua_State *L, p_socket ps) + return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); + } + ++int opt_get_dontroute(lua_State *L, p_socket ps) ++{ ++ return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); ++} ++ + int opt_set_broadcast(lua_State *L, p_socket ps) + { + return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); + } + ++int opt_get_broadcast(lua_State *L, p_socket ps) ++{ ++ return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST); ++} ++ + int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) + { + return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); +@@ -156,12 +166,12 @@ int opt_set_linger(lua_State *L, p_socket ps) + if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); + lua_pushstring(L, "on"); + lua_gettable(L, 3); +- if (!lua_isboolean(L, -1)) ++ if (!lua_isboolean(L, -1)) + luaL_argerror(L, 3, "boolean 'on' field expected"); + li.l_onoff = (u_short) lua_toboolean(L, -1); + lua_pushstring(L, "timeout"); + lua_gettable(L, 3); +- if (!lua_isnumber(L, -1)) ++ if (!lua_isnumber(L, -1)) + luaL_argerror(L, 3, "number 'timeout' field expected"); + li.l_linger = (u_short) lua_tonumber(L, -1); + return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); +@@ -194,7 +204,7 @@ int opt_set_ip_multicast_if(lua_State *L, p_socket ps) + val.s_addr = htonl(INADDR_ANY); + if (strcmp(address, "*") && !inet_aton(address, &val)) + luaL_argerror(L, 3, "ip expected"); +- return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, ++ return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF, + (char *) &val, sizeof(val)); + } + +@@ -250,17 +260,17 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) + if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); + lua_pushstring(L, "multiaddr"); + lua_gettable(L, 3); +- if (!lua_isstring(L, -1)) ++ if (!lua_isstring(L, -1)) + luaL_argerror(L, 3, "string 'multiaddr' field expected"); +- if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) ++ if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr)) + luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); + lua_pushstring(L, "interface"); + lua_gettable(L, 3); +- if (!lua_isstring(L, -1)) ++ if (!lua_isstring(L, -1)) + luaL_argerror(L, 3, "string 'interface' field expected"); + val.imr_interface.s_addr = htonl(INADDR_ANY); + if (strcmp(lua_tostring(L, -1), "*") && +- !inet_aton(lua_tostring(L, -1), &val.imr_interface)) ++ !inet_aton(lua_tostring(L, -1), &val.imr_interface)) + luaL_argerror(L, 3, "invalid 'interface' ip address"); + return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); + } +@@ -272,14 +282,14 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) + if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); + lua_pushstring(L, "multiaddr"); + lua_gettable(L, 3); +- if (!lua_isstring(L, -1)) ++ if (!lua_isstring(L, -1)) + luaL_argerror(L, 3, "string 'multiaddr' field expected"); +- if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) ++ if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) + luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); + lua_pushstring(L, "interface"); + lua_gettable(L, 3); + /* By default we listen to interface on default route +- * (sigh). However, interface= can override it. We should ++ * (sigh). However, interface= can override it. We should + * support either number, or name for it. Waiting for + * windows port of if_nametoindex */ + if (!lua_isnil(L, -1)) { +@@ -291,7 +301,7 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) + return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); + } + +-static ++static + int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) + { + socklen_t socklen = *len; +@@ -304,7 +314,7 @@ int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) + return 0; + } + +-static ++static + int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) + { + if (setsockopt(*ps, level, name, (char *) val, len) < 0) { +diff --git a/src/options.h b/src/options.h +index 5657a06..19ba0df 100644 +--- a/src/options.h ++++ b/src/options.h +@@ -21,7 +21,6 @@ typedef t_opt *p_opt; + /* supported options for setoption */ + int opt_set_dontroute(lua_State *L, p_socket ps); + int opt_set_broadcast(lua_State *L, p_socket ps); +-int opt_set_reuseaddr(lua_State *L, p_socket ps); + int opt_set_tcp_nodelay(lua_State *L, p_socket ps); + int opt_set_keepalive(lua_State *L, p_socket ps); + int opt_set_linger(lua_State *L, p_socket ps); +@@ -40,18 +39,21 @@ int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); + int opt_set_ip6_v6only(lua_State *L, p_socket ps); + + /* supported options for getoption */ ++int opt_get_dontroute(lua_State *L, p_socket ps); ++int opt_get_broadcast(lua_State *L, p_socket ps); + int opt_get_reuseaddr(lua_State *L, p_socket ps); ++int opt_get_reuseport(lua_State *L, p_socket ps); + int opt_get_tcp_nodelay(lua_State *L, p_socket ps); + int opt_get_keepalive(lua_State *L, p_socket ps); + int opt_get_linger(lua_State *L, p_socket ps); +-int opt_get_reuseaddr(lua_State *L, p_socket ps); + int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); + int opt_get_ip_multicast_if(lua_State *L, p_socket ps); + int opt_get_error(lua_State *L, p_socket ps); + int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); + int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); + int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); +-int opt_get_ip6_v6only(lua_State *L, p_socket ps); ++int opt_get_ip6_v6only(lua_State *L, p_socket ps); ++int opt_get_reuseport(lua_State *L, p_socket ps); + + /* invokes the appropriate option handler */ + int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); +diff --git a/src/pierror.h b/src/pierror.h +new file mode 100644 +index 0000000..cb773ab +--- /dev/null ++++ b/src/pierror.h +@@ -0,0 +1,28 @@ ++#ifndef PIERROR_H ++#define PIERROR_H ++/*=========================================================================*\ ++* Error messages ++* Defines platform independent error messages ++\*=========================================================================*/ ++ ++#define PIE_HOST_NOT_FOUND "host not found" ++#define PIE_ADDRINUSE "address already in use" ++#define PIE_ISCONN "already connected" ++#define PIE_ACCESS "permission denied" ++#define PIE_CONNREFUSED "connection refused" ++#define PIE_CONNABORTED "closed" ++#define PIE_CONNRESET "closed" ++#define PIE_TIMEDOUT "timeout" ++#define PIE_AGAIN "temporary failure in name resolution" ++#define PIE_BADFLAGS "invalid value for ai_flags" ++#define PIE_BADHINTS "invalid value for hints" ++#define PIE_FAIL "non-recoverable failure in name resolution" ++#define PIE_FAMILY "ai_family not supported" ++#define PIE_MEMORY "memory allocation failure" ++#define PIE_NONAME "host or service not provided, or not known" ++#define PIE_OVERFLOW "argument buffer overflow" ++#define PIE_PROTOCOL "resolved protocol is unknown" ++#define PIE_SERVICE "service not supported for socket type" ++#define PIE_SOCKTYPE "ai_socktype not supported" ++ ++#endif +diff --git a/src/select.c b/src/select.c +index fafaa62..9d133b7 100644 +--- a/src/select.c ++++ b/src/select.c +@@ -6,6 +6,7 @@ + + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + #include "socket.h" + #include "timeout.h" +@@ -16,10 +17,10 @@ + \*=========================================================================*/ + static t_socket getfd(lua_State *L); + static int dirty(lua_State *L); +-static void collect_fd(lua_State *L, int tab, int itab, ++static void collect_fd(lua_State *L, int tab, int itab, + fd_set *set, t_socket *max_fd); + static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set); +-static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, ++static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, + int itab, int tab, int start); + static void make_assoc(lua_State *L, int tab); + static int global_select(lua_State *L); +@@ -38,13 +39,12 @@ static luaL_Reg func[] = { + \*-------------------------------------------------------------------------*/ + int select_open(lua_State *L) { + lua_pushstring(L, "_SETSIZE"); +- lua_pushnumber(L, FD_SETSIZE); ++ lua_pushinteger(L, FD_SETSIZE); ++ lua_rawset(L, -3); ++ lua_pushstring(L, "_SOCKETINVALID"); ++ lua_pushinteger(L, SOCKET_INVALID); + lua_rawset(L, -3); +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, NULL, func, 0); +-#endif + return 0; + } + +@@ -98,10 +98,10 @@ static t_socket getfd(lua_State *L) { + lua_pushvalue(L, -2); + lua_call(L, 1, 1); + if (lua_isnumber(L, -1)) { +- double numfd = lua_tonumber(L, -1); ++ double numfd = lua_tonumber(L, -1); + fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID; + } +- } ++ } + lua_pop(L, 1); + return fd; + } +@@ -114,12 +114,12 @@ static int dirty(lua_State *L) { + lua_pushvalue(L, -2); + lua_call(L, 1, 1); + is = lua_toboolean(L, -1); +- } ++ } + lua_pop(L, 1); + return is; + } + +-static void collect_fd(lua_State *L, int tab, int itab, ++static void collect_fd(lua_State *L, int tab, int itab, + fd_set *set, t_socket *max_fd) { + int i = 1, n = 0; + /* nil is the same as an empty table */ +@@ -139,16 +139,16 @@ static void collect_fd(lua_State *L, int tab, int itab, + if (fd != SOCKET_INVALID) { + /* make sure we don't overflow the fd_set */ + #ifdef _WIN32 +- if (n >= FD_SETSIZE) ++ if (n >= FD_SETSIZE) + luaL_argerror(L, tab, "too many sockets"); + #else +- if (fd >= FD_SETSIZE) ++ if (fd >= FD_SETSIZE) + luaL_argerror(L, tab, "descriptor too large for set size"); + #endif + FD_SET(fd, set); + n++; + /* keep track of the largest descriptor so far */ +- if (*max_fd == SOCKET_INVALID || *max_fd < fd) ++ if (*max_fd == SOCKET_INVALID || *max_fd < fd) + *max_fd = fd; + /* make sure we can map back from descriptor to the object */ + lua_pushnumber(L, (lua_Number) fd); +@@ -162,9 +162,9 @@ static void collect_fd(lua_State *L, int tab, int itab, + + static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) { + int ndirty = 0, i = 1; +- if (lua_isnil(L, tab)) ++ if (lua_isnil(L, tab)) + return 0; +- for ( ;; ) { ++ for ( ;; ) { + t_socket fd; + lua_pushnumber(L, i); + lua_gettable(L, tab); +@@ -185,7 +185,7 @@ static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) { + return ndirty; + } + +-static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, ++static void return_fd(lua_State *L, fd_set *set, t_socket max_fd, + int itab, int tab, int start) { + t_socket fd; + for (fd = 0; fd < max_fd; fd++) { +diff --git a/src/serial.c b/src/serial.c +index 583d4e5..7bdb21c 100644 +--- a/src/serial.c ++++ b/src/serial.c +@@ -2,7 +2,7 @@ + * Serial stream + * LuaSocket toolkit + \*=========================================================================*/ +-#include <string.h> ++#include <string.h> + + #include "lua.h" + #include "lauxlib.h" +@@ -11,7 +11,7 @@ + #include "socket.h" + #include "options.h" + #include "unix.h" +-#include <sys/un.h> ++#include <sys/un.h> + + /* + Reuses userdata definition from unix.h, since it is useful for all +@@ -54,15 +54,6 @@ static luaL_Reg serial_methods[] = { + {NULL, NULL} + }; + +-/* our socket creation function */ +-/* this is an ad-hoc module that returns a single function +- * as such, do not include other functions in this array. */ +-static luaL_Reg func[] = { +- {"serial", global_create}, +- {NULL, NULL} +-}; +- +- + /*-------------------------------------------------------------------------*\ + * Initializes module + \*-------------------------------------------------------------------------*/ +@@ -71,14 +62,7 @@ LUASOCKET_API int luaopen_socket_serial(lua_State *L) { + auxiliar_newclass(L, "serial{client}", serial_methods); + /* create class groups */ + auxiliar_add2group(L, "serial{client}", "serial{any}"); +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) +- lua_pushcfunction(L, global_create); +- (void) func; +-#else +- /* set function into socket namespace */ +- luaL_openlib(L, "socket", func, 0); + lua_pushcfunction(L, global_create); +-#endif + return 1; + } + +@@ -120,7 +104,7 @@ static int meth_getfd(lua_State *L) { + /* this is very dangerous, but can be handy for those that are brave enough */ + static int meth_setfd(lua_State *L) { + p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); +- un->sock = (t_socket) luaL_checknumber(L, 2); ++ un->sock = (t_socket) luaL_checknumber(L, 2); + return 0; + } + +@@ -131,7 +115,7 @@ static int meth_dirty(lua_State *L) { + } + + /*-------------------------------------------------------------------------*\ +-* Closes socket used by object ++* Closes socket used by object + \*-------------------------------------------------------------------------*/ + static int meth_close(lua_State *L) + { +@@ -156,7 +140,7 @@ static int meth_settimeout(lua_State *L) { + + + /*-------------------------------------------------------------------------*\ +-* Creates a serial object ++* Creates a serial object + \*-------------------------------------------------------------------------*/ + static int global_create(lua_State *L) { + const char* path = luaL_checkstring(L, 1); +@@ -180,7 +164,7 @@ static int global_create(lua_State *L) { + /* initialize remaining structure fields */ + socket_setnonblocking(&sock); + un->sock = sock; +- io_init(&un->io, (p_send) socket_write, (p_recv) socket_read, ++ io_init(&un->io, (p_send) socket_write, (p_recv) socket_read, + (p_error) socket_ioerror, &un->sock); + timeout_init(&un->tm, -1, -1); + buffer_init(&un->buf, &un->io, &un->tm); +diff --git a/src/socket.lua b/src/socket.lua +index 3913e6f..d1c0b16 100644 +--- a/src/socket.lua ++++ b/src/socket.lua +@@ -32,23 +32,23 @@ function _M.bind(host, port, backlog) + err = "no info on address" + for i, alt in base.ipairs(addrinfo) do + if alt.family == "inet" then +- sock, err = socket.tcp() ++ sock, err = socket.tcp4() + else + sock, err = socket.tcp6() + end + if not sock then return nil, err end + sock:setoption("reuseaddr", true) + res, err = sock:bind(alt.addr, port) +- if not res then ++ if not res then + sock:close() +- else ++ else + res, err = sock:listen(backlog) +- if not res then ++ if not res then + sock:close() + else + return sock + end +- end ++ end + end + return nil, err + end +diff --git a/src/tcp.c b/src/tcp.c +index 6594bda..ef9ee6f 100644 +--- a/src/tcp.c ++++ b/src/tcp.c +@@ -6,6 +6,7 @@ + + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + #include "auxiliar.h" + #include "socket.h" +@@ -17,6 +18,7 @@ + * Internal function prototypes + \*=========================================================================*/ + static int global_create(lua_State *L); ++static int global_create4(lua_State *L); + static int global_create6(lua_State *L); + static int global_connect(lua_State *L); + static int meth_connect(lua_State *L); +@@ -34,6 +36,7 @@ static int meth_accept(lua_State *L); + static int meth_close(lua_State *L); + static int meth_getoption(lua_State *L); + static int meth_setoption(lua_State *L); ++static int meth_gettimeout(lua_State *L); + static int meth_settimeout(lua_State *L); + static int meth_getfd(lua_State *L); + static int meth_setfd(lua_State *L); +@@ -63,6 +66,7 @@ static luaL_Reg tcp_methods[] = { + {"setpeername", meth_connect}, + {"setsockname", meth_bind}, + {"settimeout", meth_settimeout}, ++ {"gettimeout", meth_gettimeout}, + {"shutdown", meth_shutdown}, + {NULL, NULL} + }; +@@ -71,6 +75,7 @@ static luaL_Reg tcp_methods[] = { + static t_opt optget[] = { + {"keepalive", opt_get_keepalive}, + {"reuseaddr", opt_get_reuseaddr}, ++ {"reuseport", opt_get_reuseport}, + {"tcp-nodelay", opt_get_tcp_nodelay}, + {"linger", opt_get_linger}, + {"error", opt_get_error}, +@@ -80,6 +85,7 @@ static t_opt optget[] = { + static t_opt optset[] = { + {"keepalive", opt_set_keepalive}, + {"reuseaddr", opt_set_reuseaddr}, ++ {"reuseport", opt_set_reuseport}, + {"tcp-nodelay", opt_set_tcp_nodelay}, + {"ipv6-v6only", opt_set_ip6_v6only}, + {"linger", opt_set_linger}, +@@ -89,6 +95,7 @@ static t_opt optset[] = { + /* functions in library namespace */ + static luaL_Reg func[] = { + {"tcp", global_create}, ++ {"tcp4", global_create4}, + {"tcp6", global_create6}, + {"connect", global_connect}, + {NULL, NULL} +@@ -108,11 +115,7 @@ int tcp_open(lua_State *L) + auxiliar_add2group(L, "tcp{client}", "tcp{any}"); + auxiliar_add2group(L, "tcp{server}", "tcp{any}"); + /* define library functions */ +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, NULL, func, 0); +-#endif + return 0; + } + +@@ -216,8 +219,7 @@ static int meth_accept(lua_State *L) + /*-------------------------------------------------------------------------*\ + * Binds an object to an address + \*-------------------------------------------------------------------------*/ +-static int meth_bind(lua_State *L) +-{ ++static int meth_bind(lua_State *L) { + p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1); + const char *address = luaL_checkstring(L, 2); + const char *port = luaL_checkstring(L, 3); +@@ -227,7 +229,7 @@ static int meth_bind(lua_State *L) + bindhints.ai_socktype = SOCK_STREAM; + bindhints.ai_family = tcp->family; + bindhints.ai_flags = AI_PASSIVE; +- err = inet_trybind(&tcp->sock, address, port, &bindhints); ++ err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); +@@ -240,8 +242,7 @@ static int meth_bind(lua_State *L) + /*-------------------------------------------------------------------------*\ + * Turns a master tcp object into a client object. + \*-------------------------------------------------------------------------*/ +-static int meth_connect(lua_State *L) +-{ ++static int meth_connect(lua_State *L) { + p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); + const char *address = luaL_checkstring(L, 2); + const char *port = luaL_checkstring(L, 3); +@@ -252,7 +253,7 @@ static int meth_connect(lua_State *L) + /* make sure we try to connect only to the same family */ + connecthints.ai_family = tcp->family; + timeout_markstart(&tcp->tm); +- err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, ++ err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, + &tcp->tm, &connecthints); + /* have to set the class even if it failed due to non-blocking connects */ + auxiliar_setclass(L, "tcp{client}", 1); +@@ -282,9 +283,12 @@ static int meth_close(lua_State *L) + static int meth_getfamily(lua_State *L) + { + p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); +- if (tcp->family == PF_INET6) { ++ if (tcp->family == AF_INET6) { + lua_pushliteral(L, "inet6"); + return 1; ++ } else if (tcp->family == AF_INET) { ++ lua_pushliteral(L, "inet4"); ++ return 1; + } else { + lua_pushliteral(L, "inet4"); + return 1; +@@ -348,6 +352,12 @@ static int meth_settimeout(lua_State *L) + return timeout_meth_settimeout(L, &tcp->tm); + } + ++static int meth_gettimeout(lua_State *L) ++{ ++ p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); ++ return timeout_meth_gettimeout(L, &tcp->tm); ++} ++ + /*=========================================================================*\ + * Library functions + \*=========================================================================*/ +@@ -355,37 +365,36 @@ static int meth_settimeout(lua_State *L) + * Creates a master tcp object + \*-------------------------------------------------------------------------*/ + static int tcp_create(lua_State *L, int family) { +- t_socket sock; +- const char *err = inet_trycreate(&sock, family, SOCK_STREAM); +- /* try to allocate a system socket */ +- if (!err) { +- /* allocate tcp object */ +- p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); +- memset(tcp, 0, sizeof(t_tcp)); +- /* set its type as master object */ +- auxiliar_setclass(L, "tcp{master}", -1); +- /* initialize remaining structure fields */ +- socket_setnonblocking(&sock); +- if (family == PF_INET6) { +- int yes = 1; +- setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, +- (void *)&yes, sizeof(yes)); ++ p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); ++ memset(tcp, 0, sizeof(t_tcp)); ++ /* set its type as master object */ ++ auxiliar_setclass(L, "tcp{master}", -1); ++ /* if family is AF_UNSPEC, we leave the socket invalid and ++ * store AF_UNSPEC into family. This will allow it to later be ++ * replaced with an AF_INET6 or AF_INET socket upon first use. */ ++ tcp->sock = SOCKET_INVALID; ++ tcp->family = family; ++ io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, ++ (p_error) socket_ioerror, &tcp->sock); ++ timeout_init(&tcp->tm, -1, -1); ++ buffer_init(&tcp->buf, &tcp->io, &tcp->tm); ++ if (family != AF_UNSPEC) { ++ const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0); ++ if (err != NULL) { ++ lua_pushnil(L); ++ lua_pushstring(L, err); ++ return 2; + } +- tcp->sock = sock; +- io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv, +- (p_error) socket_ioerror, &tcp->sock); +- timeout_init(&tcp->tm, -1, -1); +- buffer_init(&tcp->buf, &tcp->io, &tcp->tm); +- tcp->family = family; +- return 1; +- } else { +- lua_pushnil(L); +- lua_pushstring(L, err); +- return 2; ++ socket_setnonblocking(&tcp->sock); + } ++ return 1; + } + + static int global_create(lua_State *L) { ++ return tcp_create(L, AF_UNSPEC); ++} ++ ++static int global_create4(lua_State *L) { + return tcp_create(L, AF_INET); + } + +@@ -393,53 +402,6 @@ static int global_create6(lua_State *L) { + return tcp_create(L, AF_INET6); + } + +-#if 0 +-static const char *tryconnect6(const char *remoteaddr, const char *remoteserv, +- struct addrinfo *connecthints, p_tcp tcp) { +- struct addrinfo *iterator = NULL, *resolved = NULL; +- const char *err = NULL; +- /* try resolving */ +- err = socket_gaistrerror(getaddrinfo(remoteaddr, remoteserv, +- connecthints, &resolved)); +- if (err != NULL) { +- if (resolved) freeaddrinfo(resolved); +- return err; +- } +- /* iterate over all returned addresses trying to connect */ +- for (iterator = resolved; iterator; iterator = iterator->ai_next) { +- p_timeout tm = timeout_markstart(&tcp->tm); +- /* create new socket if necessary. if there was no +- * bind, we need to create one for every new family +- * that shows up while iterating. if there was a +- * bind, all families will be the same and we will +- * not enter this branch. */ +- if (tcp->family != iterator->ai_family) { +- socket_destroy(&tcp->sock); +- err = socket_strerror(socket_create(&tcp->sock, +- iterator->ai_family, iterator->ai_socktype, +- iterator->ai_protocol)); +- if (err != NULL) { +- freeaddrinfo(resolved); +- return err; +- } +- tcp->family = iterator->ai_family; +- /* all sockets initially non-blocking */ +- socket_setnonblocking(&tcp->sock); +- } +- /* finally try connecting to remote address */ +- err = socket_strerror(socket_connect(&tcp->sock, +- (SA *) iterator->ai_addr, +- (socklen_t) iterator->ai_addrlen, tm)); +- /* if success, break out of loop */ +- if (err == NULL) break; +- } +- +- freeaddrinfo(resolved); +- /* here, if err is set, we failed */ +- return err; +-} +-#endif +- + static int global_connect(lua_State *L) { + const char *remoteaddr = luaL_checkstring(L, 1); + const char *remoteserv = luaL_checkstring(L, 2); +@@ -456,26 +418,26 @@ static int global_connect(lua_State *L) { + timeout_init(&tcp->tm, -1, -1); + buffer_init(&tcp->buf, &tcp->io, &tcp->tm); + tcp->sock = SOCKET_INVALID; +- tcp->family = PF_UNSPEC; ++ tcp->family = AF_UNSPEC; + /* allow user to pick local address and port */ + memset(&bindhints, 0, sizeof(bindhints)); + bindhints.ai_socktype = SOCK_STREAM; + bindhints.ai_family = family; + bindhints.ai_flags = AI_PASSIVE; + if (localaddr) { +- err = inet_trybind(&tcp->sock, localaddr, localserv, &bindhints); ++ err = inet_trybind(&tcp->sock, &tcp->family, localaddr, ++ localserv, &bindhints); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } +- tcp->family = bindhints.ai_family; + } + /* try to connect to remote address and port */ + memset(&connecthints, 0, sizeof(connecthints)); + connecthints.ai_socktype = SOCK_STREAM; + /* make sure we try to connect only to the same family */ +- connecthints.ai_family = bindhints.ai_family; ++ connecthints.ai_family = tcp->family; + err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, + &tcp->tm, &connecthints); + if (err) { +diff --git a/src/timeout.c b/src/timeout.c +index bdd5e1c..5a601d5 100644 +--- a/src/timeout.c ++++ b/src/timeout.c +@@ -8,6 +8,7 @@ + + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + #include "auxiliar.h" + #include "timeout.h" +@@ -52,7 +53,7 @@ void timeout_init(p_timeout tm, double block, double total) { + + /*-------------------------------------------------------------------------*\ + * Determines how much time we have left for the next system call, +-* if the previous call was successful ++* if the previous call was successful + * Input + * tm: timeout control structure + * Returns +@@ -107,7 +108,7 @@ double timeout_getretry(p_timeout tm) { + } + + /*-------------------------------------------------------------------------*\ +-* Marks the operation start time in structure ++* Marks the operation start time in structure + * Input + * tm: timeout control structure + \*-------------------------------------------------------------------------*/ +@@ -117,7 +118,7 @@ p_timeout timeout_markstart(p_timeout tm) { + } + + /*-------------------------------------------------------------------------*\ +-* Gets time in s, relative to January 1, 1970 (UTC) ++* Gets time in s, relative to January 1, 1970 (UTC) + * Returns + * time in s. + \*-------------------------------------------------------------------------*/ +@@ -144,11 +145,7 @@ double timeout_gettime(void) { + * Initializes module + \*-------------------------------------------------------------------------*/ + int timeout_open(lua_State *L) { +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, NULL, func, 0); +-#endif + return 0; + } + +@@ -163,7 +160,7 @@ int timeout_meth_settimeout(lua_State *L, p_timeout tm) { + const char *mode = luaL_optstring(L, 3, "b"); + switch (*mode) { + case 'b': +- tm->block = t; ++ tm->block = t; + break; + case 'r': case 't': + tm->total = t; +@@ -176,6 +173,16 @@ int timeout_meth_settimeout(lua_State *L, p_timeout tm) { + return 1; + } + ++/*-------------------------------------------------------------------------*\ ++* Gets timeout values for IO operations ++* Lua Output: block, total ++\*-------------------------------------------------------------------------*/ ++int timeout_meth_gettimeout(lua_State *L, p_timeout tm) { ++ lua_pushnumber(L, tm->block); ++ lua_pushnumber(L, tm->total); ++ return 2; ++} ++ + /*=========================================================================*\ + * Test support functions + \*=========================================================================*/ +diff --git a/src/timeout.h b/src/timeout.h +index 6715ca7..af90231 100644 +--- a/src/timeout.h ++++ b/src/timeout.h +@@ -22,6 +22,7 @@ p_timeout timeout_markstart(p_timeout tm); + double timeout_getstart(p_timeout tm); + double timeout_gettime(void); + int timeout_meth_settimeout(lua_State *L, p_timeout tm); ++int timeout_meth_gettimeout(lua_State *L, p_timeout tm); + + #define timeout_iszero(tm) ((tm)->block == 0.0) + +diff --git a/src/tp.lua b/src/tp.lua +index cbeff56..328cbab 100644 +--- a/src/tp.lua ++++ b/src/tp.lua +@@ -74,7 +74,7 @@ function metat.__index:command(cmd, arg) + end + + function metat.__index:sink(snk, pat) +- local chunk, err = c:receive(pat) ++ local chunk, err = self.c:receive(pat) + return snk(chunk, err) + end + +diff --git a/src/udp.c b/src/udp.c +index a9f2393..ec97252 100644 +--- a/src/udp.c ++++ b/src/udp.c +@@ -7,6 +7,7 @@ + + #include "lua.h" + #include "lauxlib.h" ++#include "compat.h" + + #include "auxiliar.h" + #include "socket.h" +@@ -26,6 +27,7 @@ + * Internal function prototypes + \*=========================================================================*/ + static int global_create(lua_State *L); ++static int global_create4(lua_State *L); + static int global_create6(lua_State *L); + static int meth_send(lua_State *L); + static int meth_sendto(lua_State *L); +@@ -34,6 +36,7 @@ static int meth_receivefrom(lua_State *L); + static int meth_getfamily(lua_State *L); + static int meth_getsockname(lua_State *L); + static int meth_getpeername(lua_State *L); ++static int meth_gettimeout(lua_State *L); + static int meth_setsockname(lua_State *L); + static int meth_setpeername(lua_State *L); + static int meth_close(lua_State *L); +@@ -64,6 +67,7 @@ static luaL_Reg udp_methods[] = { + {"setpeername", meth_setpeername}, + {"setsockname", meth_setsockname}, + {"settimeout", meth_settimeout}, ++ {"gettimeout", meth_gettimeout}, + {NULL, NULL} + }; + +@@ -89,6 +93,10 @@ static t_opt optset[] = { + + /* socket options for getoption */ + static t_opt optget[] = { ++ {"dontroute", opt_get_dontroute}, ++ {"broadcast", opt_get_broadcast}, ++ {"reuseaddr", opt_get_reuseaddr}, ++ {"reuseport", opt_get_reuseport}, + {"ip-multicast-if", opt_get_ip_multicast_if}, + {"ip-multicast-loop", opt_get_ip_multicast_loop}, + {"error", opt_get_error}, +@@ -102,6 +110,7 @@ static t_opt optget[] = { + /* functions in library namespace */ + static luaL_Reg func[] = { + {"udp", global_create}, ++ {"udp4", global_create4}, + {"udp6", global_create6}, + {NULL, NULL} + }; +@@ -109,8 +118,7 @@ static luaL_Reg func[] = { + /*-------------------------------------------------------------------------*\ + * Initializes module + \*-------------------------------------------------------------------------*/ +-int udp_open(lua_State *L) +-{ ++int udp_open(lua_State *L) { + /* create classes */ + auxiliar_newclass(L, "udp{connected}", udp_methods); + auxiliar_newclass(L, "udp{unconnected}", udp_methods); +@@ -120,18 +128,18 @@ int udp_open(lua_State *L) + auxiliar_add2group(L, "udp{connected}", "select{able}"); + auxiliar_add2group(L, "udp{unconnected}", "select{able}"); + /* define library functions */ +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + luaL_setfuncs(L, func, 0); +-#else +- luaL_openlib(L, NULL, func, 0); +-#endif ++ /* export default UDP size */ ++ lua_pushliteral(L, "_DATAGRAMSIZE"); ++ lua_pushinteger(L, UDP_DATAGRAMSIZE); ++ lua_rawset(L, -3); + return 0; + } + + /*=========================================================================*\ + * Lua methods + \*=========================================================================*/ +-const char *udp_strerror(int err) { ++static const char *udp_strerror(int err) { + /* a 'closed' error on an unconnected means the target address was not + * accepted by the transport layer */ + if (err == IO_CLOSED) return "refused"; +@@ -182,7 +190,7 @@ static int meth_sendto(lua_State *L) { + return 2; + } + timeout_markstart(tm); +- err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, ++ err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, + (socklen_t) ai->ai_addrlen, tm); + freeaddrinfo(ai); + if (err != IO_DONE) { +@@ -199,71 +207,80 @@ static int meth_sendto(lua_State *L) { + \*-------------------------------------------------------------------------*/ + static int meth_receive(lua_State *L) { + p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); +- char buffer[UDP_DATAGRAMSIZE]; +- size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); ++ char buf[UDP_DATAGRAMSIZE]; ++ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); ++ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; + int err; + p_timeout tm = &udp->tm; +- count = MIN(count, sizeof(buffer)); + timeout_markstart(tm); +- err = socket_recv(&udp->sock, buffer, count, &got, tm); ++ if (!dgram) { ++ lua_pushnil(L); ++ lua_pushliteral(L, "out of memory"); ++ return 2; ++ } ++ err = socket_recv(&udp->sock, dgram, wanted, &got, tm); + /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ +- if (err == IO_CLOSED) +- err = IO_DONE; +- if (err != IO_DONE) { ++ if (err != IO_DONE && err != IO_CLOSED) { + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); ++ if (wanted > sizeof(buf)) free(dgram); + return 2; + } +- lua_pushlstring(L, buffer, got); ++ lua_pushlstring(L, dgram, got); ++ if (wanted > sizeof(buf)) free(dgram); + return 1; + } + + /*-------------------------------------------------------------------------*\ + * Receives data and sender from a UDP socket + \*-------------------------------------------------------------------------*/ +-static int meth_receivefrom(lua_State *L) +-{ ++static int meth_receivefrom(lua_State *L) { + p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); +- char buffer[UDP_DATAGRAMSIZE]; +- size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); +- int err; +- p_timeout tm = &udp->tm; ++ char buf[UDP_DATAGRAMSIZE]; ++ size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); ++ char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + char addrstr[INET6_ADDRSTRLEN]; + char portstr[6]; ++ int err; ++ p_timeout tm = &udp->tm; + timeout_markstart(tm); +- count = MIN(count, sizeof(buffer)); +- err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, ++ if (!dgram) { ++ lua_pushnil(L); ++ lua_pushliteral(L, "out of memory"); ++ return 2; ++ } ++ err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, + &addr_len, tm); + /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ +- if (err == IO_CLOSED) +- err = IO_DONE; +- if (err != IO_DONE) { ++ if (err != IO_DONE && err != IO_CLOSED) { + lua_pushnil(L); + lua_pushstring(L, udp_strerror(err)); ++ if (wanted > sizeof(buf)) free(dgram); + return 2; + } +- err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, ++ err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, + INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); + if (err) { + lua_pushnil(L); + lua_pushstring(L, gai_strerror(err)); ++ if (wanted > sizeof(buf)) free(dgram); + return 2; + } +- lua_pushlstring(L, buffer, got); ++ lua_pushlstring(L, dgram, got); + lua_pushstring(L, addrstr); + lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); ++ if (wanted > sizeof(buf)) free(dgram); + return 3; + } + + /*-------------------------------------------------------------------------*\ + * Returns family as string + \*-------------------------------------------------------------------------*/ +-static int meth_getfamily(lua_State *L) +-{ ++static int meth_getfamily(lua_State *L) { + p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); +- if (udp->family == PF_INET6) { ++ if (udp->family == AF_INET6) { + lua_pushliteral(L, "inet6"); + return 1; + } else { +@@ -332,6 +349,11 @@ static int meth_settimeout(lua_State *L) { + return timeout_meth_settimeout(L, &udp->tm); + } + ++static int meth_gettimeout(lua_State *L) { ++ p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); ++ return timeout_meth_gettimeout(L, &udp->tm); ++} ++ + /*-------------------------------------------------------------------------*\ + * Turns a master udp object into a client object. + \*-------------------------------------------------------------------------*/ +@@ -348,7 +370,7 @@ static int meth_setpeername(lua_State *L) { + /* make sure we try to connect only to the same family */ + connecthints.ai_family = udp->family; + if (connecting) { +- err = inet_tryconnect(&udp->sock, &udp->family, address, ++ err = inet_tryconnect(&udp->sock, &udp->family, address, + port, tm, &connecthints); + if (err) { + lua_pushnil(L); +@@ -362,7 +384,6 @@ static int meth_setpeername(lua_State *L) { + inet_trydisconnect(&udp->sock, udp->family, tm); + auxiliar_setclass(L, "udp{unconnected}", 1); + } +- /* change class to connected or unconnected depending on address */ + lua_pushnumber(L, 1); + return 1; + } +@@ -390,7 +411,7 @@ static int meth_setsockname(lua_State *L) { + bindhints.ai_socktype = SOCK_DGRAM; + bindhints.ai_family = udp->family; + bindhints.ai_flags = AI_PASSIVE; +- err = inet_trybind(&udp->sock, address, port, &bindhints); ++ err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); +@@ -407,32 +428,32 @@ static int meth_setsockname(lua_State *L) { + * Creates a master udp object + \*-------------------------------------------------------------------------*/ + static int udp_create(lua_State *L, int family) { +- t_socket sock; +- const char *err = inet_trycreate(&sock, family, SOCK_DGRAM); +- /* try to allocate a system socket */ +- if (!err) { +- /* allocate udp object */ +- p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); +- auxiliar_setclass(L, "udp{unconnected}", -1); +- /* initialize remaining structure fields */ +- socket_setnonblocking(&sock); +- if (family == PF_INET6) { +- int yes = 1; +- setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, +- (void *)&yes, sizeof(yes)); ++ /* allocate udp object */ ++ p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); ++ auxiliar_setclass(L, "udp{unconnected}", -1); ++ /* if family is AF_UNSPEC, we leave the socket invalid and ++ * store AF_UNSPEC into family. This will allow it to later be ++ * replaced with an AF_INET6 or AF_INET socket upon first use. */ ++ udp->sock = SOCKET_INVALID; ++ timeout_init(&udp->tm, -1, -1); ++ udp->family = family; ++ if (family != AF_UNSPEC) { ++ const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0); ++ if (err != NULL) { ++ lua_pushnil(L); ++ lua_pushstring(L, err); ++ return 2; + } +- udp->sock = sock; +- timeout_init(&udp->tm, -1, -1); +- udp->family = family; +- return 1; +- } else { +- lua_pushnil(L); +- lua_pushstring(L, err); +- return 2; ++ socket_setnonblocking(&udp->sock); + } ++ return 1; + } + + static int global_create(lua_State *L) { ++ return udp_create(L, AF_UNSPEC); ++} ++ ++static int global_create4(lua_State *L) { + return udp_create(L, AF_INET); + } + +diff --git a/src/udp.h b/src/udp.h +index 2b831a5..be9b6a5 100644 +--- a/src/udp.h ++++ b/src/udp.h +@@ -8,7 +8,7 @@ + * (AF_INET, SOCK_DGRAM). + * + * Two classes are defined: connected and unconnected. UDP objects are +-* originally unconnected. They can be "connected" to a given address ++* originally unconnected. They can be "connected" to a given address + * with a call to the setpeername function. The same function can be used to + * break the connection. + \*=========================================================================*/ +@@ -17,7 +17,6 @@ + #include "timeout.h" + #include "socket.h" + +-/* can't be larger than wsocket.c MAXCHUNK!!! */ + #define UDP_DATAGRAMSIZE 8192 + + typedef struct t_udp_ { +diff --git a/src/unix.c b/src/unix.c +index 91aaaf8..5bc3148 100644 +--- a/src/unix.c ++++ b/src/unix.c +@@ -1,8 +1,8 @@ + /*=========================================================================*\ +-* Unix domain socket ++* Unix domain socket + * LuaSocket toolkit + \*=========================================================================*/ +-#include <string.h> ++#include <string.h> + + #include "lua.h" + #include "lauxlib.h" +@@ -11,7 +11,7 @@ + #include "socket.h" + #include "options.h" + #include "unix.h" +-#include <sys/un.h> ++#include <sys/un.h> + + /*=========================================================================*\ + * Internal function prototypes +@@ -68,15 +68,6 @@ static t_opt optset[] = { + {NULL, NULL} + }; + +-/* our socket creation function */ +-/* this is an ad-hoc module that returns a single function +- * as such, do not include other functions in this array. */ +-static luaL_Reg func[] = { +- {"unix", global_create}, +- {NULL, NULL} +-}; +- +- + /*-------------------------------------------------------------------------*\ + * Initializes module + \*-------------------------------------------------------------------------*/ +@@ -89,15 +80,8 @@ int luaopen_socket_unix(lua_State *L) { + auxiliar_add2group(L, "unix{master}", "unix{any}"); + auxiliar_add2group(L, "unix{client}", "unix{any}"); + auxiliar_add2group(L, "unix{server}", "unix{any}"); +-#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) +- lua_pushcfunction(L, global_create); +- (void) func; +-#else +- /* set function into socket namespace */ +- luaL_openlib(L, "socket", func, 0); +- lua_pushcfunction(L, global_create); +-#endif + /* return the function instead of the 'socket' table */ ++ lua_pushcfunction(L, global_create); + return 1; + } + +@@ -147,7 +131,7 @@ static int meth_getfd(lua_State *L) { + /* this is very dangerous, but can be handy for those that are brave enough */ + static int meth_setfd(lua_State *L) { + p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); +- un->sock = (t_socket) luaL_checknumber(L, 2); ++ un->sock = (t_socket) luaL_checknumber(L, 2); + return 0; + } + +@@ -158,8 +142,8 @@ static int meth_dirty(lua_State *L) { + } + + /*-------------------------------------------------------------------------*\ +-* Waits for and returns a client object attempting connection to the +-* server object ++* Waits for and returns a client object attempting connection to the ++* server object + \*-------------------------------------------------------------------------*/ + static int meth_accept(lua_State *L) { + p_unix server = (p_unix) auxiliar_checkclass(L, "unix{server}", 1); +@@ -173,20 +157,20 @@ static int meth_accept(lua_State *L) { + /* initialize structure fields */ + socket_setnonblocking(&sock); + clnt->sock = sock; +- io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv, ++ io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv, + (p_error) socket_ioerror, &clnt->sock); + timeout_init(&clnt->tm, -1, -1); + buffer_init(&clnt->buf, &clnt->io, &clnt->tm); + return 1; + } else { +- lua_pushnil(L); ++ lua_pushnil(L); + lua_pushstring(L, socket_strerror(err)); + return 2; + } + } + + /*-------------------------------------------------------------------------*\ +-* Binds an object to an address ++* Binds an object to an address + \*-------------------------------------------------------------------------*/ + static const char *unix_trybind(p_unix un, const char *path) { + struct sockaddr_un local; +@@ -197,16 +181,16 @@ static const char *unix_trybind(p_unix un, const char *path) { + strcpy(local.sun_path, path); + local.sun_family = AF_UNIX; + #ifdef UNIX_HAS_SUN_LEN +- local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) ++ local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) + + len + 1; + err = socket_bind(&un->sock, (SA *) &local, local.sun_len); + +-#else +- err = socket_bind(&un->sock, (SA *) &local, ++#else ++ err = socket_bind(&un->sock, (SA *) &local, + sizeof(local.sun_family) + len); + #endif + if (err != IO_DONE) socket_destroy(&un->sock); +- return socket_strerror(err); ++ return socket_strerror(err); + } + + static int meth_bind(lua_State *L) { +@@ -236,11 +220,11 @@ static const char *unix_tryconnect(p_unix un, const char *path) + remote.sun_family = AF_UNIX; + timeout_markstart(&un->tm); + #ifdef UNIX_HAS_SUN_LEN +- remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) ++ remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) + + len + 1; + err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm); + #else +- err = socket_connect(&un->sock, (SA *) &remote, ++ err = socket_connect(&un->sock, (SA *) &remote, + sizeof(remote.sun_family) + len, &un->tm); + #endif + if (err != IO_DONE) socket_destroy(&un->sock); +@@ -264,7 +248,7 @@ static int meth_connect(lua_State *L) + } + + /*-------------------------------------------------------------------------*\ +-* Closes socket used by object ++* Closes socket used by object + \*-------------------------------------------------------------------------*/ + static int meth_close(lua_State *L) + { +@@ -319,13 +303,13 @@ static int meth_settimeout(lua_State *L) { + * Library functions + \*=========================================================================*/ + /*-------------------------------------------------------------------------*\ +-* Creates a master unix object ++* Creates a master unix object + \*-------------------------------------------------------------------------*/ + static int global_create(lua_State *L) { + t_socket sock; + int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0); + /* try to allocate a system socket */ +- if (err == IO_DONE) { ++ if (err == IO_DONE) { + /* allocate unix object */ + p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); + /* set its type as master object */ +@@ -333,7 +317,7 @@ static int global_create(lua_State *L) { + /* initialize remaining structure fields */ + socket_setnonblocking(&sock); + un->sock = sock; +- io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, ++ io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv, + (p_error) socket_ioerror, &un->sock); + timeout_init(&un->tm, -1, -1); + buffer_init(&un->buf, &un->io, &un->tm); +diff --git a/src/url.lua b/src/url.lua +index 7809535..fbd93d1 100644 +--- a/src/url.lua ++++ b/src/url.lua +@@ -219,6 +219,7 @@ end + -- corresponding absolute url + ----------------------------------------------------------------------------- + function _M.absolute(base_url, relative_url) ++ local base_parsed + if base.type(base_url) == "table" then + base_parsed = base_url + base_url = _M.build(base_parsed) +diff --git a/src/usocket.c b/src/usocket.c +index 096ecd0..8adc573 100644 +--- a/src/usocket.c ++++ b/src/usocket.c +@@ -4,12 +4,13 @@ + * + * The code is now interrupt-safe. + * The penalty of calling select to avoid busy-wait is only paid when +-* the I/O call fail in the first place. ++* the I/O call fail in the first place. + \*=========================================================================*/ +-#include <string.h> ++#include <string.h> + #include <signal.h> + + #include "socket.h" ++#include "pierror.h" + + /*-------------------------------------------------------------------------*\ + * Wait for readable/writable/connected socket with timeout +@@ -72,7 +73,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { + + + /*-------------------------------------------------------------------------*\ +-* Initializes module ++* Initializes module + \*-------------------------------------------------------------------------*/ + int socket_open(void) { + /* instals a handler to ignore sigpipe or it will crash us */ +@@ -81,7 +82,7 @@ int socket_open(void) { + } + + /*-------------------------------------------------------------------------*\ +-* Close module ++* Close module + \*-------------------------------------------------------------------------*/ + int socket_close(void) { + return 1; +@@ -92,7 +93,6 @@ int socket_close(void) { + \*-------------------------------------------------------------------------*/ + void socket_destroy(p_socket ps) { + if (*ps != SOCKET_INVALID) { +- socket_setblocking(ps); + close(*ps); + *ps = SOCKET_INVALID; + } +@@ -101,7 +101,7 @@ void socket_destroy(p_socket ps) { + /*-------------------------------------------------------------------------*\ + * Select with timeout control + \*-------------------------------------------------------------------------*/ +-int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, ++int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, + p_timeout tm) { + int ret; + do { +@@ -120,8 +120,8 @@ int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, + \*-------------------------------------------------------------------------*/ + int socket_create(p_socket ps, int domain, int type, int protocol) { + *ps = socket(domain, type, protocol); +- if (*ps != SOCKET_INVALID) return IO_DONE; +- else return errno; ++ if (*ps != SOCKET_INVALID) return IO_DONE; ++ else return errno; + } + + /*-------------------------------------------------------------------------*\ +@@ -130,29 +130,25 @@ int socket_create(p_socket ps, int domain, int type, int protocol) { + int socket_bind(p_socket ps, SA *addr, socklen_t len) { + int err = IO_DONE; + socket_setblocking(ps); +- if (bind(*ps, addr, len) < 0) err = errno; ++ if (bind(*ps, addr, len) < 0) err = errno; + socket_setnonblocking(ps); + return err; + } + + /*-------------------------------------------------------------------------*\ +-* ++* + \*-------------------------------------------------------------------------*/ + int socket_listen(p_socket ps, int backlog) { +- int err = IO_DONE; +- socket_setblocking(ps); +- if (listen(*ps, backlog)) err = errno; +- socket_setnonblocking(ps); ++ int err = IO_DONE; ++ if (listen(*ps, backlog)) err = errno; + return err; + } + + /*-------------------------------------------------------------------------*\ +-* ++* + \*-------------------------------------------------------------------------*/ + void socket_shutdown(p_socket ps, int how) { +- socket_setblocking(ps); + shutdown(*ps, how); +- socket_setnonblocking(ps); + } + + /*-------------------------------------------------------------------------*\ +@@ -166,7 +162,7 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { + do if (connect(*ps, addr, len) == 0) return IO_DONE; + while ((err = errno) == EINTR); + /* if connection failed immediately, return error code */ +- if (err != EINPROGRESS && err != EAGAIN) return err; ++ if (err != EINPROGRESS && err != EAGAIN) return err; + /* zero timeout case optimization */ + if (timeout_iszero(tm)) return IO_TIMEOUT; + /* wait until we have the result of the connection attempt or timeout */ +@@ -181,7 +177,7 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { + * Accept with timeout + \*-------------------------------------------------------------------------*/ + int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { +- if (*ps == SOCKET_INVALID) return IO_CLOSED; ++ if (*ps == SOCKET_INVALID) return IO_CLOSED; + for ( ;; ) { + int err; + if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; +@@ -197,7 +193,7 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout + /*-------------------------------------------------------------------------*\ + * Send with timeout + \*-------------------------------------------------------------------------*/ +-int socket_send(p_socket ps, const char *data, size_t count, ++int socket_send(p_socket ps, const char *data, size_t count, + size_t *sent, p_timeout tm) + { + int err; +@@ -215,6 +211,8 @@ int socket_send(p_socket ps, const char *data, size_t count, + err = errno; + /* EPIPE means the connection was closed */ + if (err == EPIPE) return IO_CLOSED; ++ /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/ ++ if (err == EPROTOTYPE) continue; + /* we call was interrupted, just try again */ + if (err == EINTR) continue; + /* if failed fatal reason, report error */ +@@ -229,20 +227,21 @@ int socket_send(p_socket ps, const char *data, size_t count, + /*-------------------------------------------------------------------------*\ + * Sendto with timeout + \*-------------------------------------------------------------------------*/ +-int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, ++int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, + SA *addr, socklen_t len, p_timeout tm) + { + int err; + *sent = 0; + if (*ps == SOCKET_INVALID) return IO_CLOSED; + for ( ;; ) { +- long put = (long) sendto(*ps, data, count, 0, addr, len); ++ long put = (long) sendto(*ps, data, count, 0, addr, len); + if (put >= 0) { + *sent = put; + return IO_DONE; + } + err = errno; + if (err == EPIPE) return IO_CLOSED; ++ if (err == EPROTOTYPE) continue; + if (err == EINTR) continue; + if (err != EAGAIN) return err; + if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; +@@ -266,8 +265,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm + err = errno; + if (taken == 0) return IO_CLOSED; + if (err == EINTR) continue; +- if (err != EAGAIN) return err; +- if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; ++ if (err != EAGAIN) return err; ++ if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; + } + return IO_UNKNOWN; + } +@@ -275,7 +274,7 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm + /*-------------------------------------------------------------------------*\ + * Recvfrom with timeout + \*-------------------------------------------------------------------------*/ +-int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, ++int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, + SA *addr, socklen_t *len, p_timeout tm) { + int err; + *got = 0; +@@ -289,8 +288,8 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, + err = errno; + if (taken == 0) return IO_CLOSED; + if (err == EINTR) continue; +- if (err != EAGAIN) return err; +- if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; ++ if (err != EAGAIN) return err; ++ if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; + } + return IO_UNKNOWN; + } +@@ -303,7 +302,7 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, + * with send/recv replaced with write/read. We can't just use write/read + * in the socket version, because behaviour when size is zero is different. + \*-------------------------------------------------------------------------*/ +-int socket_write(p_socket ps, const char *data, size_t count, ++int socket_write(p_socket ps, const char *data, size_t count, + size_t *sent, p_timeout tm) + { + int err; +@@ -321,6 +320,8 @@ int socket_write(p_socket ps, const char *data, size_t count, + err = errno; + /* EPIPE means the connection was closed */ + if (err == EPIPE) return IO_CLOSED; ++ /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/ ++ if (err == EPROTOTYPE) continue; + /* we call was interrupted, just try again */ + if (err == EINTR) continue; + /* if failed fatal reason, report error */ +@@ -349,8 +350,8 @@ int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm + err = errno; + if (taken == 0) return IO_CLOSED; + if (err == EINTR) continue; +- if (err != EAGAIN) return err; +- if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; ++ if (err != EAGAIN) return err; ++ if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; + } + return IO_UNKNOWN; + } +@@ -374,7 +375,7 @@ void socket_setnonblocking(p_socket ps) { + } + + /*-------------------------------------------------------------------------*\ +-* DNS helpers ++* DNS helpers + \*-------------------------------------------------------------------------*/ + int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { + *hp = gethostbyaddr(addr, len, AF_INET); +@@ -399,7 +400,7 @@ int socket_gethostbyname(const char *addr, struct hostent **hp) { + const char *socket_hoststrerror(int err) { + if (err <= 0) return io_strerror(err); + switch (err) { +- case HOST_NOT_FOUND: return "host not found"; ++ case HOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; + default: return hstrerror(err); + } + } +@@ -407,42 +408,43 @@ const char *socket_hoststrerror(int err) { + const char *socket_strerror(int err) { + if (err <= 0) return io_strerror(err); + switch (err) { +- case EADDRINUSE: return "address already in use"; +- case EISCONN: return "already connected"; +- case EACCES: return "permission denied"; +- case ECONNREFUSED: return "connection refused"; +- case ECONNABORTED: return "closed"; +- case ECONNRESET: return "closed"; +- case ETIMEDOUT: return "timeout"; +- default: return strerror(err); ++ case EADDRINUSE: return PIE_ADDRINUSE; ++ case EISCONN: return PIE_ISCONN; ++ case EACCES: return PIE_ACCESS; ++ case ECONNREFUSED: return PIE_CONNREFUSED; ++ case ECONNABORTED: return PIE_CONNABORTED; ++ case ECONNRESET: return PIE_CONNRESET; ++ case ETIMEDOUT: return PIE_TIMEDOUT; ++ default: { ++ return strerror(err); ++ } + } + } + + const char *socket_ioerror(p_socket ps, int err) { + (void) ps; + return socket_strerror(err); +-} ++} + + const char *socket_gaistrerror(int err) { +- if (err == 0) return NULL; ++ if (err == 0) return NULL; + switch (err) { +- case EAI_AGAIN: return "temporary failure in name resolution"; +- case EAI_BADFLAGS: return "invalid value for ai_flags"; ++ case EAI_AGAIN: return PIE_AGAIN; ++ case EAI_BADFLAGS: return PIE_BADFLAGS; + #ifdef EAI_BADHINTS +- case EAI_BADHINTS: return "invalid value for hints"; ++ case EAI_BADHINTS: return PIE_BADHINTS; + #endif +- case EAI_FAIL: return "non-recoverable failure in name resolution"; +- case EAI_FAMILY: return "ai_family not supported"; +- case EAI_MEMORY: return "memory allocation failure"; +- case EAI_NONAME: +- return "host or service not provided, or not known"; +- case EAI_OVERFLOW: return "argument buffer overflow"; ++ case EAI_FAIL: return PIE_FAIL; ++ case EAI_FAMILY: return PIE_FAMILY; ++ case EAI_MEMORY: return PIE_MEMORY; ++ case EAI_NONAME: return PIE_NONAME; ++ case EAI_OVERFLOW: return PIE_OVERFLOW; + #ifdef EAI_PROTOCOL +- case EAI_PROTOCOL: return "resolved protocol is unknown"; ++ case EAI_PROTOCOL: return PIE_PROTOCOL; + #endif +- case EAI_SERVICE: return "service not supported for socket type"; +- case EAI_SOCKTYPE: return "ai_socktype not supported"; +- case EAI_SYSTEM: return strerror(errno); ++ case EAI_SERVICE: return PIE_SERVICE; ++ case EAI_SOCKTYPE: return PIE_SOCKTYPE; ++ case EAI_SYSTEM: return strerror(errno); + default: return gai_strerror(err); + } + } +diff --git a/src/wsocket.c b/src/wsocket.c +index b4a4384..8ecb0fc 100644 +--- a/src/wsocket.c ++++ b/src/wsocket.c +@@ -3,33 +3,34 @@ + * LuaSocket toolkit + * + * The penalty of calling select to avoid busy-wait is only paid when +-* the I/O call fail in the first place. ++* the I/O call fail in the first place. + \*=========================================================================*/ + #include <string.h> + + #include "socket.h" ++#include "pierror.h" + + /* WinSock doesn't have a strerror... */ + static const char *wstrerror(int err); + + /*-------------------------------------------------------------------------*\ +-* Initializes module ++* Initializes module + \*-------------------------------------------------------------------------*/ + int socket_open(void) { + WSADATA wsaData; +- WORD wVersionRequested = MAKEWORD(2, 0); ++ WORD wVersionRequested = MAKEWORD(2, 0); + int err = WSAStartup(wVersionRequested, &wsaData ); + if (err != 0) return 0; + if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && + (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { + WSACleanup(); +- return 0; ++ return 0; + } + return 1; + } + + /*-------------------------------------------------------------------------*\ +-* Close module ++* Close module + \*-------------------------------------------------------------------------*/ + int socket_close(void) { + WSACleanup(); +@@ -50,10 +51,10 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { + struct timeval tv, *tp = NULL; + double t; + if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ +- if (sw & WAITFD_R) { +- FD_ZERO(&rfds); ++ if (sw & WAITFD_R) { ++ FD_ZERO(&rfds); + FD_SET(*ps, &rfds); +- rp = &rfds; ++ rp = &rfds; + } + if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } + if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } +@@ -72,9 +73,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { + /*-------------------------------------------------------------------------*\ + * Select with int timeout in ms + \*-------------------------------------------------------------------------*/ +-int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, ++int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, + p_timeout tm) { +- struct timeval tv; ++ struct timeval tv; + double t = timeout_get(tm); + tv.tv_sec = (int) t; + tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); +@@ -96,7 +97,7 @@ void socket_destroy(p_socket ps) { + } + + /*-------------------------------------------------------------------------*\ +-* ++* + \*-------------------------------------------------------------------------*/ + void socket_shutdown(p_socket ps, int how) { + socket_setblocking(ps); +@@ -134,10 +135,10 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { + /* give windows time to set the error (yes, disgusting) */ + Sleep(10); + /* find out why we failed */ +- getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); ++ getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); + /* we KNOW there was an error. if 'why' is 0, we will return + * "unknown error", but it's not really our fault */ +- return err > 0? err: IO_UNKNOWN; ++ return err > 0? err: IO_UNKNOWN; + } else return err; + + } +@@ -154,7 +155,7 @@ int socket_bind(p_socket ps, SA *addr, socklen_t len) { + } + + /*-------------------------------------------------------------------------*\ +-* ++* + \*-------------------------------------------------------------------------*/ + int socket_listen(p_socket ps, int backlog) { + int err = IO_DONE; +@@ -167,7 +168,7 @@ int socket_listen(p_socket ps, int backlog) { + /*-------------------------------------------------------------------------*\ + * Accept with timeout + \*-------------------------------------------------------------------------*/ +-int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, ++int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, + p_timeout tm) { + if (*ps == SOCKET_INVALID) return IO_CLOSED; + for ( ;; ) { +@@ -175,21 +176,21 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, + /* try to get client socket */ + if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; + /* find out why we failed */ +- err = WSAGetLastError(); ++ err = WSAGetLastError(); + /* if we failed because there was no connectoin, keep trying */ + if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; + /* call select to avoid busy wait */ + if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; +- } ++ } + } + + /*-------------------------------------------------------------------------*\ + * Send with timeout +-* On windows, if you try to send 10MB, the OS will buffer EVERYTHING +-* this can take an awful lot of time and we will end up blocked. ++* On windows, if you try to send 10MB, the OS will buffer EVERYTHING ++* this can take an awful lot of time and we will end up blocked. + * Therefore, whoever calls this function should not pass a huge buffer. + \*-------------------------------------------------------------------------*/ +-int socket_send(p_socket ps, const char *data, size_t count, ++int socket_send(p_socket ps, const char *data, size_t count, + size_t *sent, p_timeout tm) + { + int err; +@@ -206,18 +207,18 @@ int socket_send(p_socket ps, const char *data, size_t count, + return IO_DONE; + } + /* deal with failure */ +- err = WSAGetLastError(); ++ err = WSAGetLastError(); + /* we can only proceed if there was no serious error */ + if (err != WSAEWOULDBLOCK) return err; + /* avoid busy wait */ + if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; +- } ++ } + } + + /*-------------------------------------------------------------------------*\ + * Sendto with timeout + \*-------------------------------------------------------------------------*/ +-int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, ++int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, + SA *addr, socklen_t len, p_timeout tm) + { + int err; +@@ -229,17 +230,17 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, + *sent = put; + return IO_DONE; + } +- err = WSAGetLastError(); ++ err = WSAGetLastError(); + if (err != WSAEWOULDBLOCK) return err; + if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; +- } ++ } + } + + /*-------------------------------------------------------------------------*\ + * Receive with timeout + \*-------------------------------------------------------------------------*/ +-int socket_recv(p_socket ps, char *data, size_t count, size_t *got, +- p_timeout tm) ++int socket_recv(p_socket ps, char *data, size_t count, size_t *got, ++ p_timeout tm) + { + int err, prev = IO_DONE; + *got = 0; +@@ -252,9 +253,9 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, + } + if (taken == 0) return IO_CLOSED; + err = WSAGetLastError(); +- /* On UDP, a connreset simply means the previous send failed. +- * So we try again. +- * On TCP, it means our socket is now useless, so the error passes. ++ /* On UDP, a connreset simply means the previous send failed. ++ * So we try again. ++ * On TCP, it means our socket is now useless, so the error passes. + * (We will loop again, exiting because the same error will happen) */ + if (err != WSAEWOULDBLOCK) { + if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; +@@ -267,8 +268,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, + /*-------------------------------------------------------------------------*\ + * Recvfrom with timeout + \*-------------------------------------------------------------------------*/ +-int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, +- SA *addr, socklen_t *len, p_timeout tm) ++int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, ++ SA *addr, socklen_t *len, p_timeout tm) + { + int err, prev = IO_DONE; + *got = 0; +@@ -281,8 +282,8 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, + } + if (taken == 0) return IO_CLOSED; + err = WSAGetLastError(); +- /* On UDP, a connreset simply means the previous send failed. +- * So we try again. ++ /* On UDP, a connreset simply means the previous send failed. ++ * So we try again. + * On TCP, it means our socket is now useless, so the error passes. + * (We will loop again, exiting because the same error will happen) */ + if (err != WSAEWOULDBLOCK) { +@@ -310,7 +311,7 @@ void socket_setnonblocking(p_socket ps) { + } + + /*-------------------------------------------------------------------------*\ +-* DNS helpers ++* DNS helpers + \*-------------------------------------------------------------------------*/ + int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { + *hp = gethostbyaddr(addr, len, AF_INET); +@@ -330,21 +331,21 @@ int socket_gethostbyname(const char *addr, struct hostent **hp) { + const char *socket_hoststrerror(int err) { + if (err <= 0) return io_strerror(err); + switch (err) { +- case WSAHOST_NOT_FOUND: return "host not found"; +- default: return wstrerror(err); ++ case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; ++ default: return wstrerror(err); + } + } + + const char *socket_strerror(int err) { + if (err <= 0) return io_strerror(err); + switch (err) { +- case WSAEADDRINUSE: return "address already in use"; +- case WSAECONNREFUSED: return "connection refused"; +- case WSAEISCONN: return "already connected"; +- case WSAEACCES: return "permission denied"; +- case WSAECONNABORTED: return "closed"; +- case WSAECONNRESET: return "closed"; +- case WSAETIMEDOUT: return "timeout"; ++ case WSAEADDRINUSE: return PIE_ADDRINUSE; ++ case WSAECONNREFUSED : return PIE_CONNREFUSED; ++ case WSAEISCONN: return PIE_ISCONN; ++ case WSAEACCES: return PIE_ACCESS; ++ case WSAECONNABORTED: return PIE_CONNABORTED; ++ case WSAECONNRESET: return PIE_CONNRESET; ++ case WSAETIMEDOUT: return PIE_TIMEDOUT; + default: return wstrerror(err); + } + } +@@ -357,7 +358,7 @@ const char *socket_ioerror(p_socket ps, int err) { + static const char *wstrerror(int err) { + switch (err) { + case WSAEINTR: return "Interrupted function call"; +- case WSAEACCES: return "Permission denied"; ++ case WSAEACCES: return PIE_ACCESS; // "Permission denied"; + case WSAEFAULT: return "Bad address"; + case WSAEINVAL: return "Invalid argument"; + case WSAEMFILE: return "Too many open files"; +@@ -370,63 +371,61 @@ static const char *wstrerror(int err) { + case WSAEPROTOTYPE: return "Protocol wrong type for socket"; + case WSAENOPROTOOPT: return "Bad protocol option"; + case WSAEPROTONOSUPPORT: return "Protocol not supported"; +- case WSAESOCKTNOSUPPORT: return "Socket type not supported"; ++ case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported"; + case WSAEOPNOTSUPP: return "Operation not supported"; + case WSAEPFNOSUPPORT: return "Protocol family not supported"; +- case WSAEAFNOSUPPORT: +- return "Address family not supported by protocol family"; +- case WSAEADDRINUSE: return "Address already in use"; ++ case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family"; ++ case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use"; + case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; + case WSAENETDOWN: return "Network is down"; + case WSAENETUNREACH: return "Network is unreachable"; + case WSAENETRESET: return "Network dropped connection on reset"; + case WSAECONNABORTED: return "Software caused connection abort"; +- case WSAECONNRESET: return "Connection reset by peer"; ++ case WSAECONNRESET: return PIE_CONNRESET; // "Connection reset by peer"; + case WSAENOBUFS: return "No buffer space available"; +- case WSAEISCONN: return "Socket is already connected"; ++ case WSAEISCONN: return PIE_ISCONN; // "Socket is already connected"; + case WSAENOTCONN: return "Socket is not connected"; + case WSAESHUTDOWN: return "Cannot send after socket shutdown"; +- case WSAETIMEDOUT: return "Connection timed out"; +- case WSAECONNREFUSED: return "Connection refused"; ++ case WSAETIMEDOUT: return PIE_TIMEDOUT; // "Connection timed out"; ++ case WSAECONNREFUSED: return PIE_CONNREFUSED; // "Connection refused"; + case WSAEHOSTDOWN: return "Host is down"; + case WSAEHOSTUNREACH: return "No route to host"; + case WSAEPROCLIM: return "Too many processes"; + case WSASYSNOTREADY: return "Network subsystem is unavailable"; + case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; +- case WSANOTINITIALISED: ++ case WSANOTINITIALISED: + return "Successful WSAStartup not yet performed"; + case WSAEDISCON: return "Graceful shutdown in progress"; +- case WSAHOST_NOT_FOUND: return "Host not found"; ++ case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found"; + case WSATRY_AGAIN: return "Nonauthoritative host not found"; +- case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; ++ case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error"; + case WSANO_DATA: return "Valid name, no data record of requested type"; + default: return "Unknown error"; + } + } + + const char *socket_gaistrerror(int err) { +- if (err == 0) return NULL; ++ if (err == 0) return NULL; + switch (err) { +- case EAI_AGAIN: return "temporary failure in name resolution"; +- case EAI_BADFLAGS: return "invalid value for ai_flags"; ++ case EAI_AGAIN: return PIE_AGAIN; ++ case EAI_BADFLAGS: return PIE_BADFLAGS; + #ifdef EAI_BADHINTS +- case EAI_BADHINTS: return "invalid value for hints"; ++ case EAI_BADHINTS: return PIE_BADHINTS; + #endif +- case EAI_FAIL: return "non-recoverable failure in name resolution"; +- case EAI_FAMILY: return "ai_family not supported"; +- case EAI_MEMORY: return "memory allocation failure"; +- case EAI_NONAME: +- return "host or service not provided, or not known"; ++ case EAI_FAIL: return PIE_FAIL; ++ case EAI_FAMILY: return PIE_FAMILY; ++ case EAI_MEMORY: return PIE_MEMORY; ++ case EAI_NONAME: return PIE_NONAME; + #ifdef EAI_OVERFLOW +- case EAI_OVERFLOW: return "argument buffer overflow"; ++ case EAI_OVERFLOW: return PIE_OVERFLOW; + #endif + #ifdef EAI_PROTOCOL +- case EAI_PROTOCOL: return "resolved protocol is unknown"; ++ case EAI_PROTOCOL: return PIE_PROTOCOL; + #endif +- case EAI_SERVICE: return "service not supported for socket type"; +- case EAI_SOCKTYPE: return "ai_socktype not supported"; ++ case EAI_SERVICE: return PIE_SERVICE; ++ case EAI_SOCKTYPE: return PIE_SOCKTYPE; + #ifdef EAI_SYSTEM +- case EAI_SYSTEM: return strerror(errno); ++ case EAI_SYSTEM: return strerror(errno); + #endif + default: return gai_strerror(err); + } +diff --git a/test/auth/.htaccess b/test/auth/.htaccess +new file mode 100644 +index 0000000..bb2794a +--- /dev/null ++++ b/test/auth/.htaccess +@@ -0,0 +1,4 @@ ++AuthName "test-auth" ++ AuthType Basic ++ AuthUserFile /Users/diego/impa/luasocket/test/auth/.htpasswd ++ Require valid-user +diff --git a/test/auth/.htpasswd b/test/auth/.htpasswd +index fd9002b..cfb2603 100644 +--- a/test/auth/.htpasswd ++++ b/test/auth/.htpasswd +@@ -1 +1 @@ +-luasocket:l8n2npozPB.sQ ++luasocket:$apr1$47u2O.Me$.m/5BWAtt7GVoxsouIPBR1 +diff --git a/test/excepttest.lua b/test/excepttest.lua +index ce9f197..80c9cb8 100644 +--- a/test/excepttest.lua ++++ b/test/excepttest.lua +@@ -1,6 +1,30 @@ + local socket = require("socket") +-try = socket.newtry(function() +- print("finalized!!!") ++ ++local finalizer_called ++ ++local func = socket.protect(function(err, ...) ++ local try = socket.newtry(function() ++ finalizer_called = true ++ end) ++ ++ if err then ++ return error(err, 0) ++ else ++ return try(...) ++ end + end) +-try = socket.protect(try) +-print(try(nil, "it works")) ++ ++local ret1, ret2, ret3 = func(false, 1, 2, 3) ++assert(not finalizer_called, "unexpected finalizer call") ++assert(ret1 == 1 and ret2 == 2 and ret3 == 3, "incorrect return values") ++ ++ret1, ret2, ret3 = func(false, false, "error message") ++assert(finalizer_called, "finalizer not called") ++assert(ret1 == nil and ret2 == "error message" and ret3 == nil, "incorrect return values") ++ ++local err = {key = "value"} ++ret1, ret2 = pcall(func, err) ++assert(not ret1, "error not rethrown") ++assert(ret2 == err, "incorrect error rethrown") ++ ++print("OK") +diff --git a/test/httptest.lua b/test/httptest.lua +index d5fbb37..63ff921 100644 +--- a/test/httptest.lua ++++ b/test/httptest.lua +@@ -1,4 +1,4 @@ +--- needs Alias from /home/c/diego/tec/luasocket/test to ++-- needs Alias from /home/c/diego/tec/luasocket/test to + -- "/luasocket-test" and "/luasocket-test/" + -- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi + -- to "/luasocket-test-cgi" and "/luasocket-test-cgi/" +@@ -36,22 +36,22 @@ index = readfile(index_file) + local check_result = function(response, expect, ignore) + for i,v in pairs(response) do + if not ignore[i] then +- if v ~= expect[i] then ++ if v ~= expect[i] then + local f = io.open("err", "w") + f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i])) + f:close() +- fail(i .. " differs!") ++ fail(i .. " differs!") + end + end + end + for i,v in pairs(expect) do + if not ignore[i] then +- if v ~= response[i] then ++ if v ~= response[i] then + local f = io.open("err", "w") + f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v)) + v = string.sub(type(v) == "string" and v or "", 1, 70) + f:close() +- fail(i .. " differs!") ++ fail(i .. " differs!") + end + end + end +@@ -61,10 +61,10 @@ end + local check_request = function(request, expect, ignore) + local t + if not request.sink then request.sink, t = ltn12.sink.table() end +- request.source = request.source or ++ request.source = request.source or + (request.body and ltn12.source.string(request.body)) + local response = {} +- response.code, response.headers, response.status = ++ response.code, response.headers, response.status = + socket.skip(1, http.request(request)) + if t and #t > 0 then response.body = table.concat(t) end + check_result(response, expect, ignore) +@@ -82,7 +82,7 @@ else fail(back.query) end + ------------------------------------------------------------------------ + io.write("testing query string correctness: ") + forth = "this+is+the+query+string" +-back = http.request("http://" .. host .. cgiprefix .. ++back = http.request("http://" .. host .. cgiprefix .. + "/query-string?" .. forth) + if similar(back, forth) then print("ok") + else fail("failed!") end +@@ -120,10 +120,10 @@ check_request(request, expect, ignore) + ------------------------------------------------------------------------ + io.write("testing invalid url: ") + local r, e = http.request{url = host .. prefix} +-assert(r == nil and e == "invalid host ''") ++assert(r == nil and e == "invalid host ''") + r, re = http.request(host .. prefix) +-assert(r == nil and e == re, tostring(r) ..", " .. tostring(re) .. +- " vs " .. tostring(e)) ++assert(r == nil and e == re, tostring(r) ..", " .. tostring(re) .. ++ " vs " .. tostring(e)) + print("ok") + + io.write("testing invalid empty port: ") +@@ -212,7 +212,7 @@ os.remove(index_file .. "-back") + io.write("testing ltn12.(sink|source).chain and mime.(encode|decode): ") + + local function b64length(len) +- local a = math.ceil(len/3)*4 ++ local a = math.ceil(len/3)*4 + local l = math.ceil(a/76) + return a + l*2 + end +@@ -313,7 +313,7 @@ ignore = { + headers = 1 + } + check_request(request, expect, ignore) +- ++ + ------------------------------------------------------------------------ + io.write("testing document not found: ") + request = { +@@ -429,9 +429,9 @@ print("ok") + io.write("testing host not found: ") + local c, e = socket.connect("example.invalid", 80) + local r, re = http.request{url = "http://example.invalid/does/not/exist"} +-assert(r == nil and e == re, tostring(r) .. " " .. tostring(re)) ++assert(r == nil and e == re, tostring(r) .. " " .. tostring(re)) + r, re = http.request("http://example.invalid/does/not/exist") +-assert(r == nil and e == re) ++assert(r == nil and e == re) + print("ok") + + ------------------------------------------------------------------------ +diff --git a/test/ltn12test.lua b/test/ltn12test.lua +index 74a45e8..e3f85fb 100644 +--- a/test/ltn12test.lua ++++ b/test/ltn12test.lua +@@ -192,6 +192,21 @@ assert(filter(nil, 1), "filter not empty") + print("ok") + + -------------------------------- ++io.write("testing source.chain (with several filters): ") ++local function double(x) -- filter turning "ABC" into "AABBCC" ++ if not x then return end ++ local b={} ++ for k in x:gmatch'.' do table.insert(b, k..k) end ++ return table.concat(b) ++end ++source = ltn12.source.string(s) ++source = ltn12.source.chain(source, double, double, double) ++sink, t = ltn12.sink.table() ++assert(ltn12.pump.all(source, sink), "returned error") ++assert(table.concat(t) == double(double(double(s))), "mismatch") ++print("ok") ++ ++-------------------------------- + io.write("testing source.chain (with split) and sink.chain (with merge): ") + source = ltn12.source.string(s) + filter = split(5) +@@ -206,6 +221,15 @@ assert(filter2(nil, 1), "filter2 not empty") + print("ok") + + -------------------------------- ++io.write("testing sink.chain (with several filters): ") ++source = ltn12.source.string(s) ++sink, t = ltn12.sink.table() ++sink = ltn12.sink.chain(double, double, double, sink) ++assert(ltn12.pump.all(source, sink), "returned error") ++assert(table.concat(t) == double(double(double(s))), "mismatch") ++print("ok") ++ ++-------------------------------- + io.write("testing filter.chain (and sink.chain, with split, merge): ") + source = ltn12.source.string(s) + filter = split(5) +@@ -272,3 +296,4 @@ assert(filter3(nil, 1), "filter3 not empty") + assert(filter4(nil, 1), "filter4 not empty") + assert(filter5(nil, 1), "filter5 not empty") + print("ok") ++ +diff --git a/test/testclnt.lua b/test/testclnt.lua +index 315783b..170e187 100644 +--- a/test/testclnt.lua ++++ b/test/testclnt.lua +@@ -8,7 +8,7 @@ function printf(...) + end + + function pass(...) +- printf(...) ++ printf(...) + io.stderr:write("\n") + end + +@@ -45,30 +45,30 @@ function check_timeout(tm, sl, elapsed, err, opp, mode, alldone) + if not err then warn("must be buffered") + elseif err == "timeout" then pass("proper timeout") + else fail("unexpected error '%s'", err) end +- else +- if err ~= "timeout" then fail("should have timed out") ++ else ++ if err ~= "timeout" then fail("should have timed out") + else pass("proper timeout") end + end + else + if mode == "total" then +- if elapsed > tm then ++ if elapsed > tm then + if err ~= "timeout" then fail("should have timed out") + else pass("proper timeout") end + elseif elapsed < tm then +- if err then fail(err) ++ if err then fail(err) + else pass("ok") end +- else +- if alldone then +- if err then fail("unexpected error '%s'", err) ++ else ++ if alldone then ++ if err then fail("unexpected error '%s'", err) + else pass("ok") end + else +- if err ~= "timeout" then fail(err) ++ if err ~= "timeout" then fail(err) + else pass("proper timeoutk") end + end + end +- else +- if err then fail(err) +- else pass("ok") end ++ else ++ if err then fail(err) ++ else pass("ok") end + end + end + end +@@ -104,8 +104,8 @@ control:setoption("tcp-nodelay", true) + ------------------------------------------------------------------------ + function test_methods(sock, methods) + for _, v in pairs(methods) do +- if type(sock[v]) ~= "function" then +- fail(sock.class .. " method '" .. v .. "' not registered") ++ if type(sock[v]) ~= "function" then ++ fail(sock.class .. " method '" .. v .. "' not registered") + end + end + pass(sock.class .. " methods are ok") +@@ -121,7 +121,7 @@ function test_mixed(len) + local p3 = "raw " .. string.rep("z", inter) .. "bytes" + local p4 = "end" .. string.rep("w", inter) .. "bytes" + local bp1, bp2, bp3, bp4 +-remote (string.format("str = data:receive(%d)", ++remote (string.format("str = data:receive(%d)", + string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4))) + sent, err = data:send(p1..p2..p3..p4) + if err then fail(err) end +@@ -166,7 +166,7 @@ function test_rawline(len) + io.stderr:write("length " .. len .. ": ") + local str, str10, back, err + str = string.rep(string.char(47), math.mod(len, 10)) +- str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100), ++ str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100), + math.floor(len/10)) + str = str .. str10 + remote "str = data:receive()" +@@ -216,7 +216,7 @@ function test_totaltimeoutreceive(len, tm, sl) + data:settimeout(tm, "total") + local t = socket.gettime() + str, err, partial, elapsed = data:receive(2*len) +- check_timeout(tm, sl, elapsed, err, "receive", "total", ++ check_timeout(tm, sl, elapsed, err, "receive", "total", + string.len(str or partial) == 2*len) + end + +@@ -236,7 +236,7 @@ function test_totaltimeoutsend(len, tm, sl) + data:settimeout(tm, "total") + str = string.rep("a", 2*len) + total, err, partial, elapsed = data:send(str) +- check_timeout(tm, sl, elapsed, err, "send", "total", ++ check_timeout(tm, sl, elapsed, err, "send", "total", + total == 2*len) + end + +@@ -256,7 +256,7 @@ function test_blockingtimeoutreceive(len, tm, sl) + ]], 2*tm, len, sl, sl)) + data:settimeout(tm) + str, err, partial, elapsed = data:receive(2*len) +- check_timeout(tm, sl, elapsed, err, "receive", "blocking", ++ check_timeout(tm, sl, elapsed, err, "receive", "blocking", + string.len(str or partial) == 2*len) + end + +@@ -290,10 +290,10 @@ function empty_connect() + data = server:accept() + ]] + data, err = socket.connect("", port) +- if not data then ++ if not data then + pass("ok") + data = socket.connect(host, port) +- else ++ else + pass("gethostbyname returns localhost on empty string...") + end + end +@@ -304,15 +304,20 @@ function isclosed(c) + end + + function active_close() +- reconnect() +- if isclosed(data) then fail("should not be closed") end +- data:close() +- if not isclosed(data) then fail("should be closed") end +- data = nil +- local udp = socket.udp() ++ local tcp = socket.tcp4() ++ if isclosed(tcp) then fail("should not be closed") end ++ tcp:close() ++ if not isclosed(tcp) then fail("should be closed") end ++ tcp = socket.tcp() ++ if not isclosed(tcp) then fail("should be closed") end ++ tcp = nil ++ local udp = socket.udp4() + if isclosed(udp) then fail("should not be closed") end + udp:close() + if not isclosed(udp) then fail("should be closed") end ++ udp = socket.udp() ++ if not isclosed(udp) then fail("should be closed") end ++ udp = nil + pass("ok") + end + +@@ -327,7 +332,7 @@ function test_closed() + data:close() + data = nil + ]], str)) +- -- try to get a line ++ -- try to get a line + back, err, partial = data:receive() + if not err then fail("should have gotten 'closed'.") + elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.") +@@ -340,25 +345,25 @@ function test_closed() + data = nil + ]] + total, err, partial = data:send(string.rep("ugauga", 100000)) +- if not err then ++ if not err then + pass("failed: output buffer is at least %d bytes long!", total) +- elseif err ~= "closed" then ++ elseif err ~= "closed" then + fail("got '"..err.."' instead of 'closed'.") +- else +- pass("graceful 'closed' received after %d bytes were sent", partial) ++ else ++ pass("graceful 'closed' received after %d bytes were sent", partial) + end + end + + ------------------------------------------------------------------------ + function test_selectbugs() + local r, s, e = socket.select(nil, nil, 0.1) +- assert(type(r) == "table" and type(s) == "table" and ++ assert(type(r) == "table" and type(s) == "table" and + (e == "timeout" or e == "error")) + pass("both nil: ok") + local udp = socket.udp() + udp:close() + r, s, e = socket.select({ udp }, { udp }, 0.1) +- assert(type(r) == "table" and type(s) == "table" and ++ assert(type(r) == "table" and type(s) == "table" and + (e == "timeout" or e == "error")) + pass("closed sockets: ok") + e = pcall(socket.select, "wrong", 1, 0.1) +@@ -368,7 +373,7 @@ function test_selectbugs() + pass("invalid input: ok") + local toomany = {} + for i = 1, socket._SETSIZE+1 do +- toomany[#toomany+1] = socket.udp() ++ toomany[#toomany+1] = socket.udp4() + end + if #toomany > socket._SETSIZE then + local e = pcall(socket.select, toomany, nil, 0.1) +@@ -389,7 +394,7 @@ function accept_timeout() + local t = socket.gettime() + s:settimeout(1) + local c, e = s:accept() +- assert(not c, "should not accept") ++ assert(not c, "should not accept") + assert(e == "timeout", string.format("wrong error message (%s)", e)) + t = socket.gettime() - t + assert(t < 2, string.format("took to long to give up (%gs)", t)) +@@ -407,9 +412,9 @@ function connect_timeout() + local t = socket.gettime() + local r, e = c:connect("10.0.0.1", 81) + assert(not r, "should not connect") +- assert(socket.gettime() - t < 2, "took too long to give up.") ++ assert(socket.gettime() - t < 2, "took too long to give up.") + c:close() +- pass("ok") ++ pass("ok") + end + + ------------------------------------------------------------------------ +@@ -447,16 +452,14 @@ end + + ------------------------------------------------------------------------ + function rebind_test() +- --local c ,c1 = socket.bind("localhost", 0) + local c ,c1 = socket.bind("127.0.0.1", 0) + if not c then pass ("failed to bind! " .. tostring(c) .. ' ' .. tostring(c1)) return end + assert(c,c1) +- + local i, p = c:getsockname() + local s, e = socket.tcp() + assert(s, e) + s:setoption("reuseaddr", false) +- r, e = s:bind("localhost", p) ++ r, e = s:bind(i, p) + assert(not r, "managed to rebind!") + assert(e) + pass("ok") +@@ -476,9 +479,9 @@ function getstats_test() + data:receive(c) + t = t + c + local r, s, a = data:getstats() +- assert(r == t, "received count failed" .. tostring(r) ++ assert(r == t, "received count failed" .. tostring(r) + .. "/" .. tostring(t)) +- assert(s == t, "sent count failed" .. tostring(s) ++ assert(s == t, "sent count failed" .. tostring(s) + .. "/" .. tostring(t)) + end + pass("ok") +@@ -486,7 +489,7 @@ end + + + ------------------------------------------------------------------------ +-function test_nonblocking(size) ++function test_nonblocking(size) + reconnect() + printf("testing " .. 2*size .. " bytes: ") + remote(string.format([[ +@@ -545,7 +548,7 @@ function test_readafterclose() + data:close() + data = nil + ]])) +- data:close() ++ data:close() + back, err, partial = data:receive("*a") + assert(back == nil and err == "closed", "should have returned 'closed'") + pass("ok") +@@ -555,7 +558,7 @@ function test_readafterclose() + data:close() + data = nil + ]])) +- data:close() ++ data:close() + back, err, partial = data:receive() + assert(back == nil and err == "closed", "should have returned 'closed'") + pass("ok") +@@ -565,7 +568,7 @@ function test_readafterclose() + data:close() + data = nil + ]])) +- data:close() ++ data:close() + back, err, partial = data:receive(1) + assert(back == nil and err == "closed", "should have returned 'closed'") + pass("ok") +@@ -575,7 +578,7 @@ function test_readafterclose() + data:close() + data = nil + ]])) +- data:close() ++ data:close() + back, err, partial = data:receive(0) + assert(back == nil and err == "closed", "should have returned 'closed'") + pass("ok") +@@ -590,10 +593,10 @@ function test_writeafterclose() + data = nil + ]])) + local sent, err, errsent +- while not err do ++ while not err do + sent, err, errsent, time = data:send(str) + end +- assert(err == "closed", "should have returned 'closed'") ++ assert(err == "closed", "got " .. err .. " instead of 'closed'") + pass("ok") + end + +@@ -648,25 +651,24 @@ else io.stderr:write("Warning! IPv6 does not support!\n") end + end + + local udp_methods = { +- "close", ++ "close", + "dirty", + "getfamily", + "getfd", + "getoption", + "getpeername", + "getsockname", +- "receive", +- "receivefrom", +- "send", +- "sendto", +- "setfd", ++ "receive", ++ "receivefrom", ++ "send", ++ "sendto", ++ "setfd", + "setoption", + "setpeername", + "setsockname", + "settimeout" + } + +- + ------------------------------------------------------------------------ + test_methods(socket.udp(), udp_methods) + do local sock = socket.tcp6() +@@ -674,6 +676,9 @@ if sock then test_methods(socket.udp6(), udp_methods) + else io.stderr:write("Warning! IPv6 does not support!\n") end + end + ++test("closed connection detection: ") ++test_closed() ++ + test("partial receive") + test_partialrecv() + +@@ -697,9 +702,6 @@ rebind_test() + test("active close: ") + active_close() + +-test("closed connection detection: ") +-test_closed() +- + test("accept function: ") + accept_timeout() + accept_errors() +diff --git a/test/testsrvr.lua b/test/testsrvr.lua +index 72b93ab..1eb2d5b 100644 +--- a/test/testsrvr.lua ++++ b/test/testsrvr.lua +@@ -6,7 +6,7 @@ ack = "\n"; + while 1 do + print("server: waiting for client connection..."); + control = assert(server:accept()); +- while 1 do ++ while 1 do + command, emsg = control:receive(); + if emsg == "closed" then + control:close() +diff --git a/test/udpconnectclnt.lua b/test/udpconnectclnt.lua +index effe13a..ad6ab6a 100644 +--- a/test/udpconnectclnt.lua ++++ b/test/udpconnectclnt.lua +@@ -1,7 +1,7 @@ + local socket = require"socket" + local udp = socket.udp + local localhost = "127.0.0.1" +-local port = arg[1] ++local port = assert(arg[1], "missing port argument") + + se = udp(); se:setoption("reuseaddr", true) + se:setsockname(localhost, 5062) +diff --git a/win32.cmd b/win32.cmd +index 48522f0..3045721 100644 +--- a/win32.cmd ++++ b/win32.cmd +@@ -1,12 +1 @@ +-make PLAT=win32 LUAV=5.2 LUAINC_win32='c:\cygwin\home\diego\build\include' LUALIB_win32='c:\cygwin\home\diego\build\bin\release' +- +-#!/bin/sh +-for p in Release Debug x64/Release x64/Debug; do +- for el in mime socket; do +- for e in dll lib; do +- cp $p/$el/core.$e ../bin/$p/$el/ +- done; +- done; +- cp src/ltn12.lua src/socket.lua src/mime.lua ../bin/$p/ +- cp src/http.lua src/url.lua src/tp.lua src/ftp.lua src/headers.lua src/smtp.lua ../bin/$p/socket/ +-done; ++make LUAPREFIX_win32='c:\cygwin\home\diego\vc12' LUAV=5.1 PLAT=win32 LUALIBNAME_win32=lualib.lib PLATFORM_win32=Debug install-both diff --git a/user/lua-socket/lua-cflags.patch b/user/lua-socket/lua-cflags.patch new file mode 100644 index 000000000..c1da89644 --- /dev/null +++ b/user/lua-socket/lua-cflags.patch @@ -0,0 +1,22 @@ +diff --git a/src/makefile b/src/makefile +index adf687f..c2abddc 100644 +--- a/src/makefile ++++ b/src/makefile +@@ -160,6 +160,8 @@ SOCKET_macosx=usocket.o + #------ + # Compiler and linker settings + # for Linux ++LUAPC=lua ++LUA_CFLAGS=$(shell pkg-config --cflags $(LUAPC)) + SO_linux=so + O_linux=o + CC_linux=gcc +@@ -167,7 +169,7 @@ DEF_linux=-DLUASOCKET_$(DEBUG) \ + -DLUASOCKET_API='__attribute__((visibility("default")))' \ + -DUNIX_API='__attribute__((visibility("default")))' \ + -DMIME_API='__attribute__((visibility("default")))' +-CFLAGS_linux= -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ ++CFLAGS_linux= $(LUA_CFLAGS) -I$(LUAINC) $(DEF) -Wall -Wshadow -Wextra \ + -Wimplicit -O2 -ggdb3 -fpic -fvisibility=hidden + LDFLAGS_linux=-O -shared -fpic -o + LD_linux=gcc diff --git a/user/mosh/APKBUILD b/user/mosh/APKBUILD new file mode 100644 index 000000000..323891e69 --- /dev/null +++ b/user/mosh/APKBUILD @@ -0,0 +1,78 @@ +# Contributor: Francesco Colista <fcolista@alpinelinux.org> +# Maintainer: Dan Theisen <djt@hxx.in> +pkgname=mosh +pkgver=1.3.2 +pkgrel=0 +pkgdesc="Mobile shell surviving disconnects with local echo and line editing" +url="https://mosh.org" +arch="all" +license="GPL-3.0+" +depends="$pkgname-client $pkgname-server" +checkdepends="tmux perl" +makedepends="ncurses-dev zlib-dev openssl-dev perl-dev perl-io-tty + protobuf-dev automake autoconf libtool gzip" +subpackages="$pkgname-doc $pkgname-client $pkgname-server + $pkgname-bash-completion:bashcomp:noarch" +source="https://mosh.org/$pkgname-$pkgver.tar.gz + fix-ppc64le-build-with-musl.patch" + +prepare() { + default_prepare + # Test unicode-later-combining is failing. Ideally we want to fix it. + sed -i '/unicode-later-combining.test/d' "$builddir"/src/tests/Makefile.am + cd "$builddir" + ./autogen.sh +} + +build() { + cd "$builddir" + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --localstatedir=/var \ + --enable-examples + make +} + +check() { + cd "$builddir" + make check VERBOSE=1 V=1 +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install +} + +bashcomp() { + depends="" + pkgdesc="Bash completions for $pkgname" + install_if="$pkgname=$pkgver-r$pkgrel bash-completion" + + install -Dm644 "$builddir"/conf/bash-completion/completions/mosh \ + "$subpkgdir"/usr/share/bash-completion/completions/$pkgname +} + +server() { + replaces="mosh" + pkgdesc="Mosh server" + depends="" + mkdir -p "$subpkgdir"/usr/bin + mv "$pkgdir"/usr/bin/mosh-server \ + "$subpkgdir"/usr/bin/ +} + +client() { + replaces="mosh" + pkgdesc="Mosh client" + depends="openssh-client perl-io-tty" + mkdir -p "$subpkgdir"/usr/bin + mv "$pkgdir"/usr/bin/mosh-client \ + "$subpkgdir"/usr/bin/ +} + +sha512sums="f400e8fe7ba2ab7362311fc12a00ec69587505f901988aeee500fc68d38a388218500a3f602111c883ff23a9d43572114fcf0a8bf505df203691e5b597615769 mosh-1.3.2.tar.gz +a276dde98a2dab63ad9c9c05468c55983a95f482878c5694713810b561eae1ea5618efc72431a17ee5b5014b12ee9709c6a8cbf582620294e7888cc837cd073c fix-ppc64le-build-with-musl.patch" diff --git a/user/mosh/fix-ppc64le-build-with-musl.patch b/user/mosh/fix-ppc64le-build-with-musl.patch new file mode 100644 index 000000000..8d918a963 --- /dev/null +++ b/user/mosh/fix-ppc64le-build-with-musl.patch @@ -0,0 +1,53 @@ +From: Roberto Oliveira <robertoguimaraes8@gmail.com> +Date: Tue, 4 Apr 2017 16:46:50 +0000 +Subject: [PATCH] Fix build with musl on ppc64le + +mosh was breaking when building in ppc64le using musl, because ioctl() is defined +as ioctl(int, int) in musl and mosh is using TIOCSWINSZ macro as parameter. This was +triggering a gcc warning and make the build fail. + +This patch does an explicit integer conversion in TIOCSWINSZ, as no bits get +lost. + +--- a/src/frontend/mosh-server.cc ++++ b/src/frontend/mosh-server.cc +@@ -714,7 +714,12 @@ + } + window_size.ws_col = res->width; + window_size.ws_row = res->height; +- if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) { ++ ++ #if defined(__powerpc64__) && (!defined(__GLIBC__) && !defined(__UCLIBC__)) ++ if ( ioctl( host_fd, (int) TIOCSWINSZ, &window_size ) < 0 ) { ++ #else ++ if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) { ++ #endif + perror( "ioctl TIOCSWINSZ" ); + network.start_shutdown(); + } +--- a/src/examples/termemu.cc ++++ a/src/examples/termemu.cc +@@ -226,7 +226,11 @@ + } + + /* tell child process */ ++ #if defined(__powerpc64__) && (!defined(__GLIBC__) && !defined(__UCLIBC__)) ++ if ( ioctl( fd, (int) TIOCSWINSZ, &window_size ) < 0 ) { ++ #else + if ( ioctl( fd, TIOCSWINSZ, &window_size ) < 0 ) { ++ #endif + perror( "ioctl TIOCSWINSZ" ); + return; + } +@@ -306,7 +310,11 @@ + complete.act( &r ); + + /* tell child process */ ++ #if defined(__powerpc64__) && (!defined(__GLIBC__) && !defined(__UCLIBC__)) ++ if ( ioctl( fd, (int) TIOCSWINSZ, &window_size ) < 0 ) { ++ #else + if ( ioctl( fd, TIOCSWINSZ, &window_size ) < 0 ) { ++ #endif + perror( "ioctl TIOCSWINSZ" ); + return; + } diff --git a/user/mpv/APKBUILD b/user/mpv/APKBUILD index d0a4e37b1..a579ecc5a 100644 --- a/user/mpv/APKBUILD +++ b/user/mpv/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> # Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> pkgname=mpv -pkgver=0.29.0 +pkgver=0.29.1 pkgrel=0 pkgdesc="An improved fork of mplayer" url="https://mpv.io" @@ -21,7 +21,6 @@ makedepends="python3 " subpackages="$pkgname-doc" source="mpv-$pkgver.tar.gz::https://github.com/mpv-player/mpv/archive/v$pkgver.tar.gz" -sha512sums="77204218bd217ae1da4812b09e0509965a3ef102d3de5cd4360f007ccf3779e4cbde5cfd6adae9629ea39062bd365e847429bdf7f9a1ddebd0a67d267492b221 mpv-0.29.0.tar.gz" build() { cd "$builddir" @@ -46,3 +45,4 @@ package() { python3 ./waf install --destdir="$pkgdir" } +sha512sums="ec57c9ceaaf2915ee237dd5a1c5ea5d22725d8611e28a9b998e5bb0d8ab5bdf3631d0267fc7b54da31cb1eaa145ef35841e68846bd41c3b9e1024902e92fd086 mpv-0.29.1.tar.gz" diff --git a/user/nextcloud-client/APKBUILD b/user/nextcloud-client/APKBUILD new file mode 100644 index 000000000..549383413 --- /dev/null +++ b/user/nextcloud-client/APKBUILD @@ -0,0 +1,46 @@ +# Contributor: Leonardo Arena <rnalrd@alpinelinux.org> +# Maintainer: Max Rees <maxcrees@me.com> +pkgname=nextcloud-client +pkgver=2.5.0_beta2 +_ver="${pkgver%_beta2}-beta2" +pkgrel=0 +pkgdesc="Nextcloud desktop client" +url="https://github.com/nextcloud/desktop" +arch="all" +options="!checkroot" +license="GPL-2.0+ AND LGPL-2.1+ AND Public-Domain AND MIT AND (Custom:Digia-Qt OR LGPL-2.1-only WITH Qt-LGPL-exception-1.1) AND (Custom:Digia-Qt OR LGPL-2.1-only WITH Qt-LGPL-exception-1.1 OR GPL-3.0-only)" +depends="" +makedepends="cmake qt5-qttools-dev qtkeychain-dev zlib-dev + openssl-dev sqlite-dev qt5-qtsvg-dev" +subpackages="$pkgname-dev" +source="$pkgname-$pkgver.tar.gz::https://github.com/nextcloud/desktop/archive/v$_ver.tar.gz + no-webengine.patch + openssl.patch" +builddir="$srcdir/desktop-$_ver" + +build() { + cd "$builddir" + cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_SYSCONFDIR="/etc/$pkgname" \ + -DNO_SHIBBOLETH=1 \ + -DWITH_CRASHREPORTER=bool:OFF \ + -DUNIT_TESTING=bool:ON + make +} + +check() { + cd "$builddir" + make test +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install +} + +sha512sums="ed5ec8c0fd79d3f7f843ef1aefb9b94088b85dacca442388bc9a42e1ddbf1ee90482595135ffaffc85e40d223406964c903949ca1c2161fa0f6a2d6770a77cea nextcloud-client-2.5.0_beta2.tar.gz +6bd83fdee02eabe7ae29fb1a677f62d4a416ec553a0f8c66b7544cafb9201dd7d8b04dc6fb21f447f6c1ece13b06f5d3cba57ac71b211e166607ef15350b3e57 no-webengine.patch +e323a1074f8ac96667a420f076fdfc988e2fd97cdacd05d83ac54b467b567f5adbf635e7c4fb0414af0012b4016cc4c13441cb35ed3976bc970e514e81b65fd4 openssl.patch" diff --git a/user/nextcloud-client/no-webengine.patch b/user/nextcloud-client/no-webengine.patch new file mode 100644 index 000000000..d5beed35c --- /dev/null +++ b/user/nextcloud-client/no-webengine.patch @@ -0,0 +1,1017 @@ +--- desktop-2.5.0-beta1/src/libsync/networkjobs.cpp 2018-08-02 16:32:56.000000000 -0400 ++++ desktop-2.5.0-beta1/src/libsync/networkjobs.cpp 2018-08-15 19:10:43.340595365 -0400 +@@ -922,7 +922,7 @@ + + // WebViewFlow > OAuth > Shib > Basic + if (_account->serverVersionInt() >= Account::makeServerVersion(12, 0, 0)) { +- result = WebViewFlow; ++ result = Basic; + } + + qCInfo(lcDetermineAuthTypeJob) << "Auth type for" << _account->davUrl() << "is" << result; +--- desktop-2.5.0-beta1/src/gui/creds/webflowcredentialsdialog.cpp 2018-08-02 16:32:56.000000000 -0400 ++++ /dev/null 2018-08-15 19:12:03.420596798 -0400 +@@ -1,49 +0,0 @@ +-#include "webflowcredentialsdialog.h" +- +-#include <QVBoxLayout> +-#include <QLabel> +- +-#include "wizard/webview.h" +- +-namespace OCC { +- +-WebFlowCredentialsDialog::WebFlowCredentialsDialog(QWidget *parent) +- : QDialog(parent) +-{ +- _layout = new QVBoxLayout(this); +- +- //QString msg = tr("You have been logged out of %1 as user %2, please login again") +- // .arg(_account->displayName(), _user); +- _infoLabel = new QLabel(); +- _layout->addWidget(_infoLabel); +- +- _webView = new WebView(); +- _layout->addWidget(_webView); +- +- _errorLabel = new QLabel(); +- _errorLabel->hide(); +- _layout->addWidget(_errorLabel); +- +- setLayout(_layout); +- +- connect(_webView, &WebView::urlCatched, this, &WebFlowCredentialsDialog::urlCatched); +-} +- +-void WebFlowCredentialsDialog::setUrl(const QUrl &url) { +- _webView->setUrl(url); +-} +- +-void WebFlowCredentialsDialog::setInfo(const QString &msg) { +- _infoLabel->setText(msg); +-} +- +-void WebFlowCredentialsDialog::setError(const QString &error) { +- if (error.isEmpty()) { +- _errorLabel->hide(); +- } else { +- _errorLabel->setText(error); +- _errorLabel->show(); +- } +-} +- +-} +--- desktop-2.5.0-beta1/src/gui/creds/webflowcredentials.cpp 2018-08-02 16:32:56.000000000 -0400 ++++ /dev/null 2018-08-15 19:12:03.420596798 -0400 +@@ -1,258 +0,0 @@ +-#include "webflowcredentials.h" +- +-#include "creds/httpcredentials.h" +- +-#include <QAuthenticator> +-#include <QNetworkAccessManager> +-#include <QNetworkReply> +-#include <QPointer> +-#include <QTimer> +-#include <keychain.h> +-#include <QDialog> +-#include <QVBoxLayout> +-#include <QLabel> +- +-#include "accessmanager.h" +-#include "account.h" +-#include "theme.h" +-#include "wizard/webview.h" +-#include "webflowcredentialsdialog.h" +- +-using namespace QKeychain; +- +-namespace OCC { +- +-Q_LOGGING_CATEGORY(lcWebFlowCredentials, "sync.credentials.webflow", QtInfoMsg) +- +-WebFlowCredentials::WebFlowCredentials() +- : _ready(false), +- _credentialsValid(false) +-{ +- +-} +- +-WebFlowCredentials::WebFlowCredentials(const QString &user, const QString &password, const QSslCertificate &certificate, const QSslKey &key) +- : _user(user) +- , _password(password) +- , _clientSslKey(key) +- , _clientSslCertificate(certificate) +- , _ready(true) +- , _credentialsValid(true) +-{ +- +-} +- +-QString WebFlowCredentials::authType() const { +- return QString::fromLatin1("webflow"); +-} +- +-QString WebFlowCredentials::user() const { +- return _user; +-} +- +-QString WebFlowCredentials::password() const { +- return _password; +-} +- +-QNetworkAccessManager *WebFlowCredentials::createQNAM() const { +- qCInfo(lcWebFlowCredentials()) << "Get QNAM"; +- AccessManager *qnam = new AccessManager(); +- +- connect(qnam, &AccessManager::authenticationRequired, this, &WebFlowCredentials::slotAuthentication); +- connect(qnam, &AccessManager::finished, this, &WebFlowCredentials::slotFinished); +- +- return qnam; +-} +- +-bool WebFlowCredentials::ready() const { +- return _ready; +-} +- +-void WebFlowCredentials::fetchFromKeychain() { +- _wasFetched = true; +- +- // Make sure we get the user fromt he config file +- fetchUser(); +- +- if (ready()) { +- emit fetched(); +- } else { +- qCInfo(lcWebFlowCredentials()) << "Fetch from keyhchain!"; +- fetchFromKeychainHelper(); +- } +-} +- +-void WebFlowCredentials::askFromUser() { +- _askDialog = new WebFlowCredentialsDialog(); +- +- QUrl url = _account->url(); +- QString path = url.path() + "/index.php/login/flow"; +- url.setPath(path); +- _askDialog->setUrl(url); +- +- QString msg = tr("You have been logged out of %1 as user %2. Please login again") +- .arg(_account->displayName(), _user); +- _askDialog->setInfo(msg); +- +- _askDialog->show(); +- +- connect(_askDialog, &WebFlowCredentialsDialog::urlCatched, this, &WebFlowCredentials::slotAskFromUserCredentialsProvided); +- +- qCWarning(lcWebFlowCredentials()) << "User needs to reauth!"; +-} +- +-void WebFlowCredentials::slotAskFromUserCredentialsProvided(const QString &user, const QString &pass, const QString &host) { +- Q_UNUSED(host); +- +- if (_user != user) { +- qCInfo(lcWebFlowCredentials()) << "Authed with the wrong user!"; +- +- QString msg = tr("Please login with the user: %1") +- .arg(_user); +- _askDialog->setError(msg); +- +- QUrl url = _account->url(); +- QString path = url.path() + "/index.php/login/flow"; +- url.setPath(path); +- _askDialog->setUrl(url); +- +- return; +- } +- +- qCInfo(lcWebFlowCredentials()) << "Obtained a new password"; +- +- _password = pass; +- _ready = true; +- _credentialsValid = true; +- persist(); +- emit asked(); +- +- _askDialog->close(); +- delete _askDialog; +- _askDialog = NULL; +-} +- +- +-bool WebFlowCredentials::stillValid(QNetworkReply *reply) { +- qCWarning(lcWebFlowCredentials()) << "Still valid?"; +- qCWarning(lcWebFlowCredentials()) << reply->error(); +- qCWarning(lcWebFlowCredentials()) << reply->errorString(); +- return (reply->error() != QNetworkReply::AuthenticationRequiredError); +-} +- +-void WebFlowCredentials::persist() { +- if (_user.isEmpty()) { +- // We don't even have a user nothing to see here move along +- return; +- } +- +- _account->setCredentialSetting("user", _user); +- _account->wantsAccountSaved(_account); +- +- //TODO: Add ssl cert and key storing +- WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName()); +- job->setInsecureFallback(false); +- job->setKey(keychainKey(_account->url().toString(), _user, _account->id())); +- job->setTextData(_password); +- job->start(); +-} +- +-void WebFlowCredentials::invalidateToken() { +- // clear the session cookie. +- _account->clearCookieJar(); +- +- // let QNAM forget about the password +- // This needs to be done later in the event loop because we might be called (directly or +- // indirectly) from QNetworkAccessManagerPrivate::authenticationRequired, which itself +- // is a called from a BlockingQueuedConnection from the Qt HTTP thread. And clearing the +- // cache needs to synchronize again with the HTTP thread. +- QTimer::singleShot(0, _account, &Account::clearQNAMCache); +-} +- +-void WebFlowCredentials::forgetSensitiveData(){ +- _password = QString(); +- _ready = false; +- +- fetchUser(); +- +- const QString kck = keychainKey(_account->url().toString(), _user, _account->id()); +- if (kck.isEmpty()) { +- qCWarning(lcWebFlowCredentials()) << "InvalidateToken: User is empty, bailing out!"; +- return; +- } +- +- DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName()); +- job->setInsecureFallback(false); +- job->setKey(kck); +- job->start(); +- +- invalidateToken(); +-} +- +-void WebFlowCredentials::setAccount(Account *account) { +- AbstractCredentials::setAccount(account); +- if (_user.isEmpty()) { +- fetchUser(); +- } +-} +- +-QString WebFlowCredentials::fetchUser() { +- _user = _account->credentialSetting("user").toString(); +- return _user; +-} +- +-void WebFlowCredentials::slotAuthentication(QNetworkReply *reply, QAuthenticator *authenticator) { +- Q_UNUSED(reply); +- +- if (!_ready) { +- return; +- } +- +- if (_credentialsValid == false) { +- return; +- } +- +- qCWarning(lcWebFlowCredentials()) << "Requires authentication"; +- +- authenticator->setUser(_user); +- authenticator->setPassword(_password); +- _credentialsValid = false; +-} +- +-void WebFlowCredentials::slotFinished(QNetworkReply *reply) { +- qCInfo(lcWebFlowCredentials()) << "request finished"; +- +- if (reply->error() == QNetworkReply::NoError) { +- _credentialsValid = true; +- } +-} +- +-void WebFlowCredentials::fetchFromKeychainHelper() { +- const QString kck = keychainKey( +- _account->url().toString(), +- _user, +- _account->id()); +- +- ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName()); +- job->setInsecureFallback(false); +- job->setKey(kck); +- connect(job, &Job::finished, this, &WebFlowCredentials::slotReadPasswordJobDone); +- job->start(); +-} +- +-void WebFlowCredentials::slotReadPasswordJobDone(Job *incomingJob) { +- QKeychain::ReadPasswordJob *job = static_cast<ReadPasswordJob *>(incomingJob); +- QKeychain::Error error = job->error(); +- +- if (error == QKeychain::NoError) { +- _password = job->textData(); +- _ready = true; +- _credentialsValid = true; +- } else { +- _ready = false; +- } +- +- emit fetched(); +-} +- +-} +--- desktop-2.5.0-beta1/src/gui/creds/webflowcredentialsdialog.h 2018-08-02 16:32:56.000000000 -0400 ++++ /dev/null 2018-08-15 19:12:03.420596798 -0400 +@@ -1,36 +0,0 @@ +-#ifndef WEBFLOWCREDENTIALSDIALOG_H +-#define WEBFLOWCREDENTIALSDIALOG_H +- +-#include <QDialog> +-#include <QUrl> +- +-class QLabel; +-class QVBoxLayout; +- +-namespace OCC { +- +-class WebView; +- +-class WebFlowCredentialsDialog : public QDialog +-{ +- Q_OBJECT +-public: +- WebFlowCredentialsDialog(QWidget *parent = 0); +- +- void setUrl(const QUrl &url); +- void setInfo(const QString &msg); +- void setError(const QString &error); +- +-signals: +- void urlCatched(const QString user, const QString pass, const QString host); +- +-private: +- WebView *_webView; +- QLabel *_errorLabel; +- QLabel *_infoLabel; +- QVBoxLayout *_layout; +-}; +- +-} +- +-#endif // WEBFLOWCREDENTIALSDIALOG_H +--- desktop-2.5.0-beta1/src/gui/creds/credentialsfactory.cpp 2018-08-02 16:32:56.000000000 -0400 ++++ desktop-2.5.0-beta1/src/gui/creds/credentialsfactory.cpp 2018-08-15 19:29:27.240615471 -0400 +@@ -21,7 +21,6 @@ + #ifndef NO_SHIBBOLETH + #include "creds/shibbolethcredentials.h" + #endif +-#include "creds/webflowcredentials.h" + + namespace OCC { + +@@ -40,8 +39,6 @@ + } else if (type == "shibboleth") { + return new ShibbolethCredentials; + #endif +- } else if (type == "webflow") { +- return new WebFlowCredentials; + } else { + qCWarning(lcGuiCredentials, "Unknown credentials type: %s", qPrintable(type)); + return new DummyCredentials; +--- desktop-2.5.0-beta1/src/gui/creds/webflowcredentials.h 2018-08-02 16:32:56.000000000 -0400 ++++ /dev/null 2018-08-15 19:12:03.420596798 -0400 +@@ -1,79 +0,0 @@ +-#ifndef WEBFLOWCREDENTIALS_H +-#define WEBFLOWCREDENTIALS_H +- +-#include <QSslCertificate> +-#include <QSslKey> +- +-#include "creds/abstractcredentials.h" +- +-class QDialog; +-class QLabel; +-class QNetworkReply; +-class QAuthenticator; +- +-namespace QKeychain { +- class Job; +-} +- +-namespace OCC { +- +-class WebFlowCredentialsDialog; +- +-class WebFlowCredentials : public AbstractCredentials +-{ +- Q_OBJECT +-public: +- explicit WebFlowCredentials(); +- WebFlowCredentials(const QString &user, const QString &password, const QSslCertificate &certificate = QSslCertificate(), const QSslKey &key = QSslKey()); +- +- QString authType() const override; +- QString user() const override; +- QString password() const; +- QNetworkAccessManager *createQNAM() const override; +- +- bool ready() const override; +- +- void fetchFromKeychain() override; +- void askFromUser() override; +- +- bool stillValid(QNetworkReply *reply) override; +- void persist() override; +- void invalidateToken() override; +- void forgetSensitiveData() override; +- +- // To fetch the user name as early as possible +- void setAccount(Account *account) override; +- +-private slots: +- void slotAuthentication(QNetworkReply *reply, QAuthenticator *authenticator); +- void slotFinished(QNetworkReply *reply); +- +- void slotReadPasswordJobDone(QKeychain::Job *incomingJob); +- void slotAskFromUserCredentialsProvided(const QString &user, const QString &pass, const QString &host); +- +-private: +- /** Reads data from keychain locations +- * +- * Goes through +- * slotReadClientCertPEMJobDone to +- * slotReadClientCertPEMJobDone to +- * slotReadJobDone +- */ +- void fetchFromKeychainHelper(); +- +- QString fetchUser(); +- +- QString _user; +- QString _password; +- QSslKey _clientSslKey; +- QSslCertificate _clientSslCertificate; +- +- bool _ready; +- bool _credentialsValid; +- +- WebFlowCredentialsDialog *_askDialog; +-}; +- +-} +- +-#endif // WEBFLOWCREDENTIALS_H +--- desktop-2.5.0-beta1/src/gui/CMakeLists.txt 2018-08-02 16:32:56.000000000 -0400 ++++ desktop-2.5.0-beta1/src/gui/CMakeLists.txt 2018-08-15 19:28:53.640614870 -0400 +@@ -41,7 +41,6 @@ + wizard/owncloudoauthcredspage.ui + wizard/owncloudsetupnocredspage.ui + wizard/owncloudwizardresultpage.ui +- wizard/webview.ui + ) + + set(client_SRCS +@@ -104,8 +103,6 @@ + creds/credentialsfactory.cpp + creds/httpcredentialsgui.cpp + creds/oauth.cpp +- creds/webflowcredentials.cpp +- creds/webflowcredentialsdialog.cpp + wizard/postfixlineedit.cpp + wizard/abstractcredswizardpage.cpp + wizard/owncloudadvancedsetuppage.cpp +@@ -116,8 +113,6 @@ + wizard/owncloudwizardcommon.cpp + wizard/owncloudwizard.cpp + wizard/owncloudwizardresultpage.cpp +- wizard/webviewpage.cpp +- wizard/webview.cpp + ) + + IF(NOT NO_SHIBBOLETH) +@@ -290,7 +290,7 @@ + endif() + + add_library(updater STATIC ${updater_SRCS}) +-target_link_libraries(updater ${synclib_NAME} Qt5::Widgets Qt5::Network Qt5::Xml Qt5::WebEngineWidgets) ++target_link_libraries(updater ${synclib_NAME} Qt5::Widgets Qt5::Network Qt5::Xml) + target_include_directories(updater PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + + set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES +--- desktop-2.5.0-beta2/src/gui/wizard/webview.cpp 2018-08-24 12:54:42.000000000 +0000 ++++ /dev/null 2018-10-03 06:10:44.230254545 +0000 +@@ -1,162 +0,0 @@ +-#include "webview.h" +- +-#include <QWebEnginePage> +-#include <QWebEngineProfile> +-#include <QWebEngineUrlRequestInterceptor> +-#include <QWebEngineUrlRequestJob> +-#include <QWebEngineUrlSchemeHandler> +-#include <QWebEngineView> +-#include <QDesktopServices> +-#include <QProgressBar> +-#include <QLoggingCategory> +-#include <QLocale> +- +-#include "common/utility.h" +- +-namespace OCC { +- +-Q_LOGGING_CATEGORY(lcWizardWebiew, "gui.wizard.webview", QtInfoMsg) +- +- +-class WebViewPageUrlRequestInterceptor : public QWebEngineUrlRequestInterceptor +-{ +- Q_OBJECT +-public: +- WebViewPageUrlRequestInterceptor(QObject *parent = 0); +- void interceptRequest(QWebEngineUrlRequestInfo &info); +-}; +- +-class WebViewPageUrlSchemeHandler : public QWebEngineUrlSchemeHandler +-{ +- Q_OBJECT +-public: +- WebViewPageUrlSchemeHandler(QObject *parent = 0); +- void requestStarted(QWebEngineUrlRequestJob *request); +- +-Q_SIGNALS: +- void urlCatched(QString user, QString pass, QString host); +-}; +- +-class WebEnginePage : public QWebEnginePage { +-public: +- WebEnginePage(QWebEngineProfile *profile, QObject* parent = nullptr); +- QWebEnginePage * createWindow(QWebEnginePage::WebWindowType type) override; +-}; +- +-// We need a separate class here, since we cannot simply return the same WebEnginePage object +-// this leads to a strage segfault somewhere deep inside of the QWebEngine code +-class ExternalWebEnginePage : public QWebEnginePage { +-public: +- ExternalWebEnginePage(QWebEngineProfile *profile, QObject* parent = nullptr); +- bool acceptNavigationRequest(const QUrl &url, QWebEnginePage::NavigationType type, bool isMainFrame) override; +-}; +- +-WebView::WebView(QWidget *parent) +- : QWidget(parent), +- _ui() +-{ +- _ui.setupUi(this); +- +- _webview = new QWebEngineView(this); +- _profile = new QWebEngineProfile(this); +- _page = new WebEnginePage(_profile); +- _interceptor = new WebViewPageUrlRequestInterceptor(this); +- _schemeHandler = new WebViewPageUrlSchemeHandler(this); +- +- const QString userAgent(Utility::userAgentString()); +- _profile->setHttpUserAgent(userAgent); +- QWebEngineProfile::defaultProfile()->setHttpUserAgent(userAgent); +- _profile->setRequestInterceptor(_interceptor); +- _profile->installUrlSchemeHandler("nc", _schemeHandler); +- +- /* +- * Set a proper accept langauge to the language of the client +- * code from: http://code.qt.io/cgit/qt/qtbase.git/tree/src/network/access/qhttpnetworkconnection.cpp +- */ +- { +- QString systemLocale = QLocale::system().name().replace(QChar::fromLatin1('_'),QChar::fromLatin1('-')); +- QString acceptLanguage; +- if (systemLocale == QLatin1String("C")) { +- acceptLanguage = QString::fromLatin1("en,*"); +- } else if (systemLocale.startsWith(QLatin1String("en-"))) { +- acceptLanguage = systemLocale + QLatin1String(",*"); +- } else { +- acceptLanguage = systemLocale + QLatin1String(",en,*"); +- } +- _profile->setHttpAcceptLanguage(acceptLanguage); +- } +- +- _webview->setPage(_page); +- _ui.verticalLayout->addWidget(_webview); +- +- connect(_webview, &QWebEngineView::loadProgress, _ui.progressBar, &QProgressBar::setValue); +- connect(_schemeHandler, &WebViewPageUrlSchemeHandler::urlCatched, this, &WebView::urlCatched); +-} +- +-void WebView::setUrl(const QUrl &url) { +- _page->setUrl(url); +-} +- +-WebViewPageUrlRequestInterceptor::WebViewPageUrlRequestInterceptor(QObject *parent) +- : QWebEngineUrlRequestInterceptor(parent) { +- +-} +- +-void WebViewPageUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) { +- info.setHttpHeader("OCS-APIREQUEST", "true"); +-} +- +-WebViewPageUrlSchemeHandler::WebViewPageUrlSchemeHandler(QObject *parent) +- : QWebEngineUrlSchemeHandler(parent) { +- +-} +- +-void WebViewPageUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request) { +- QUrl url = request->requestUrl(); +- +- QString path = url.path().mid(1); +- QStringList parts = path.split("&"); +- +- QString server; +- QString user; +- QString password; +- +- for (QString part : parts) { +- if (part.startsWith("server:")) { +- server = part.mid(7); +- } else if (part.startsWith("user:")) { +- user = part.mid(5); +- } else if (part.startsWith("password:")) { +- password = part.mid(9); +- } +- } +- +- qCInfo(lcWizardWebiew()) << "Got user: " << user << ", server: " << server; +- +- emit urlCatched(user, password, server); +-} +- +- +-WebEnginePage::WebEnginePage(QWebEngineProfile *profile, QObject* parent) : QWebEnginePage(profile, parent) { +- +-} +- +-QWebEnginePage * WebEnginePage::createWindow(QWebEnginePage::WebWindowType type) { +- ExternalWebEnginePage *view = new ExternalWebEnginePage(this->profile()); +- return view; +-} +- +-ExternalWebEnginePage::ExternalWebEnginePage(QWebEngineProfile *profile, QObject* parent) : QWebEnginePage(profile, parent) { +- +-} +- +- +-bool ExternalWebEnginePage::acceptNavigationRequest(const QUrl &url, QWebEnginePage::NavigationType type, bool isMainFrame) +-{ +- QDesktopServices::openUrl(url); +- return false; +-} +- +-} +- +-#include "webview.moc" +--- desktop-2.5.0-beta1/src/gui/wizard/webviewpage.cpp 2018-08-02 16:32:56.000000000 -0400 ++++ /dev/null 2018-08-15 19:06:30.250590838 -0400 +@@ -1,73 +0,0 @@ +-#include "webviewpage.h" +- +-#include <QWebEngineUrlRequestJob> +-#include <QProgressBar> +-#include <QVBoxLayout> +- +-#include "owncloudwizard.h" +-#include "creds/webflowcredentials.h" +-#include "webview.h" +-#include "account.h" +- +-namespace OCC { +- +-Q_LOGGING_CATEGORY(lcWizardWebiewPage, "gui.wizard.webviewpage", QtInfoMsg) +- +- +-WebViewPage::WebViewPage(QWidget *parent) +- : AbstractCredentialsWizardPage() +-{ +- _ocWizard = qobject_cast<OwncloudWizard *>(parent); +- +- qCInfo(lcWizardWebiewPage()) << "Time for a webview!"; +- _webView = new WebView(this); +- +- QVBoxLayout *layout = new QVBoxLayout(this); +- layout->addWidget(_webView); +- setLayout(layout); +- +- connect(_webView, &WebView::urlCatched, this, &WebViewPage::urlCatched); +-} +- +-void WebViewPage::initializePage() { +- QString url; +- if (_ocWizard->registration()) { +- url = "https://nextcloud.com/register"; +- } else { +- url = _ocWizard->ocUrl(); +- url += "/index.php/login/flow"; +- } +- qCInfo(lcWizardWebiewPage()) << "Url to auth at: " << url; +- _webView->setUrl(QUrl(url)); +-} +- +-int WebViewPage::nextId() const { +- return WizardCommon::Page_AdvancedSetup; +-} +- +-bool WebViewPage::isComplete() const { +- return false; +-} +- +-AbstractCredentials* WebViewPage::getCredentials() const { +- return new WebFlowCredentials(_user, _pass, _ocWizard->_clientSslCertificate, _ocWizard->_clientSslKey); +-} +- +-void WebViewPage::setConnected() { +- qCInfo(lcWizardWebiewPage()) << "YAY! we are connected!"; +-} +- +-void WebViewPage::urlCatched(QString user, QString pass, QString host) { +- qCInfo(lcWizardWebiewPage()) << "Got user: " << user << ", server: " << host; +- +- _user = user; +- _pass = pass; +- +- AccountPtr account = _ocWizard->account(); +- account->setUrl(host); +- +- qCInfo(lcWizardWebiewPage()) << "URL: " << field("OCUrl").toString(); +- emit connectToOCUrl(host); +-} +- +-} +--- desktop-2.5.0-beta2/src/gui/wizard/webview.h 2018-08-24 12:54:42.000000000 +0000 ++++ /dev/null 2018-10-03 06:11:27.640255322 +0000 +@@ -1,42 +0,0 @@ +-#ifndef WEBVIEW_H +-#define WEBVIEW_H +- +-#include <QUrl> +-#include <QWidget> +- +-#include "ui_webview.h" +- +-class QWebEngineView; +-class QWebEngineProfile; +-class QWebEnginePage; +- +-namespace OCC { +- +-class WebViewPageUrlRequestInterceptor; +-class WebViewPageUrlSchemeHandler; +-class WebEnginePage; +- +-class WebView : public QWidget +-{ +- Q_OBJECT +-public: +- WebView(QWidget *parent = 0); +- void setUrl(const QUrl &url); +- +-signals: +- void urlCatched(const QString user, const QString pass, const QString host); +- +-private: +- Ui_WebView _ui; +- +- QWebEngineView *_webview; +- QWebEngineProfile *_profile; +- WebEnginePage *_page; +- +- WebViewPageUrlRequestInterceptor *_interceptor; +- WebViewPageUrlSchemeHandler *_schemeHandler; +-}; +- +-} +- +-#endif // WEBVIEW_H +--- desktop-2.5.0-beta1/src/gui/wizard/webviewpage.h 2018-08-02 16:32:56.000000000 -0400 ++++ /dev/null 2018-08-15 19:25:56.010611692 -0400 +@@ -1,41 +0,0 @@ +-#ifndef WEBVIEWPAGE_H +-#define WEBVIEWPAGE_H +- +-#include "wizard/abstractcredswizardpage.h" +- +-namespace OCC { +- +-class AbstractCredentials; +-class OwncloudWizard; +-class WebView; +- +-class WebViewPage : public AbstractCredentialsWizardPage +-{ +- Q_OBJECT +-public: +- WebViewPage(QWidget *parent = 0); +- +- void initializePage() Q_DECL_OVERRIDE; +- int nextId() const Q_DECL_OVERRIDE; +- bool isComplete() const; +- +- AbstractCredentials* getCredentials() const; +- void setConnected(); +- +-signals: +- void connectToOCUrl(const QString&); +- +-private slots: +- void urlCatched(QString user, QString pass, QString host); +- +-private: +- OwncloudWizard *_ocWizard; +- WebView *_webView; +- +- QString _user; +- QString _pass; +-}; +- +-} +- +-#endif // WEBVIEWPAGE_H +--- desktop-2.5.0-beta1/src/gui/wizard/owncloudsetuppage.cpp 2018-08-02 16:32:56.000000000 -0400 ++++ desktop-2.5.0-beta1/src/gui/wizard/owncloudsetuppage.cpp 2018-08-15 19:23:33.100609136 -0400 +@@ -161,7 +161,7 @@ + void OwncloudSetupPage::slotGotoProviderList() + { + _ocWizard->setRegistration(true); +- _ocWizard->setAuthType(DetermineAuthTypeJob::AuthType::WebViewFlow); ++ _ocWizard->setAuthType(DetermineAuthTypeJob::AuthType::Basic); + _authTypeKnown = true; + _checking = false; + emit completeChanged(); +@@ -278,8 +278,6 @@ + return WizardCommon::Page_OAuthCreds; + case DetermineAuthTypeJob::Shibboleth: + return WizardCommon::Page_ShibbolethCreds; +- case DetermineAuthTypeJob::WebViewFlow: +- return WizardCommon::Page_WebView; + } + return WizardCommon::Page_HttpCreds; + } +--- desktop-2.5.0-beta1/src/gui/wizard/webview.ui 2018-08-02 16:32:56.000000000 -0400 ++++ /dev/null 2018-08-15 19:24:43.320610392 -0400 +@@ -1,80 +0,0 @@ +-<?xml version="1.0" encoding="UTF-8"?> +-<ui version="4.0"> +- <class>WebView</class> +- <widget class="QWidget" name="WebView"> +- <property name="geometry"> +- <rect> +- <x>0</x> +- <y>0</y> +- <width>800</width> +- <height>700</height> +- </rect> +- </property> +- <property name="sizePolicy"> +- <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +- <horstretch>0</horstretch> +- <verstretch>0</verstretch> +- </sizepolicy> +- </property> +- <property name="minimumSize"> +- <size> +- <width>800</width> +- <height>650</height> +- </size> +- </property> +- <property name="windowTitle"> +- <string>Form</string> +- </property> +- <layout class="QGridLayout" name="gridLayout"> +- <property name="leftMargin"> +- <number>0</number> +- </property> +- <property name="topMargin"> +- <number>0</number> +- </property> +- <property name="rightMargin"> +- <number>0</number> +- </property> +- <property name="bottomMargin"> +- <number>0</number> +- </property> +- <item row="1" column="0"> +- <layout class="QVBoxLayout" name="verticalLayout"> +- <property name="spacing"> +- <number>0</number> +- </property> +- <item> +- <widget class="QProgressBar" name="progressBar"> +- <property name="maximumSize"> +- <size> +- <width>16777215</width> +- <height>5</height> +- </size> +- </property> +- <property name="styleSheet"> +- <string notr="true">QProgressBar::chunk { +- background-color: rgba(0, 130, 201, 255); +-}</string> +- </property> +- <property name="value"> +- <number>0</number> +- </property> +- <property name="textVisible"> +- <bool>false</bool> +- </property> +- </widget> +- </item> +- <item> +- <layout class="QHBoxLayout" name="resultLayout"> +- <property name="spacing"> +- <number>0</number> +- </property> +- </layout> +- </item> +- </layout> +- </item> +- </layout> +- </widget> +- <resources/> +- <connections/> +-</ui> +--- desktop-2.5.0-beta1/src/gui/wizard/owncloudwizard.h 2018-08-02 16:32:56.000000000 -0400 ++++ desktop-2.5.0-beta1/src/gui/wizard/owncloudwizard.h 2018-08-15 19:22:00.430607478 -0400 +@@ -39,7 +39,6 @@ + class OwncloudWizardResultPage; + class AbstractCredentials; + class AbstractCredentialsWizardPage; +-class WebViewPage; + + /** + * @brief The OwncloudWizard class +@@ -106,7 +105,6 @@ + OwncloudAdvancedSetupPage *_advancedSetupPage; + OwncloudWizardResultPage *_resultPage; + AbstractCredentialsWizardPage *_credentialsPage; +- WebViewPage *_webViewPage; + + QStringList _setupLog; + +--- desktop-2.5.0-beta1/src/gui/wizard/owncloudwizard.cpp 2018-08-02 16:32:56.000000000 -0400 ++++ desktop-2.5.0-beta1/src/gui/wizard/owncloudwizard.cpp 2018-08-15 19:04:35.670588788 -0400 +@@ -26,7 +26,6 @@ + #endif + #include "wizard/owncloudadvancedsetuppage.h" + #include "wizard/owncloudwizardresultpage.h" +-#include "wizard/webviewpage.h" + + #include "QProgressIndicator.h" + +@@ -51,7 +50,6 @@ + , _advancedSetupPage(new OwncloudAdvancedSetupPage) + , _resultPage(new OwncloudWizardResultPage) + , _credentialsPage(0) +- , _webViewPage(new WebViewPage(this)) + , _setupLog() + , _registration(false) + { +@@ -64,7 +62,6 @@ + #endif + setPage(WizardCommon::Page_AdvancedSetup, _advancedSetupPage); + setPage(WizardCommon::Page_Result, _resultPage); +- setPage(WizardCommon::Page_WebView, _webViewPage); + + connect(this, &QDialog::finished, this, &OwncloudWizard::basicSetupFinished); + +@@ -79,7 +76,6 @@ + #ifndef NO_SHIBBOLETH + connect(_shibbolethCredsPage, &OwncloudShibbolethCredsPage::connectToOCUrl, this, &OwncloudWizard::connectToOCUrl); + #endif +- connect(_webViewPage, &WebViewPage::connectToOCUrl, this, &OwncloudWizard::connectToOCUrl); + connect(_advancedSetupPage, &OwncloudAdvancedSetupPage::createLocalAndRemoteFolders, + this, &OwncloudWizard::createLocalAndRemoteFolders); + connect(this, &QWizard::customButtonClicked, this, &OwncloudWizard::skipFolderConfiguration); +@@ -168,10 +164,6 @@ + break; + #endif + +- case WizardCommon::Page_WebView: +- _webViewPage->setConnected(); +- break; +- + case WizardCommon::Page_AdvancedSetup: + _advancedSetupPage->directoriesCreated(); + break; +@@ -195,8 +187,6 @@ + #endif + if (type == DetermineAuthTypeJob::OAuth) { + _credentialsPage = _browserCredsPage; +- } else if (type == DetermineAuthTypeJob::WebViewFlow) { +- _credentialsPage = _webViewPage; + } else { // try Basic auth even for "Unknown" + _credentialsPage = _httpCredsPage; + } +--- desktop-2.5.0-beta1/src/CMakeLists.txt 2018-08-02 16:32:56.000000000 -0400 ++++ desktop-2.5.0-beta1/src/CMakeLists.txt 2018-08-15 20:59:59.390712646 -0400 +@@ -4,7 +4,7 @@ + + set(synclib_NAME ${APPLICATION_EXECUTABLE}sync) + +-find_package(Qt5 5.6 COMPONENTS Core Network Xml Concurrent WebEngineWidgets WebEngine REQUIRED) ++find_package(Qt5 5.6 COMPONENTS Core Network Xml Concurrent REQUIRED) + if (Qt5Core_VERSION VERSION_LESS 5.9.0) + message(STATUS "For HTTP/2 support, compile with Qt 5.9 or higher.") + endif() diff --git a/user/nextcloud-client/openssl.patch b/user/nextcloud-client/openssl.patch new file mode 100644 index 000000000..426fa0cfb --- /dev/null +++ b/user/nextcloud-client/openssl.patch @@ -0,0 +1,11 @@ +--- desktop-2.5.0-beta2/CMakeLists.txt 2018-08-24 12:54:42.000000000 +0000 ++++ desktop-2.5.0-beta2/CMakeLists.txt 2018-10-03 06:19:15.840263697 +0000 +@@ -183,7 +183,7 @@ if(BUILD_CLIENT) + endif() + find_package(Sphinx) + find_package(PdfLatex) +- find_package(OpenSSL 1.1 REQUIRED ) ++ find_package(OpenSSL 1.0 REQUIRED ) + + find_package(ZLIB REQUIRED) + find_package(GLib2) diff --git a/user/perl-file-finder/APKBUILD b/user/perl-file-finder/APKBUILD index a28247770..83f2ada97 100644 --- a/user/perl-file-finder/APKBUILD +++ b/user/perl-file-finder/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Adélie Perl Team <adelie-perl@lists.adelielinux.org> pkgname=perl-file-finder pkgver=0.53 -pkgrel=0 +pkgrel=1 pkgdesc="Wrap Perl File::Find" url="https://metacpan.org/release/File-Finder" arch="noarch" @@ -10,7 +10,9 @@ license="Artistic-1.0-Perl" depends="perl-text-glob" makedepends="perl-dev" subpackages="$pkgname-doc" -source="https://cpan.metacpan.org/authors/id/M/ME/MERLYN/File-Finder-$pkgver.tar.gz" +source="https://cpan.metacpan.org/authors/id/M/ME/MERLYN/File-Finder-$pkgver.tar.gz + fix-test.patch + " builddir="$srcdir/File-Finder-$pkgver" build() { @@ -30,4 +32,5 @@ package() { find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete } -sha512sums="abcbc5b5c7ae09eb13e62ab1656e79a25becafb91eeef241fc0803ba0b35ae902c93db2240dfff6342952df7f0ff589350f63fdb1ccead64816f51bf52e366f0 File-Finder-0.53.tar.gz" +sha512sums="abcbc5b5c7ae09eb13e62ab1656e79a25becafb91eeef241fc0803ba0b35ae902c93db2240dfff6342952df7f0ff589350f63fdb1ccead64816f51bf52e366f0 File-Finder-0.53.tar.gz +8b96e6adb28e0a26843a3551d5939b9c9f65fbef155e46c155b82263923e1275a6be8c6184bbc831dfff7cc899d7b48df0f21e7005f273c389eff830190be166 fix-test.patch" diff --git a/user/perl-file-finder/fix-test.patch b/user/perl-file-finder/fix-test.patch new file mode 100644 index 000000000..6c371f6fc --- /dev/null +++ b/user/perl-file-finder/fix-test.patch @@ -0,0 +1,16 @@ +Thanks @smaeul + +--- File-Finder-0.53/t/05-steps.t.old 2004-10-07 01:04:12.000000000 -0500 ++++ File-Finder-0.53/t/05-steps.t 2018-10-02 22:27:29.867015209 -0500 +@@ -51,9 +51,9 @@ + 'mode 755'); + + { +- my $dirperm = (stat ".")[2] & 07777; ++ my $dirperm = (stat ".")[2] & 0777; + is_deeply([File::Finder->perm($dirperm)->in(qw(.))], +- [fin(sub { ((stat($_))[2] & 07777) == $dirperm }, '.')], ++ [fin(sub { ((stat($_))[2] & 0777) == $dirperm }, '.')], + 'mode same as current directory'); + } + diff --git a/user/perl-io-tty/APKBUILD b/user/perl-io-tty/APKBUILD new file mode 100644 index 000000000..d42b831a2 --- /dev/null +++ b/user/perl-io-tty/APKBUILD @@ -0,0 +1,33 @@ +# Contributor: Dan Theisen <djt@hxx.in> +# Maintainer: Adélie Perl Team <adelie-perl@lists.adelielinux.org> +pkgname=perl-io-tty +pkgver=1.12 +pkgrel=0 +pkgdesc="Low-level allocate a pseudo-tty" +url="https://metacpan.org/pod/IO::Tty" +arch="all" +license="Artistic-1.0-Perl" +depends="" +makedepends="perl-dev" +subpackages="$pkgname-doc" +source="https://cpan.metacpan.org/authors/id/T/TO/TODDR/IO-Tty-$pkgver.tar.gz" +builddir="$srcdir/IO-Tty-$pkgver" + +build() { + cd "$builddir" + PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor + make +} + +check() { + cd "$builddir" + make test +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install + find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete +} + +sha512sums="23733e7832a0de370952420df8a781f85d28ff60eb4cd55be22147337bf5587f4e1ec7fcfc190ae3ad1fd9df0f9697f2d647e00739f4a2927b1ac9c81435454d IO-Tty-1.12.tar.gz" diff --git a/user/prosody/APKBUILD b/user/prosody/APKBUILD new file mode 100644 index 000000000..990de722f --- /dev/null +++ b/user/prosody/APKBUILD @@ -0,0 +1,59 @@ +# Contributor: Mika Havela <mika.havela@gmail.com> +# Contributor: Francesco Colista <fcolista@alpinelinux.org> +# Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> +pkgname=prosody +pkgver=0.10.2 +pkgrel=0 +pkgdesc="Lua based Jabber/XMPP server" +url="http://prosody.im/" +arch="all" +options="!check" # broken testsuite +license="MIT" +depends="lua-socket lua-expat lua-filesystem lua-sec lua5.3" +makedepends="linux-headers lua5.3-dev libidn-dev openssl-dev" +install="prosody.pre-install" +subpackages="$pkgname-doc $pkgname-openrc" +pkgusers="prosody" +pkggroups="prosody" +source="https://prosody.im/downloads/source/$pkgname-$pkgver.tar.gz + prosody.cfg.lua.patch + mallinfo.patch + $pkgname.initd + " + +build() { + cd "$builddir" + ./configure \ + --prefix=/usr \ + --sysconfdir=/etc/prosody \ + --ostype=linux \ + --with-lua-lib=/usr/lib \ + --with-lua-include=/usr/include \ + --lua-version=5.3 \ + --no-example-certs + # Don't generate certs + rm -f "$builddir"/certs/Makefile + + make +} + +check() { + cd "$builddir" + make test +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install + + install -d -o prosody -g prosody "$pkgdir/var/log/prosody" + install -d -o prosody -g prosody "$pkgdir/var/run/prosody" + install -d -m750 -o prosody -g prosody "$pkgdir/var/lib/prosody" + + install -D -m755 "$srcdir"/"$pkgname".initd "$pkgdir"/etc/init.d/"$pkgname" +} + +sha512sums="9fc05e34b45b0c16835ba94a73532fb3b4ee335f27d56bb9260e1b3e22614f89f44eb5d04b4e90d016db0b5bee6f5c7e7d099e1defb027e6823ee7667c1fe28f prosody-0.10.2.tar.gz +a6ca168fe3d11ee3b05295fb36dfaf8240c60a85507032b2502f9a97d3fd055f7eee38ba6efbb8f79472fc7cdd3556922194d0bd7099f7fb809be01890acc511 prosody.cfg.lua.patch +b07498cd42677d09f1a3fd4a5d91a085e90dd10cee7d6ee7c5e41438cfc2f4049ab9948c0fd0f7e148dd81f6a25c64c6ae832ea4864cee2329d3c6735216b78b mallinfo.patch +24360603dbd5d2a92758e6c4b4aab4f02cbd05373580cba2df76df98b6045891e8108e8c2d16af9508e93968ed5880db952e7a21b2742ebeec6f14b167968c2c prosody.initd" diff --git a/user/prosody/luasec-0.6-fix.patch b/user/prosody/luasec-0.6-fix.patch new file mode 100644 index 000000000..c8e37d091 --- /dev/null +++ b/user/prosody/luasec-0.6-fix.patch @@ -0,0 +1,14 @@ +diff --git a/util/dependencies.lua b/util/dependencies.lua +index 4d50cf6..9ea211d 100644 +--- a/util/dependencies.lua ++++ b/util/dependencies.lua +@@ -99,6 +99,9 @@ function check_dependencies() + ["luarocks"] = "luarocks install luasec"; + ["Source"] = "http://www.inf.puc-rio.br/~brunoos/luasec/"; + }, "SSL/TLS support will not be available"); ++ elseif not _G.ssl then ++ _G.ssl = ssl; ++ _G.ssl.context = require "ssl.context"; + end + + local encodings, err = softreq "util.encodings" diff --git a/user/prosody/mallinfo.patch b/user/prosody/mallinfo.patch new file mode 100644 index 000000000..4f9247c9b --- /dev/null +++ b/user/prosody/mallinfo.patch @@ -0,0 +1,13 @@ +diff --git a/util-src/pposix.c b/util-src/pposix.c +index e70a9d7..b9729ab 100644 +--- a/util-src/pposix.c ++++ b/util-src/pposix.c +@@ -52,7 +52,7 @@ + #include <linux/falloc.h> + #endif + +-#if !defined(WITHOUT_MALLINFO) && defined(__linux__) ++#ifdef __GLIBC__ + #include <malloc.h> + #define WITH_MALLINFO + #endif diff --git a/user/prosody/prosody.cfg.lua.patch b/user/prosody/prosody.cfg.lua.patch new file mode 100644 index 000000000..ff74c5172 --- /dev/null +++ b/user/prosody/prosody.cfg.lua.patch @@ -0,0 +1,36 @@ +diff --git a/prosody.cfg.lua.dist b/prosody.cfg.lua.dist +index a0fc6c9..23a36ac 100644 +--- a/prosody.cfg.lua.dist ++++ b/prosody.cfg.lua.dist +@@ -13,6 +13,9 @@ + -- blanks. Good luck, and happy Jabbering! + + ++daemonize = true ++pidfile = "/var/run/prosody/prosody.pid" ++ + ---------- Server-wide settings ---------- + -- Settings in this section apply to the whole server and are the default settings + -- for any virtual hosts +@@ -86,7 +89,7 @@ modules_disabled = { + -- "offline"; -- Store offline messages + -- "c2s"; -- Handle client connections + -- "s2s"; -- Handle server-to-server connections +- -- "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. ++ "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. + } + + -- Disable account creation by default, for security +@@ -161,9 +164,9 @@ archive_expires_after = "1w" -- Remove archived messages after 1 week + -- Logging configuration + -- For advanced logging see https://prosody.im/doc/logging + log = { +- info = "prosody.log"; -- Change 'info' to 'debug' for verbose logging +- error = "prosody.err"; +- -- "*syslog"; -- Uncomment this for logging to syslog ++ -- info = "prosody.log"; -- Change 'info' to 'debug' for verbose logging ++ -- error = "prosody.err"; ++ "*syslog"; -- Uncomment this for logging to syslog + -- "*console"; -- Log to the console, useful for debugging with daemonize=false + } + diff --git a/user/prosody/prosody.initd b/user/prosody/prosody.initd new file mode 100644 index 000000000..1d835daca --- /dev/null +++ b/user/prosody/prosody.initd @@ -0,0 +1,47 @@ +#!/sbin/openrc-run +# Copyright 1999-2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +description="Prosody is a server for prosody/XMPP written in Lua." +description_reload="Reload configuration and reopen log files." +extra_started_commands="reload" +pidfile="/var/run/prosody/prosody.pid" + +depend() { + use dns + need net + provide prosody-server +} + +checkconfig() { + if [ ! -e /etc/prosody/prosody.cfg.lua ] ; then + eerror "You need a /etc/prosody/prosody.cfg.lua file to run prosody" + return 1 + fi + luac5.2 -p /etc/prosody/prosody.cfg.lua + return $? +} + +start() { + checkconfig || return 1 + checkpath -q -d -m 0770 -o prosody:prosody "$(dirname ${pidfile})" + checkpath -q -f -m 0770 -o prosody:prosody "${pidfile}" + checkpath -q -d -m 0750 -o prosody:prosody /var/log/prosody + ebegin "Starting Prosody XMPP Server" + prosodyctl start + eend $? +} + +stop() { + ebegin "Stopping Prosody XMPP Server" + prosodyctl stop + eend $? +} + +reload() { + checkconfig || return 1 + ebegin "Reloading configuration of Prosody XMPP Server" + prosodyctl reload + eend $? +} diff --git a/user/prosody/prosody.pre-install b/user/prosody/prosody.pre-install new file mode 100644 index 000000000..39d9cfadd --- /dev/null +++ b/user/prosody/prosody.pre-install @@ -0,0 +1,11 @@ +#!/bin/sh + +addgroup -S prosody 2>/dev/null +adduser -S -D \ + -h /var/lib/prosody \ + -s /sbin/nologin \ + -G prosody \ + -g "Prosody XMPP Server" \ + prosody 2>/dev/null + +exit 0 diff --git a/user/prosody/prosodyctl.patch b/user/prosody/prosodyctl.patch new file mode 100644 index 000000000..18333dd52 --- /dev/null +++ b/user/prosody/prosodyctl.patch @@ -0,0 +1,11 @@ +--- prosody-0.9.10.q/prosodyctl ++++ prosody-0.9.10/prosodyctl +@@ -244,7 +244,7 @@ + local modulemanager = require "core.modulemanager" + + local prosodyctl = require "util.prosodyctl" +-require "socket" ++local socket = require "socket" + ----------------------- + + -- FIXME: Duplicate code waiting for util.startup diff --git a/user/protobuf/APKBUILD b/user/protobuf/APKBUILD new file mode 100644 index 000000000..f8ff737a6 --- /dev/null +++ b/user/protobuf/APKBUILD @@ -0,0 +1,108 @@ +# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com> +# Contributor: Natanael Copa <ncopa@alpinelinux.org> +# Maintainer: Dan Theisen <djt@hxx.in> +# TODO: Build Python module, and clean up Ruby build process +pkgname=protobuf +_gemname=google-protobuf +pkgver=3.6.1 +_tstver=1.8.0 +pkgrel=0 +pkgdesc="Library for extensible, efficient structure packing" +url="https://github.com/google/protobuf" +arch="all" +license="BSD-3-Clause" +depends_dev="zlib-dev" +makedepends="$depends_dev autoconf automake libtool ruby ruby-dev ruby-rake" +subpackages="ruby-$_gemname:_ruby $pkgname-dev $pkgname-vim::noarch" +source="$pkgname-$pkgver.tar.gz::https://github.com/google/$pkgname/archive/v$pkgver.tar.gz + googletest-$_tstver.tar.gz::https://github.com/google/googletest/archive/release-$_tstver.tar.gz + musl-fix.patch + trim-rakefile.patch" +builddir="$srcdir/$pkgname-$pkgver" + +prepare() { + default_prepare + + cd "$builddir" + ./autogen.sh + + # symlink tests to the test directory + rm -rf third_party/* + ln -sf "$srcdir"/googletest-release-$_tstver \ + "$builddir"/third_party/googletest +} + +build() { + cd "$builddir" + + CXXFLAGS="$CXXFLAGS -fno-delete-null-pointer-checks" LDFLAGS="$LDFLAGS -latomic" \ + ./configure --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info \ + --localstatedir=/var + make + + cd "$builddir"/ruby + + # Generate proto files for built-in protocols. + rake genproto + + gem build $_gemname.gemspec + gem install --local \ + --install-dir dist \ + --ignore-dependencies \ + --no-document \ + --verbose \ + $_gemname + + # build test-suite + local test; for test in googletest googlemock; do + cd "$builddir/third_party/googletest/$test" + autoreconf -vfi + ./configure + make + done +} + +# TODO: Run tests for ruby gem. +check() { + cd "$builddir" + make check +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install +} + +_ruby() { + pkgdesc="Ruby bindings to Google's data interchange format" + + local gemdir="$subpkgdir/$(ruby -e 'puts Gem.default_dir')" + cd "$builddir"/ruby/dist + + mkdir -p "$gemdir" + cp -r extensions gems specifications "$gemdir"/ + + # Remove duplicated .so libs (should be only in extensions directory). + find "$gemdir"/gems/ -name "*.so" -delete + + # Remove unnecessary files. + cd "$gemdir"/gems/$_gemname-$pkgver + rm -r ext/ tests/ +} + +vim() { + pkgdesc="Vim syntax for $pkgname" + depends="" + install_if="$pkgname=$pkgver-r$pkgrel vim" + + install -Dm644 "$builddir"/editors/proto.vim \ + "$subpkgdir"/usr/share/vim/vimfiles/syntax/proto.vim +} + +sha512sums="1bc175d24b49de1b1e41eaf39598194e583afffb924c86c8d2e569d935af21874be76b2cbd4d9655a1d38bac3d4cd811de88bc2c72d81bad79115e69e5b0d839 protobuf-3.6.1.tar.gz +1dbece324473e53a83a60601b02c92c089f5d314761351974e097b2cf4d24af4296f9eb8653b6b03b1e363d9c5f793897acae1f0c7ac40149216035c4d395d9d googletest-1.8.0.tar.gz +875592bc5dc5efe9087ea1b340673f54c984ecd5aa3b110a2da136bdc28009af7ce1a9c57f4747ff809fc02eb6c39a0209c277177172af467a54172d9700188a musl-fix.patch +d1d11fe76d2a1ae92f47f9eb1e0d94c67b7192a9dc4a382b6c0835f4fe4dbc2f98ca1b3c5095ad5b4e368581072330f943209c0decea02ebb47938588543fdb1 trim-rakefile.patch" diff --git a/user/protobuf/musl-fix.patch b/user/protobuf/musl-fix.patch new file mode 100644 index 000000000..442ca20ed --- /dev/null +++ b/user/protobuf/musl-fix.patch @@ -0,0 +1,22 @@ +seems like both musl libc and android has byteswap.h + +--- a/src/google/protobuf/stubs/port.h ++++ b/src/google/protobuf/stubs/port.h +@@ -94,7 +94,7 @@ + #include <intrin.h> + #elif defined(__APPLE__) + #include <libkern/OSByteOrder.h> +-#elif defined(__GLIBC__) || defined(__BIONIC__) || defined(__CYGWIN__) ++#elif defined(__linux__) || defined(__BIONIC__) || defined(__CYGWIN__) + #include <byteswap.h> // IWYU pragma: export + #endif + +@@ -380,7 +380,7 @@ inline void GOOGLE_UNALIGNED_STORE64(voi + #define bswap_32(x) OSSwapInt32(x) + #define bswap_64(x) OSSwapInt64(x) + +-#elif !defined(__GLIBC__) && !defined(__BIONIC__) && !defined(__CYGWIN__) ++#elif !defined(__linux__) && !defined(__BIONIC__) && !defined(__CYGWIN__) + + static inline uint16 bswap_16(uint16 x) { + return static_cast<uint16>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); diff --git a/user/protobuf/trim-rakefile.patch b/user/protobuf/trim-rakefile.patch new file mode 100644 index 000000000..7f53d7099 --- /dev/null +++ b/user/protobuf/trim-rakefile.patch @@ -0,0 +1,72 @@ +Remove code that we don't use to avoid installing additional dependencies. +--- a/ruby/Rakefile ++++ b/ruby/Rakefile +@@ -1,6 +1,4 @@ + require "rubygems" +-require "rubygems/package_task" +-require "rake/extensiontask" unless RUBY_PLATFORM == "java" + require "rake/testtask" + + spec = Gem::Specification.load("google-protobuf.gemspec") +@@ -39,51 +37,6 @@ + end + end + +-if RUBY_PLATFORM == "java" +- if `which mvn` == '' +- raise ArgumentError, "maven needs to be installed" +- end +- task :clean do +- system("mvn --batch-mode clean") +- end +- +- task :compile do +- system("mvn --batch-mode package") +- end +-else +- Rake::ExtensionTask.new("protobuf_c", spec) do |ext| +- unless RUBY_PLATFORM =~ /darwin/ +- # TODO: also set "no_native to true" for mac if possible. As is, +- # "no_native" can only be set if the RUBY_PLATFORM doing +- # cross-compilation is contained in the "ext.cross_platform" array. +- ext.no_native = true +- end +- ext.ext_dir = "ext/google/protobuf_c" +- ext.lib_dir = "lib/google" +- ext.cross_compile = true +- ext.cross_platform = [ +- 'x86-mingw32', 'x64-mingw32', +- 'x86_64-linux', 'x86-linux', +- 'universal-darwin' +- ] +- end +- +- task 'gem:windows' do +- require 'rake_compiler_dock' +- RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0" +- end +- +- if RUBY_PLATFORM =~ /darwin/ +- task 'gem:native' do +- system "rake genproto" +- system "rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0" +- end +- else +- task 'gem:native' => [:genproto, 'gem:windows'] +- end +-end +- +- + # Proto for tests. + genproto_output << "tests/generated_code.rb" + genproto_output << "tests/test_import.rb" +@@ -104,9 +57,6 @@ + + task :clean do + sh "rm -f #{genproto_output.join(' ')}" +-end +- +-Gem::PackageTask.new(spec) do |pkg| + end + + Rake::TestTask.new(:test => :build) do |t| diff --git a/user/shunit2/APKBUILD b/user/shunit2/APKBUILD index 8a110ff6d..baa658cf8 100644 --- a/user/shunit2/APKBUILD +++ b/user/shunit2/APKBUILD @@ -9,7 +9,7 @@ arch="noarch" license="Apache-2.0" depends="/bin/sh" makedepends="" -checkdepends="debianutils-which bash dash zsh" +checkdepends="cmd:which bash dash zsh" subpackages="$pkgname-doc" source="$pkgname-$pkgver.tar.gz::https://github.com/kward/shunit2/archive/v$pkgver.tar.gz dash-negative-lineno.patch" diff --git a/user/sshfs/APKBUILD b/user/sshfs/APKBUILD index 404c077be..32fcfbd7c 100644 --- a/user/sshfs/APKBUILD +++ b/user/sshfs/APKBUILD @@ -10,7 +10,7 @@ options="!check" # Requires fuse kernel module to be loaded and local ssh serve license="GPL-2.0-only AND GPL-2.0+ AND LGPL-2.1-only" depends="openssh-client" makedepends="fuse3-dev glib-dev meson coreutils py3-docutils" -#checkdepends="py3-pytest debianutils-which" +#checkdepends="py3-pytest cmd:which" subpackages="$pkgname-doc" source="https://github.com/libfuse/$pkgname/releases/download/$pkgname-$pkgver/$pkgname-$pkgver.tar.xz" diff --git a/user/strongswan/APKBUILD b/user/strongswan/APKBUILD index a89a10a6c..29390b652 100644 --- a/user/strongswan/APKBUILD +++ b/user/strongswan/APKBUILD @@ -2,7 +2,7 @@ # Contributor: Natanael Copa <ncopa@alpinelinux.org> # Maintainer: Lee Starnes <lee@canned-death.us> pkgname=strongswan -pkgver=5.7.0 +pkgver=5.7.1 _pkgver=${pkgver//_rc/rc} pkgrel=0 pkgdesc="IPsec-based VPN solution focused on security and ease of use, supporting IKEv1/IKEv2 and MOBIKE" @@ -28,6 +28,10 @@ source="https://download.strongswan.org/$pkgname-$_pkgver.tar.bz2 " builddir="$srcdir/$pkgname-$_pkgver" +# secfixes: +# 5.7.1-r0: +# - CVE-2018-17540 + build() { cd "$builddir" @@ -95,7 +99,7 @@ package() { install -m755 -D "$srcdir/charon.initd" "$pkgdir/etc/init.d/charon" } -sha512sums="811bfa79aa2b17fcf298c45a2b4109cf4235286e90c4def3e09022ed94c7fa481fc25b8d5054529e4ff4e33011ce6f6ba9874595d16c1a8fe13ef924c4ec6395 strongswan-5.7.0.tar.bz2 +sha512sums="43102814434bee7c27a5956be59099cc4ffb9bb5b0d6382ce4c6a80d1d82ed6639f698f5f5544b9ca563554a344638c953525b0e2d39bc6b71b19055c80e07fc strongswan-5.7.1.tar.bz2 193d845e2751c23d98cdf84134c7803f2e412197669c6d6c1c9974041608d154b85594ed3d9ffb923ca22a4d5926c7f2373787ddc7da47b52019e284a1d13211 0205-ike-Adhere-to-IKE_SA-limit-when-checking-out-by-conf.patch 21db8f153f535ef13cc7c9c011f9b90b8c794e0072bd93fda6a0a56dc00d32d04e186b1a72a87a85613b7e511eed5cb96623abf0721c67dd5c96446db969a185 1001-charon-add-optional-source-and-remote-overrides-for-.patch f7d98fb99b4855e8bfbb7369292c170536b1987e717feeda71f64ab71b35538e7d462609a773c6a6ed08c8e6ee7a186df12e1ea7d64b9dac0b17d4c7af17dab3 1002-vici-send-certificates-for-ike-sa-events.patch diff --git a/user/thunar/APKBUILD b/user/thunar/APKBUILD index 5f1360cf9..b11ee1106 100644 --- a/user/thunar/APKBUILD +++ b/user/thunar/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> # Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> pkgname=thunar -pkgver=1.8.1 +pkgver=1.8.2 pkgrel=0 pkgdesc="File manager for the XFCE desktop environment" url="https://xfce.org" @@ -13,7 +13,6 @@ makedepends="intltool gtk+3.0-dev exo-dev libxfce4ui-dev vala-dev subpackages="$pkgname-dev $pkgname-doc $pkgname-lang" langdir="/usr/lib/locale" source="http://archive.xfce.org/src/xfce/thunar/1.8/Thunar-$pkgver.tar.bz2" -sha512sums="89aa29af5e272d58c7de02ba1c96d7f0c32eed49cda9621ef863dd679712cc653f58e729e49b9dc3d1626c9b8ebe2b18a2307e00c7ea1d1d2b42fa71272aced7 Thunar-1.8.1.tar.bz2" builddir="$srcdir/Thunar-$pkgver" build() { @@ -38,3 +37,4 @@ package() { make DESTDIR="$pkgdir" install } +sha512sums="c770fae8b6e5e0e42148ed2b9777afba5159783e5fc716eba1e0499b5390684f386eb575f1a608814bc118bbf05ede34c6737e28c06470c4d01717b579308ec9 Thunar-1.8.2.tar.bz2" diff --git a/user/unrar/APKBUILD b/user/unrar/APKBUILD index 5364d74f6..f50447699 100644 --- a/user/unrar/APKBUILD +++ b/user/unrar/APKBUILD @@ -2,7 +2,7 @@ # Contributor: Carlo Landmeter <clandmeter@gmail.com> # Maintainer: Dan Theisen <djt@hxx.in> pkgname=unrar -pkgver=5.6.6 +pkgver=5.6.8 pkgrel=0 pkgdesc="The RAR uncompression program" url="https://www.rarlab.com" @@ -29,5 +29,5 @@ package() { "$pkgdir/usr/share/licenses/$pkgname/license.txt" } -sha512sums="1e1e9dc2ed104ab7819d11ad2249780a4320cb30f3c427ea1669c3769fa3a8369841711a2d46d918049659bc67b2cd7dc7560a12127d810a57614293c24fe25a unrarsrc-5.6.6.tar.gz +sha512sums="5410308d7f462824bc10087cdc4515c58aaad776cc09eb6491864a338ae00ff35e3b54d1e7250c0a9576554ea382383155be718a0b95d7af00f27d5df04f4f56 unrarsrc-5.6.8.tar.gz 7da30d8454a67999e7052ed2c0ee8d29627b1d47bfdf36e8cf1e24f3c36ee58b17f7e7a6505a4b38e0ca3162067368a1bf554829fd824f7c17a3a2a5b35ca29c makefile.patch" diff --git a/user/which/APKBUILD b/user/which/APKBUILD index 42e7e3b10..cea55c32a 100644 --- a/user/which/APKBUILD +++ b/user/which/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> pkgname=which pkgver=2.21 -pkgrel=1 +pkgrel=2 pkgdesc="A utility to show the full path of commands" url="http://savannah.gnu.org/projects/which" arch="all" @@ -10,6 +10,7 @@ license="GPL-2.0+ AND LGPL-2.0+ AND GPL-3.0+" makedepends="" subpackages="$pkgname-doc" source="http://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz" +provider_priority=1 build() { cd "$builddir" diff --git a/user/xautolock/APKBUILD b/user/xautolock/APKBUILD new file mode 100644 index 000000000..71fd17994 --- /dev/null +++ b/user/xautolock/APKBUILD @@ -0,0 +1,30 @@ +# Contributor: Johannes Matheis <jomat+alpinebuild@jmt.gr> +# Maintainer: Dan Theisen <djt@hxx.in> +pkgname=xautolock +pkgver=2.2 +pkgrel=4 +pkgdesc="An automatic X screen-locker/screen-saver" +url="http://ibiblio.org/pub/Linux/X11/screensavers/" +arch="all" # this might not build on aarch64? removed from alpine commit +license="GPL-2.0" +options="!check" # This package has no testsuite +depends="" +makedepends="$depends_dev imake xorg-server-dev libxscrnsaver-dev xorg-cf-files" +subpackages="$pkgname-doc" +source="https://www.ibiblio.org/pub/linux/X11/screensavers/xautolock-$pkgver.tgz + processwait.patch" + +build() { + cd "$builddir" + xmkmf + make +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install + make MANPATH=/usr/share/man DESTDIR="$pkgdir" install.man +} + +sha512sums="5f9dcc25cda706610e77a74235c4b421ca3a833d154b1a269057f0774579e1c6ec36fe0e5be5fadd6942ce8c1640a760f891397586b162e6024b524635153d04 xautolock-2.2.tgz +3242d01e394f8b84946d7d7fca9a87f2e17783352e180e43470737d3a2e4a7eb15f1a514dcd98118b6491895ab56d3cef29d4abb32b5a341c73efaa2a7ff323a processwait.patch" diff --git a/user/xautolock/processwait.patch b/user/xautolock/processwait.patch new file mode 100644 index 000000000..cb49f8d88 --- /dev/null +++ b/user/xautolock/processwait.patch @@ -0,0 +1,33 @@ +--- xautolock/src/engine.c.orig 2014-08-28 12:50:56.086307943 +0000 ++++ xautolock/src/engine.c 2014-08-28 12:50:59.496333650 +0000 +@@ -209,24 +209,24 @@ evaluateTriggers (Display* d) + { + #else /* VMS */ + if (lockerPid) + { +-#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) ++#if (!defined (UTEKV) && !defined (SYSV) && !defined (SVR4)) && defined (__GLIBC__) + union wait status; /* childs process status */ +-#else /* !UTEKV && !SYSV && !SVR4 */ ++#else /* (!UTEKV && !SYSV && !SVR4) && __GLIBC__ */ + int status = 0; /* childs process status */ +-#endif /* !UTEKV && !SYSV && !SVR4 */ ++#endif /* (!UTEKV && !SYSV && !SVR4) && __GLIBC__ */ + + if (unlockNow && !disabled) + { + (void) kill (lockerPid, SIGTERM); + } + +-#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) ++#if (!defined (UTEKV) && !defined (SYSV) && !defined (SVR4)) && defined (__GLIBC__) + if (wait3 (&status, WNOHANG, 0)) +-#else /* !UTEKV && !SYSV && !SVR4 */ ++#else /* (!UTEKV && !SYSV && !SVR4) && __GLIBC__ */ + if (waitpid (-1, &status, WNOHANG)) +-#endif /* !UTEKV && !SYSV && !SVR4 */ ++#endif /* (!UTEKV && !SYSV && !SVR4) && __GLIBC__ */ + { + /* + * If the locker exited normally, we disable any pending kill + * trigger. Otherwise, we assume that it either has crashed or diff --git a/user/xdotool/APKBUILD b/user/xdotool/APKBUILD index 35d7984cc..3aae63783 100644 --- a/user/xdotool/APKBUILD +++ b/user/xdotool/APKBUILD @@ -12,7 +12,7 @@ license="BSD-3-Clause" depends="" depends_dev="libx11-dev libxtst-dev libxinerama-dev libxkbcommon-dev" makedepends="$depends_dev perl" -#checkdepends="xvfb ruby-minitest debianutils-which lsof xdpyinfo xterm xwininfo" +#checkdepends="xvfb ruby-minitest cmd:which lsof xdpyinfo xterm xwininfo" subpackages="$pkgname-dev $pkgname-doc" source="https://github.com/jordansissel/xdotool/releases/download/v$pkgver/xdotool-$pkgver.tar.gz" diff --git a/user/xfce4-panel-profiles/APKBUILD b/user/xfce4-panel-profiles/APKBUILD index 8719fc556..f30ebb39a 100644 --- a/user/xfce4-panel-profiles/APKBUILD +++ b/user/xfce4-panel-profiles/APKBUILD @@ -9,7 +9,7 @@ arch="noarch" options="!check" # no tests license="GPL-3.0+" depends="python3" -makedepends="intltool which" +makedepends="intltool cmd:which" subpackages="$pkgname-doc $pkgname-lang" source="http://archive.xfce.org/src/apps/xfce4-panel-profiles/1.0/xfce4-panel-profiles-$pkgver.tar.bz2" sha512sums="2d7980a79250414cc4611ccf573c2a3ee5eb510cf3ef6c32035ba23197eee1fded2e158cb50714dd935070916b07b3f33db02570f3d46a598144b4a2d3979ff4 xfce4-panel-profiles-1.0.8.tar.bz2" diff --git a/user/xorg-cf-files/APKBUILD b/user/xorg-cf-files/APKBUILD new file mode 100644 index 000000000..5a438d2bf --- /dev/null +++ b/user/xorg-cf-files/APKBUILD @@ -0,0 +1,38 @@ +# Contributor: Johannes Matheis <jomat+alpinebuild@jmt.gr> +# Maintainer: Dan Theisen <djt@hxx.in> +pkgname=xorg-cf-files +pkgver=1.0.6 +pkgrel=0 +pkgdesc="Data files for the imake utility" +url="http://xorg.freedesktop.org/" +arch="noarch" +license="X11" +options="!check" # This package has no testsuite +depends="" +makedepends="" +subpackages="$pkgname-doc" +source="http://xorg.freedesktop.org/releases/individual/util/${pkgname}-${pkgver}.tar.bz2" + +build() { + cd "$builddir" + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info \ + --localstatedir=/var + make +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install + install -m755 -d "${pkgdir}/usr/share/licenses/${pkgname}" + install -m644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}/" +} + +md5sums="28649f34fa23143f1945aa2750e1472a xorg-cf-files-1.0.6.tar.bz2" +sha256sums="4dcf5a9dbe3c6ecb9d2dd05e629b3d373eae9ba12d13942df87107fdc1b3934d xorg-cf-files-1.0.6.tar.bz2" +sha512sums="1749a5fbcda2c15c300028abce79a3304cfb10f215bf98cf30558144eb64f9fa06a69203159f44405224ed567ac5bc0ff1222e3656367f69acc99f44871424fa xorg-cf-files-1.0.6.tar.bz2" |