libbsd: Branch 'master' - 24 commits

Guillem Jover guillem at kemper.freedesktop.org
Sun May 26 20:42:12 PDT 2013


 COPYING                 |  198 ++++++++---------------------------
 Makefile.am             |    9 -
 configure.ac            |    5 
 include/Makefile.am     |    1 
 include/bsd/libutil.h   |   13 ++
 include/bsd/string.h    |    1 
 include/bsd/wchar.h     |   47 ++++++++
 man/Makefile.am         |    5 
 man/fgetwln.3           |  117 ++++++++++++++++++++
 man/fparseln.3          |  149 ++++++++++++++++++++++++++
 man/radixsort.3         |   23 ++--
 man/setmode.3           |   91 +++++++++++-----
 man/strnstr.3           |  110 +++++++++++++++++++
 man/wcslcat.3           |    1 
 man/wcslcpy.3           |   67 +++++++++++
 src/Makefile.am         |    9 +
 src/dehumanize_number.c |  124 ++++++---------------
 src/fgetln.c            |   30 ++++-
 src/fgetwln.c           |   87 +++++++++++++++
 src/fparseln.c          |  230 ++++++++++++++++++++++++++++++++++++++++
 src/getpeereid.c        |    6 -
 src/heapsort.c          |    2 
 src/libbsd.map          |   15 ++
 src/local-elf.h         |   16 ++
 src/nlist.c             |    3 
 src/radixsort.c         |   70 +++++-------
 src/setmode.c           |   94 ++++++++++------
 src/setproctitle.c      |  271 +++++++++++++++++++++++++++++++++++++++++++-----
 src/strnstr.c           |   65 +++++++++++
 src/wcslcat.c           |   74 +++++++++++++
 src/wcslcpy.c           |   70 ++++++++++++
 test/.gitignore         |    3 
 test/Makefile.am        |    7 +
 test/fgetln.c           |  263 ++++++++++++++++++++++++++++++++++++++++++++++
 test/humanize.c         |   64 +++++++++++
 test/proctitle.c        |   48 ++++++++
 36 files changed, 1995 insertions(+), 393 deletions(-)

New commits:
commit 9587882316f91ab880bf0ad9df2f0f98f2747f7c
Author: Guillem Jover <guillem at hadrons.org>
Date:   Tue May 21 04:34:34 2013 +0200

    Release libbsd 0.5.0

diff --git a/src/Makefile.am b/src/Makefile.am
index 8328372..ded6fa8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,7 +34,7 @@ libbsd_la_DEPENDENCIES = \
 	libbsd.map
 libbsd_la_LDFLAGS = \
 	-Wl,--version-script=$(srcdir)/libbsd.map \
-	-version-number 0:4:2
+	-version-number 0:5:0
 libbsd_la_SOURCES = \
 	arc4random.c \
 	bsd_getopt.c \
commit 01f146c28e3c0d4dd9844c7b454b37aa4d12f45b
Author: Guillem Jover <guillem at hadrons.org>
Date:   Mon May 27 04:41:58 2013 +0200

    build: Handle the ChangeLog as a distributed-only file
    
    The ChangeLog file is distributed, and cannot be regenerated outside
    of the git repository, so do not remove it in DISTCLEANFILES, and move
    the generation code into dist-hook, which also avoids unnecessary
    computation during normal builds.

diff --git a/Makefile.am b/Makefile.am
index ae7cd20..8e50b1d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,11 +9,8 @@ EXTRA_DIST = \
 	get-version \
 	$(nil)
 
-DISTCLEANFILES = ChangeLog
-.PHONY: ChangeLog
-
-ChangeLog:
-	git log --stat -C >$@
-
 dist-hook:
 	echo $(VERSION) >$(distdir)/.dist-version
+	if [ -d .git ]; then \
+	  git log --stat -C >$(distdir)/ChangeLog; \
+	fi
commit 509841b53319068d8e943d5584288ad2042e3b3c
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sat May 25 15:44:57 2013 +0200

    build: Use AM_V_at for mkdir

diff --git a/src/Makefile.am b/src/Makefile.am
index 95ebbb9..8328372 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,7 +27,7 @@ pkgconfig_DATA = \
 lib_LTLIBRARIES = libbsd.la
 
 hash/md5hl.c: $(srcdir)/hash/helper.c
-	$(MKDIR_P) hash
+	$(AM_V_at) $(MKDIR_P) hash
 	$(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@
 
 libbsd_la_DEPENDENCIES = \
commit 06f0585c4855fac5f219ba0d99fbaf0f3e8f65e1
Author: Guillem Jover <guillem at hadrons.org>
Date:   Tue May 21 10:31:59 2013 +0200

    build: Compress the distribution tarball with xz instead of gzip

diff --git a/configure.ac b/configure.ac
index 2fcd511..bdadc6e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ AC_CONFIG_SRCDIR([src/fgetln.c])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_MACRO_DIR([m4])
 
-AM_INIT_AUTOMAKE([1.8 foreign nostdinc])
+AM_INIT_AUTOMAKE([1.8 foreign nostdinc no-dist-gzip dist-xz])
 
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
                             [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
commit 7c4caa679a5065d1a34608c583c479a6e66a37e3
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sat May 25 15:36:11 2013 +0200

    Fix comparison between signed and unsigned integer compiler warnings

diff --git a/src/heapsort.c b/src/heapsort.c
index 2479cb0..7e345c7 100644
--- a/src/heapsort.c
+++ b/src/heapsort.c
@@ -135,7 +135,7 @@ heapsort(vbase, nmemb, size, compar)
 	size_t nmemb, size;
 	int (*compar)(const void *, const void *);
 {
-	int cnt, i, j, l;
+	size_t cnt, i, j, l;
 	char tmp, *tmp1, *tmp2;
 	char *base, *k, *p, *t;
 
diff --git a/src/nlist.c b/src/nlist.c
index 7f9ed96..6c9be51 100644
--- a/src/nlist.c
+++ b/src/nlist.c
@@ -100,7 +100,8 @@ __fdnlist(fd, list)
 	int fd;
 	struct nlist *list;
 {
-	int n = -1, i;
+	size_t i;
+	int n = -1;
 
 	for (i = 0; i < sizeof(nlist_fn) / sizeof(nlist_fn[0]); i++) {
 		n = (nlist_fn[i].fn)(fd, list);
diff --git a/src/radixsort.c b/src/radixsort.c
index 45e2477..b9746fc 100644
--- a/src/radixsort.c
+++ b/src/radixsort.c
@@ -175,7 +175,7 @@ r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
 		 * character at position i, move on to the next
 		 * character.
 		 */
-		if (nc == 1 && count[bmin] == n) {
+		if (nc == 1 && count[bmin] == (u_int)n) {
 			push(a, n, i+1);
 			nc = count[bmin] = 0;
 			continue;
commit 30349f8922db271043ec334a719f9910f79eecf1
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sat May 25 15:35:39 2013 +0200

    Update radixsort module from NetBSD
    
    Merge some interesting changes.

diff --git a/man/radixsort.3 b/man/radixsort.3
index 3884124..069e401 100644
--- a/man/radixsort.3
+++ b/man/radixsort.3
@@ -1,3 +1,5 @@
+.\"	$NetBSD: radixsort.3,v 1.12 2003/04/16 13:34:46 wiz Exp $
+.\"
 .\" Copyright (c) 1990, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -9,7 +11,7 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
@@ -25,14 +27,14 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     @(#)radixsort.3	8.2 (Berkeley) 1/27/94
-.\" $FreeBSD$
+.\"     from: @(#)radixsort.3	8.2 (Berkeley) 1/27/94
 .\"
 .Dd January 27, 1994
 .Dt RADIXSORT 3
 .Os
 .Sh NAME
-.Nm radixsort , sradixsort
+.Nm radixsort ,
+.Nm sradixsort
 .Nd radix sort
 .Sh LIBRARY
 .ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
@@ -52,12 +54,17 @@ and
 functions
 are implementations of radix sort.
 .Pp
-These functions sort an array of pointers to byte strings, the initial
-member of which is referenced by
+These functions sort an
+.Fa nmemb
+element array of pointers to byte strings, with
+the initial member of which is referenced by
 .Fa base .
-The byte strings may contain any values; the end of each string
-is denoted by the user-specified value
+The byte strings may contain any values.
+End of strings is denoted
+by character which has same weight as user specified value
 .Fa endbyte .
+.Fa endbyte
+has to be between 0 and 255.
 .Pp
 Applications may specify a sort order by providing the
 .Fa table
diff --git a/src/radixsort.c b/src/radixsort.c
index 82ff1bc..45e2477 100644
--- a/src/radixsort.c
+++ b/src/radixsort.c
@@ -1,3 +1,4 @@
+/*     $NetBSD: radixsort.c,v 1.18 2009/08/21 20:49:50 dsl Exp $       */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -13,7 +14,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -30,11 +31,14 @@
  * SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
+#if 0
 static char sccsid[] = "@(#)radixsort.c	8.2 (Berkeley) 4/28/95";
+#else
+__RCSID("$NetBSD: radixsort.c,v 1.18 2009/08/21 20:49:50 dsl Exp $");
+#endif
 #endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
 
 /*
  * Radixsort routines.
@@ -59,11 +63,10 @@ typedef struct {
 	int sn, si;
 } stack;
 
-static inline void simplesort
-(const u_char **, int, int, const u_char *, u_int);
+static inline void simplesort(const u_char **, int, int, const u_char *, u_int);
 static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
-static void r_sort_b(const u_char **, const u_char **, int, int,
-    const u_char *, u_int);
+static void r_sort_b(const u_char **,
+	    const u_char **, int, int, const u_char *, u_int);
 
 #define	THRESHOLD	20		/* Divert to simplesort(). */
 #define	SIZE		512		/* Default stack size. */
@@ -88,13 +91,10 @@ static void r_sort_b(const u_char **, const u_char **, int, int,
 }
 
 int
-radixsort(a, n, tab, endch)
-	const u_char **a, *tab;
-	int n;
-	u_int endch;
+radixsort(const u_char **a, int n, const u_char *tab, u_int endch)
 {
 	const u_char *tr;
-	int c;
+	u_int c;
 	u_char tr0[256];
 
 	SETUP;
@@ -103,15 +103,17 @@ radixsort(a, n, tab, endch)
 }
 
 int
-sradixsort(a, n, tab, endch)
-	const u_char **a, *tab;
-	int n;
-	u_int endch;
+sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
 {
 	const u_char *tr, **ta;
-	int c;
+	u_int c;
 	u_char tr0[256];
 
+	if (a == NULL) {
+		errno = EFAULT;
+		return (-1);
+	}
+
 	SETUP;
 	if (n < THRESHOLD)
 		simplesort(a, n, 0, tr, endch);
@@ -131,17 +133,13 @@ sradixsort(a, n, tab, endch)
 
 /* Unstable, in-place sort. */
 static void
-r_sort_a(a, n, i, tr, endch)
-	const u_char **a;
-	int n, i;
-	const u_char *tr;
-	u_int endch;
+r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
 {
-	static int count[256], nc, bmin;
-	int c;
+	static u_int count[256], nc, bmin;
+	u_int c;
 	const u_char **ak, *r;
 	stack s[SIZE], *sp, *sp0, *sp1, temp;
-	int *cp, bigc;
+	u_int *cp, bigc;
 	const u_char **an, *t, **aj, **top[256];
 
 	/* Set up stack. */
@@ -233,18 +231,15 @@ r_sort_a(a, n, i, tr, endch)
 
 /* Stable sort, requiring additional memory. */
 static void
-r_sort_b(a, ta, n, i, tr, endch)
-	const u_char **a, **ta;
-	int n, i;
-	const u_char *tr;
-	u_int endch;
+r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
+    u_int endch)
 {
-	static int count[256], nc, bmin;
-	int c;
+	static u_int count[256], nc, bmin;
+	u_int c;
 	const u_char **ak, **ai;
 	stack s[512], *sp, *sp0, *sp1, temp;
 	const u_char **top[256];
-	int *cp, bigc;
+	u_int *cp, bigc;
 
 	sp = s;
 	push(a, n, i);
@@ -304,12 +299,9 @@ r_sort_b(a, ta, n, i, tr, endch)
 	}
 }
 
+/* insertion sort */
 static inline void
-simplesort(a, n, b, tr, endch)	/* insertion sort */
-	const u_char **a;
-	int n, b;
-	const u_char *tr;
-	u_int endch;
+simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
 {
 	u_char ch;
 	const u_char  **ak, **ai, *s, *t;
commit 96a2dae3525ba28cea954d6d445bb2d03c0cff66
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sat May 25 15:31:45 2013 +0200

    Update setmode module from NetBSD
    
    Merge some interesting changes.

diff --git a/man/setmode.3 b/man/setmode.3
index ae7c568..5073d43 100644
--- a/man/setmode.3
+++ b/man/setmode.3
@@ -1,3 +1,5 @@
+.\"	$NetBSD: setmode.3,v 1.18.28.1 2009/01/04 17:02:19 christos Exp $
+.\"
 .\" Copyright (c) 1989, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -9,7 +11,7 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
@@ -28,7 +30,7 @@
 .\"     @(#)setmode.3	8.2 (Berkeley) 4/28/95
 .\" $FreeBSD: src/lib/libc/gen/setmode.3,v 1.12 2007/01/09 00:27:55 imp Exp $
 .\"
-.Dd April 28, 1995
+.Dd January 4, 2009
 .Dt SETMODE 3
 .Os
 .Sh NAME
@@ -40,34 +42,40 @@
 .Lb libbsd
 .Sh SYNOPSIS
 .In bsd/unistd.h
-.Ft mode_t
-.Fn getmode "const void *set" "mode_t mode"
 .Ft void *
 .Fn setmode "const char *mode_str"
+.Ft mode_t
+.Fn getmode "const void *set" "mode_t mode"
 .Sh DESCRIPTION
 The
+.Fn setmode
+function accepts a string representation of a file mode change,
+compiles it to binary form, and returns an abstract representation
+that may be passed to
+.Fn getmode .
+The string may be an numeric (octal) or symbolic string of the form
+accepted by
+.Xr chmod 1 ,
+and may represent either an exact mode to set or a change to make to
+the existing mode.
+.Pp
+The
 .Fn getmode
 function
-returns a copy of the file permission bits
+adjusts the file permission bits given by
 .Fa mode
-as altered by the values pointed to by
-.Fa set .
-While only the mode bits are altered, other parts of the file mode
-may be examined.
+according to the compiled change representation
+.Fa set ,
+and returns the adjusted mode.
+While only the permission bits are altered, other parts of the file
+mode, particularly the type, may be examined.
 .Pp
-The
-.Fn setmode
-function
-takes an absolute (octal) or symbolic value, as described in
-.Xr chmod 1 ,
-as an argument
-and returns a pointer to mode values to be supplied to
-.Fn getmode .
-Because some of the symbolic values are relative to the file
-creation mask,
+Because some of the possible symbolic values are defined relative to
+the file creation mask,
 .Fn setmode
 may call
-.Xr umask 2 .
+.Xr umask 2 ,
+temporarily changing the mask.
 If this occurs, the file creation mask will be restored before
 .Fn setmode
 returns.
@@ -75,13 +83,13 @@ If the calling program changes the value of its file creation mask
 after calling
 .Fn setmode ,
 .Fn setmode
-must be called again if
+must be called again to recompile the mode string if
 .Fn getmode
 is to modify future file modes correctly.
 .Pp
 If the mode passed to
 .Fn setmode
-is invalid or if memory cannot be allocated for the return value,
+is invalid,
 .Fn setmode
 returns
 .Dv NULL .
@@ -94,13 +102,40 @@ and should be returned to the system with
 .Fn free
 when the program is done with it, generally after a call to
 .Fn getmode .
+.Sh EXAMPLES
+The effects of the shell command
+.Ql "chmod a+x myscript.sh"
+can be duplicated as follows:
+.Bd -literal -offset indent
+const char *file = "myscript.sh";
+struct stat st;
+mode_t newmode;
+
+stat(file, \*[Am]st);
+newmode = getmode(setmode("a+x"), st.st_mode);
+chmod(file, newmode);
+.Ed
 .Sh ERRORS
 The
 .Fn setmode
 function
-may fail and set errno for any of the errors specified for the library
-routine
-.Xr malloc 3 .
+may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr malloc 3
+or
+.Xr strtol 3 .
+In addition,
+.Fn setmode
+will fail and set
+.Va errno
+to:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa mode
+argument does not represent a valid mode.
+.El
 .Sh SEE ALSO
 .Xr chmod 1 ,
 .Xr stat 2 ,
@@ -113,3 +148,9 @@ and
 .Fn setmode
 functions first appeared in
 .Bx 4.4 .
+.Sh BUGS
+The type of
+.Fa set
+should really be some opaque struct type used only by these functions
+rather than
+.Ft void * .
diff --git a/src/setmode.c b/src/setmode.c
index d9c7b8d..c3c9a8b 100644
--- a/src/setmode.c
+++ b/src/setmode.c
@@ -1,3 +1,5 @@
+/*	$NetBSD: setmode.c,v 1.34 2012/06/25 22:32:43 abs Exp $	*/
+
 /*
  * Copyright (c) 1989, 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -13,7 +15,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -30,19 +32,23 @@
  * SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
+#if 0
 static char sccsid[] = "@(#)setmode.c	8.2 (Berkeley) 3/25/94";
+#else
+__RCSID("$NetBSD: setmode.c,v 1.34 2012/06/25 22:32:43 abs Exp $");
+#endif
 #endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/setmode.c,v 1.11 2007/01/09 00:27:55 imp Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <ctype.h>
+#include <errno.h>
 #include <signal.h>
-#include <stddef.h>
 #include <stdlib.h>
+#include <limits.h>
 #include <unistd.h>
 
 #ifdef SETMODE_DEBUG
@@ -64,7 +70,7 @@ typedef struct bitcmd {
 #define	CMD2_OBITS	0x08
 #define	CMD2_UBITS	0x10
 
-static BITCMD	*addcmd(BITCMD *, int, int, int, u_int);
+static BITCMD	*addcmd(BITCMD *, mode_t, mode_t, mode_t, mode_t);
 static void	 compress_mode(BITCMD *);
 #ifdef SETMODE_DEBUG
 static void	 dumpmode(BITCMD *);
@@ -144,38 +150,38 @@ common:			if (set->cmd2 & CMD2_CLR) {
 		}
 }
 
-#define	ADDCMD(a, b, c, d)						\
+#define	ADDCMD(a, b, c, d) do {						\
 	if (set >= endset) {						\
 		BITCMD *newset;						\
 		setlen += SET_LEN_INCR;					\
 		newset = realloc(saveset, sizeof(BITCMD) * setlen);	\
-		if (!newset) {						\
-			if (saveset)					\
-				free(saveset);				\
-			saveset = NULL;					\
-			return (NULL);					\
-		}							\
+		if (newset == NULL)					\
+			goto out;					\
 		set = newset + (set - saveset);				\
 		saveset = newset;					\
 		endset = newset + (setlen - 2);				\
 	}								\
-	set = addcmd(set, (a), (b), (c), (d))
+	set = addcmd(set, (mode_t)(a), (mode_t)(b), (mode_t)(c), (d));	\
+} while (/*CONSTCOND*/0)
 
 #define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
 
 void *
 setmode(const char *p)
 {
-	int perm, who;
+	int serrno;
 	char op, *ep;
 	BITCMD *set, *saveset, *endset;
-	sigset_t sigset, sigoset;
-	mode_t mask;
-	int equalopdone=0, permXbits, setlen;
-	long perml;
-
-	if (!*p)
-		return (NULL);
+	sigset_t signset, sigoset;
+	mode_t mask, perm, permXbits, who;
+	long lval;
+	int equalopdone = 0;	/* pacify gcc */
+	int setlen;
+
+	if (!*p) {
+		errno = EINVAL;
+		return NULL;
+	}
 
 	/*
 	 * Get a copy of the mask for the permissions that are mask relative.
@@ -183,8 +189,8 @@ setmode(const char *p)
 	 * the caller is opening files inside a signal handler, protect them
 	 * as best we can.
 	 */
-	sigfillset(&sigset);
-	(void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
+	sigfillset(&signset);
+	(void)sigprocmask(SIG_BLOCK, &signset, &sigoset);
 	(void)umask(mask = umask(0));
 	mask = ~mask;
 	(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
@@ -201,12 +207,19 @@ setmode(const char *p)
 	 * or illegal bits.
 	 */
 	if (isdigit((unsigned char)*p)) {
-		perml = strtol(p, &ep, 8);
-		if (*ep || perml < 0 || perml & ~(STANDARD_BITS|S_ISTXT)) {
-			free(saveset);
-			return (NULL);
+		errno = 0;
+		lval = strtol(p, &ep, 8);
+		if (*ep) {
+			errno = EINVAL;
+			goto out;
+		}
+		if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
+			goto out;
+		if (lval & ~(STANDARD_BITS|S_ISTXT)) {
+			errno = EINVAL;
+			goto out;
 		}
-		perm = (mode_t)perml;
+		perm = (mode_t)lval;
 		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
 		set->cmd = 0;
 		return (saveset);
@@ -238,8 +251,8 @@ setmode(const char *p)
 		}
 
 getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
-			free(saveset);
-			return (NULL);
+			errno = EINVAL;
+			goto out;
 		}
 		if (op == '=')
 			equalopdone = 0;
@@ -251,13 +264,19 @@ getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
 				perm |= S_IRUSR|S_IRGRP|S_IROTH;
 				break;
 			case 's':
-				/* If only "other" bits ignore set-id. */
-				if (!who || who & ~S_IRWXO)
+				/*
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
+				 */
+				if (who == 0 || (who & ~S_IRWXO))
 					perm |= S_ISUID|S_ISGID;
 				break;
 			case 't':
-				/* If only "other" bits ignore sticky. */
-				if (!who || who & ~S_IRWXO) {
+				/*
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
+				 */
+				if (who == 0 || (who & ~S_IRWXO)) {
 					who |= S_ISTXT;
 					perm |= S_ISTXT;
 				}
@@ -328,10 +347,15 @@ apply:		if (!*p)
 	dumpmode(saveset);
 #endif
 	return (saveset);
+out:
+	serrno = errno;
+	free(saveset);
+	errno = serrno;
+	return NULL;
 }
 
 static BITCMD *
-addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
+addcmd(BITCMD *set, mode_t op, mode_t who, mode_t oparg, mode_t mask)
 {
 	switch (op) {
 	case '=':
commit a4812cdf240fac5d0461288094cc94e03e030272
Author: Casper Dik <casper.dik at oracle.com>
Date:   Fri Mar 15 01:13:58 2013 +0100

    Fix getpeereid() compilation on Solaris
    
    The code in getpeereid() is unlikely to compile as ucred_t is an opaque
    struct (ucred_t * works but ucred_t does not). Either you need to give
    a pointer initialized to NULL and getpeerucred() allocates a new ucred
    or you call it with an allocated ucred as in this patch.
    
    Signed-off-by: Guillem Jover <guillem at hadrons.org>

diff --git a/src/getpeereid.c b/src/getpeereid.c
index 3694219..193f366 100644
--- a/src/getpeereid.c
+++ b/src/getpeereid.c
@@ -99,11 +99,13 @@ getpeereid(int s, uid_t *euid, gid_t *egid)
 }
 #elif defined(__sun)
 /* Solaris */
+#include <alloca.h>
+#include <ucred.h>
+
 int
 getpeereid(int s, uid_t *euid, gid_t *egid)
 {
-	ucred_t cred_inst;
-	ucred_t *cred = &cred_inst;
+	ucred_t *cred = alloca(ucred_size());
 	int ret;
 
 	ret = getpeerucred(s, &cred);
commit d3a09e1cf4daa6f8a2eededa55ff4c812e11e858
Author: Guillem Jover <guillem at hadrons.org>
Date:   Thu Dec 27 11:19:20 2012 +0100

    Switch dehumanize_number() to use expand_number()
    
    The function is a duplicate of expand_number(), but covering less
    prefixes and with a slightly different function signature.
    
    Spotted-by: Peter da Silva <resuna at gmail.com>

diff --git a/COPYING b/COPYING
index df42038..5bcfd38 100644
--- a/COPYING
+++ b/COPYING
@@ -201,7 +201,7 @@ The rest of the licenses apply to code and/or man pages.
 
     --
 
-    Copyright © 1997-2000, 2002, 2005, 2006, 2008 The NetBSD Foundation, Inc.
+    Copyright © 1997-2000, 2002, 2008 The NetBSD Foundation, Inc.
     All rights reserved.
 
     Some code was contributed to The NetBSD Foundation by Allen Briggs.
diff --git a/src/dehumanize_number.c b/src/dehumanize_number.c
index 4884422..640f1fb 100644
--- a/src/dehumanize_number.c
+++ b/src/dehumanize_number.c
@@ -1,12 +1,5 @@
-/*	$NetBSD: dehumanize_number.c,v 1.2 2007/12/14 17:32:47 xtraeme Exp $	*/
-
 /*
- * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
- * 2005 program.
+ * Copyright © 2012 Guillem Jover <guillem at hadrons.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -16,99 +9,54 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 #include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: dehumanize_number.c,v 1.2 2007/12/14 17:32:47 xtraeme Exp $");
-#endif /* LIBC_SCCS and not lint */
 
-#include <inttypes.h>
+#include <errno.h>
 #include <ctype.h>
+#include <libutil.h>
+#include <stdint.h>
 #include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
 
-/*
- * Converts the number given in 'str', which may be given in a humanized
- * form (as described in humanize_number(3), but with some limitations),
- * to an int64_t without units.
- * In case of success, 0 is returned and *size holds the value.
- * Otherwise, -1 is returned and *size is untouched.
- *
- * TODO: Internationalization, SI units.
- */
 int
-dehumanize_number(const char *str, int64_t *size)
+dehumanize_number(const char *buf, int64_t *num)
 {
-	char *ep, unit;
-	const char *delimit;
-	long multiplier;
-	long long tmp, tmp2;
-	size_t len;
-
-	len = strlen(str);
-	if (len == 0) {
-		errno = EINVAL;
-		return -1;
+	uint64_t rval;
+	int sign = 1;
+	int rc;
+
+	/* The current expand_number() implementation uses bit shifts, so
+	 * we cannot pass negative numbers, preserve the sign and apply it
+	 * later. */
+	while (isspace(*buf))
+		buf++;
+	if (*buf == '-') {
+		sign = -1;
+		buf++;
 	}
 
-	multiplier = 1;
-
-	unit = str[len - 1];
-	if (isalpha((unsigned char)unit)) {
-		switch (tolower((unsigned char)unit)) {
-		case 'b':
-			multiplier = 1;
-			break;
-
-		case 'k':
-			multiplier = 1024;
-			break;
-
-		case 'm':
-			multiplier = 1024 * 1024;
-			break;
-
-		case 'g':
-			multiplier = 1024 * 1024 * 1024;
-			break;
-
-		default:
-			errno = EINVAL;
-			return -1; /* Invalid suffix. */
-		}
-
-		delimit = &str[len - 1];
-	} else
-		delimit = NULL;
-
-	errno = 0;
-	tmp = strtoll(str, &ep, 10);
-	if (str[0] == '\0' || (ep != delimit && *ep != '\0'))
-		return -1; /* Not a number. */
-	else if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN))
-		return -1; /* Out of range. */
-
-	tmp2 = tmp * multiplier;
-	tmp2 = tmp2 / multiplier;
-	if (tmp != tmp2) {
+	rc = expand_number(buf, &rval);
+	if (rc < 0)
+		return rc;
+	if (rval == UINT64_MAX && sign == -1) {
 		errno = ERANGE;
-		return -1; /* Out of range. */
+		return -1;
 	}
-	*size = tmp * multiplier;
+	*num = rval * sign;
 
 	return 0;
 }
commit 330b569fe3333f91eb7c0192ab0c5af7e15c616f
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sun May 26 04:34:57 2013 +0200

    test: Add new humanize unit test

diff --git a/test/.gitignore b/test/.gitignore
index 0d3e678..9a927b0 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,5 +1,6 @@
 endian
 fgetln
 headers
+humanize
 overlay
 proctitle
diff --git a/test/Makefile.am b/test/Makefile.am
index 170d177..73a1e91 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -11,10 +11,12 @@ check_PROGRAMS = \
 	headers \
 	overlay \
 	endian \
+	humanize \
 	fgetln \
 	proctitle \
 	$(nil)
 
+humanize_LDFLAGS = $(top_builddir)/src/libbsd.la
 fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la
 proctitle_LDFLAGS = $(top_builddir)/src/libbsd.la
 
diff --git a/test/humanize.c b/test/humanize.c
new file mode 100644
index 0000000..caa8fec
--- /dev/null
+++ b/test/humanize.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2013 Guillem Jover <guillem at hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+int
+main(int argc, char **argv)
+{
+	uint64_t uval;
+	int64_t val;
+
+	assert(expand_number("512", &uval) == 0);
+	assert(uval == 512);
+
+	assert(expand_number("512b", &uval) == 0);
+	assert(uval == 512);
+
+	assert(expand_number("10k", &uval) == 0);
+	assert(uval == 10240);
+
+	assert(expand_number("20M", &uval) == 0);
+	assert(uval == 20971520);
+
+	assert(dehumanize_number("512", &val) == 0);
+	assert(val == 512);
+
+	assert(dehumanize_number("512b", &val) == 0);
+	assert(val == 512);
+
+	assert(dehumanize_number("10k", &val) == 0);
+	assert(val == 10240);
+
+	assert(dehumanize_number("20M", &val) == 0);
+	assert(val == 20971520);
+
+	assert(dehumanize_number("-3G", &val) == 0);
+	assert(val == -3221225472);
+
+	return 0;
+}
commit 8c26c40ad2cc606a3ac1a4f7ea50d72864d21f17
Author: Guillem Jover <guillem at hadrons.org>
Date:   Tue Nov 27 14:23:26 2012 +0100

    test: Add setproctitle() unit test

diff --git a/test/.gitignore b/test/.gitignore
index 8fda062..0d3e678 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -2,3 +2,4 @@ endian
 fgetln
 headers
 overlay
+proctitle
diff --git a/test/Makefile.am b/test/Makefile.am
index f36b408..170d177 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -12,8 +12,10 @@ check_PROGRAMS = \
 	overlay \
 	endian \
 	fgetln \
+	proctitle \
 	$(nil)
 
 fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la
+proctitle_LDFLAGS = $(top_builddir)/src/libbsd.la
 
 TESTS = $(check_PROGRAMS)
diff --git a/test/proctitle.c b/test/proctitle.c
new file mode 100644
index 0000000..450f0d1
--- /dev/null
+++ b/test/proctitle.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2012 Guillem Jover <guillem at hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main(int argc, char **argv)
+{
+	const char newtitle_base[] = "test arg1 arg2";
+	char *newtitle_full;
+
+	setproctitle("-test %s arg2", "arg1");
+	assert(strcmp(argv[0], newtitle_base) == 0);
+
+	asprintf(&newtitle_full, "%s: %s", getprogname(), newtitle_base);
+	setproctitle("test %s arg2", "arg1");
+	assert(strcmp(argv[0], newtitle_full) == 0);
+	free(newtitle_full);
+
+	return 0;
+}
commit e9933255d4234a7d16f5e2f261376dd10747d469
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sat May 25 17:11:53 2013 +0200

    Make setproctitle() available in 0.2 and 0.5 version nodes
    
    Make the 0.5 version the default, so that code wanting the actual
    implemented version can get a proper versioned depdendency. For code
    linked against the old version, make it available as an alias.

diff --git a/configure.ac b/configure.ac
index 1644510..2fcd511 100644
--- a/configure.ac
+++ b/configure.ac
@@ -38,6 +38,7 @@ AC_CHECK_HEADERS([sys/ndir.h sys/dir.h dir.h dirent.h])
 # Checks for typedefs, structures, and compiler characteristics.
 AC_TYPE_UID_T
 AC_C_INLINE
+AC_C_TYPEOF
 AC_TYPE_INT64_T
 AC_TYPE_MODE_T
 AC_TYPE_OFF_T
diff --git a/src/libbsd.map b/src/libbsd.map
index e900ee3..4067e2c 100644
--- a/src/libbsd.map
+++ b/src/libbsd.map
@@ -73,8 +73,6 @@ LIBBSD_0.2 {
     pidfile_close;
     pidfile_remove;
 
-    setproctitle;
-
     arc4random_buf;
     arc4random_uniform;
 } LIBBSD_0.1;
@@ -99,6 +97,9 @@ LIBBSD_0.5 {
     fgetwln;
     fparseln;
 
+    /* Introduced in 0.2 as a stub, implemented in 0.5. */
+    setproctitle;
+
     strnstr;
 
     wcslcat;
diff --git a/src/setproctitle.c b/src/setproctitle.c
index 969f266..60b6484 100644
--- a/src/setproctitle.c
+++ b/src/setproctitle.c
@@ -191,7 +191,7 @@ spt_init(int argc, char *argv[], char *envp[])
 #endif
 
 void
-setproctitle(const char *fmt, ...)
+setproctitle_impl(const char *fmt, ...)
 {
 	/* Use buffer in case argv[0] is passed. */
 	char buf[SPT_MAXTITLE + 1];
@@ -243,3 +243,13 @@ setproctitle(const char *fmt, ...)
 		*++nul = '\0';
 	}
 }
+__asm__(".symver setproctitle_impl,setproctitle@@LIBBSD_0.5");
+
+#ifdef HAVE_TYPEOF
+/* The original function introduced in 0.2 was a stub, it only got implemented
+ * in 0.5, make the implementation available in the old version as an alias
+ * for code linking against that version, and change the default to use the
+ * new version, so that new code depends on the implemented version. */
+extern typeof(setproctitle_impl) setproctitle_stub __attribute__((alias("setproctitle_impl")));
+__asm__(".symver setproctitle_stub,setproctitle at LIBBSD_0.2");
+#endif
commit c984dacd65920b2f48cf0f4e579030488799f496
Author: Guillem Jover <guillem at hadrons.org>
Date:   Tue Nov 27 14:24:13 2012 +0100

    Implement sendmail semantics for setproctitle()
    
    Prefix the title with "progname: ", and skip it if the format string
    starts with '-' (which gets skipped on output too).

diff --git a/src/setproctitle.c b/src/setproctitle.c
index 1817739..969f266 100644
--- a/src/setproctitle.c
+++ b/src/setproctitle.c
@@ -203,8 +203,18 @@ setproctitle(const char *fmt, ...)
 		return;
 
 	if (fmt) {
+		if (fmt[0] == '-') {
+			/* Skip program name prefix. */
+			fmt++;
+			len = 0;
+		} else {
+			/* Print program name heading for grep. */
+			snprintf(buf, sizeof(buf), "%s: ", getprogname());
+			len = strlen(buf);
+		}
+
 		va_start(ap, fmt);
-		len = vsnprintf(buf, sizeof(buf), fmt, ap);
+		len += vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
 		va_end(ap);
 	} else {
 		len = snprintf(buf, sizeof(buf), "%s", SPT.arg0);
commit 35785f8dd1be73ef8e08c18a88e77e00fe332b6c
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sun Nov 25 21:10:53 2012 +0100

    Modify setproctitle() to conform to project coding style
    
    Use local getprogname()/setprogname() instead of reimplementing them
    locally. Use clearenv() if available, not just on glibc. Use bool
    instead of _Bool. Use paranthesis on sizeof. Fold the SPT_MIN macro
    into spt_min(). Make spt_init() static. Avoid unnecessary gotos.

diff --git a/COPYING b/COPYING
index 56375e8..df42038 100644
--- a/COPYING
+++ b/COPYING
@@ -432,6 +432,7 @@ The rest of the licenses apply to code and/or man pages.
     --
 
     Copyright © 2010 William Ahern
+    Copyright © 2012 Guillem Jover <guillem at hadrons.org>
 
     Permission is hereby granted, free of charge, to any person obtaining a
     copy of this software and associated documentation files (the
diff --git a/configure.ac b/configure.ac
index 063bf92..1644510 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,7 +71,7 @@ AC_LINK_IFELSE(
 	 AC_MSG_RESULT([yes])],
 	[AC_MSG_RESULT([no])])
 
-AC_CHECK_FUNCS([dirfd __fpurge getexecname getline sysconf])
+AC_CHECK_FUNCS([clearenv dirfd __fpurge getexecname getline sysconf])
 
 AC_CONFIG_FILES([
 	Makefile
diff --git a/src/setproctitle.c b/src/setproctitle.c
index 7ef5a0a..1817739 100644
--- a/src/setproctitle.c
+++ b/src/setproctitle.c
@@ -1,7 +1,6 @@
-/* ==========================================================================
- * setproctitle.c - Linux/Darwin setproctitle.
- * --------------------------------------------------------------------------
- * Copyright (C) 2010  William Ahern
+/*
+ * Copyright © 2010 William Ahern
+ * Copyright © 2012 Guillem Jover <guillem at hadrons.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
@@ -21,142 +20,130 @@
  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ==========================================================================
  */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <stddef.h>	/* NULL size_t */
-#include <stdarg.h>	/* va_list va_start va_end */
-#include <stdlib.h>	/* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */
-#include <stdio.h>	/* vsnprintf(3) snprintf(3) */
-
-#include <string.h>	/* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */
-
-#include <errno.h>	/* errno program_invocation_name program_invocation_short_name */
-
-
-#if !defined(HAVE_SETPROCTITLE)
-#define HAVE_SETPROCTITLE (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)
-#endif
-
-
-#if !HAVE_SETPROCTITLE
-#if (defined __linux || defined __APPLE__) && defined __GNUC__
 
+#include <errno.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
 
 static struct {
-	/* original value */
+	/* Original value. */
 	const char *arg0;
 
-	/* title space available */
+	/* Title space available. */
 	char *base, *end;
 
-	 /* pointer to original nul character within base */
+	 /* Pointer to original nul character within base. */
 	char *nul;
 
-	_Bool reset;
+	bool reset;
 	int error;
 } SPT;
 
 
-#ifndef SPT_MIN
-#define SPT_MIN(a, b) (((a) < (b))? (a) : (b))
-#endif
-
-static inline size_t spt_min(size_t a, size_t b) {
-	return SPT_MIN(a, b);
-} /* spt_min() */
-
+static inline size_t
+spt_min(size_t a, size_t b)
+{
+	return a < b ? a : b;
+}
 
 /*
  * For discussion on the portability of the various methods, see
  * http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
  */
-static int spt_clearenv(void) {
-#if __GLIBC__
-	clearenv();
-
-	return 0;
+static int
+spt_clearenv(void)
+{
+#ifdef HAVE_CLEARENV
+	return clearenv();
 #else
-	extern char **environ;
 	char **tmp;
 
-	if (!(tmp = malloc(sizeof *tmp)))
+	tmp = malloc(sizeof(*tmp));
+	if (tmp == NULL)
 		return errno;
 
-	tmp[0]  = NULL;
+	tmp[0] = NULL;
 	environ = tmp;
 
 	return 0;
 #endif
-} /* spt_clearenv() */
-
+}
 
-static int spt_copyenv(char *oldenv[]) {
-	extern char **environ;
+static int
+spt_copyenv(char *oldenv[])
+{
 	char *eq;
 	int i, error;
 
 	if (environ != oldenv)
 		return 0;
 
-	if ((error = spt_clearenv()))
-		goto error;
+	error = spt_clearenv();
+	if (error) {
+		environ = oldenv;
+		return error;
+	}
 
 	for (i = 0; oldenv[i]; i++) {
-		if (!(eq = strchr(oldenv[i], '=')))
+		eq = strchr(oldenv[i], '=');
+		if (eq == NULL)
 			continue;
 
 		*eq = '\0';
-		error = (0 != setenv(oldenv[i], eq + 1, 1))? errno : 0;
+		if (setenv(oldenv[i], eq + 1, 1) < 0)
+			error = errno;
 		*eq = '=';
 
-		if (error)
-			goto error;
+		if (error) {
+			environ = oldenv;
+			return error;
+		}
 	}
 
 	return 0;
-error:
-	environ = oldenv;
-
-	return error;
-} /* spt_copyenv() */
-
+}
 
-static int spt_copyargs(int argc, char *argv[]) {
+static int
+spt_copyargs(int argc, char *argv[])
+{
 	char *tmp;
 	int i;
 
 	for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
-		if (!argv[i])
+		if (argv[i] == NULL)
 			continue;
 
-		if (!(tmp = strdup(argv[i])))
+		tmp = strdup(argv[i]);
+		if (tmp == NULL)
 			return errno;
 
 		argv[i] = tmp;
 	}
 
 	return 0;
-} /* spt_copyargs() */
-
-
-void spt_init(int argc, char *argv[], char *envp[]) __attribute__((constructor));
+}
 
-void spt_init(int argc, char *argv[], char *envp[]) {
+static void __attribute__((constructor))
+spt_init(int argc, char *argv[], char *envp[])
+{
 	char *base, *end, *nul, *tmp;
 	int i, error;
 
-	if (!(base = argv[0]))
+	base = argv[0];
+	if (base == NULL)
 		return;
 
 	nul = &base[strlen(base)];
 	end = nul + 1;
 
 	for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
-		if (!argv[i] || argv[i] < end)
+		if (argv[i] == NULL || argv[i] < end)
 			continue;
 
 		end = argv[i] + strlen(argv[i]) + 1;
@@ -169,77 +156,73 @@ void spt_init(int argc, char *argv[], char *envp[]) {
 		end = envp[i] + strlen(envp[i]) + 1;
 	}
 
-	if (!(SPT.arg0 = strdup(argv[0])))
-		goto syerr;
-
-#if __GLIBC__
-	if (!(tmp = strdup(program_invocation_name)))
-		goto syerr;
-
-	program_invocation_name = tmp;
-
-	if (!(tmp = strdup(program_invocation_short_name)))
-		goto syerr;
-
-	program_invocation_short_name = tmp;
-#elif __APPLE__
-	if (!(tmp = strdup(getprogname())))
-		goto syerr;
+	SPT.arg0 = strdup(argv[0]);
+	if (SPT.arg0 == NULL) {
+		SPT.error = errno;
+		return;
+	}
 
+	tmp = strdup(getprogname());
+	if (tmp == NULL) {
+		SPT.error = errno;
+		return;
+	}
 	setprogname(tmp);
-#endif
 
+	error = spt_copyenv(envp);
+	if (error) {
+		SPT.error = error;
+		return;
+	}
 
-	if ((error = spt_copyenv(envp)))
-		goto error;
-
-	if ((error = spt_copyargs(argc, argv)))
-		goto error;
+	error = spt_copyargs(argc, argv);
+	if (error) {
+		SPT.error = error;
+		return;
+	}
 
 	SPT.nul  = nul;
 	SPT.base = base;
 	SPT.end  = end;
-
-	return;
-syerr:
-	error = errno;
-error:
-	SPT.error = error;
-} /* spt_init() */
-
+}
 
 #ifndef SPT_MAXTITLE
 #define SPT_MAXTITLE 255
 #endif
 
-void setproctitle(const char *fmt, ...) {
-	char buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */
+void
+setproctitle(const char *fmt, ...)
+{
+	/* Use buffer in case argv[0] is passed. */
+	char buf[SPT_MAXTITLE + 1];
 	va_list ap;
 	char *nul;
-	int len, error;
+	int len;
 
-	if (!SPT.base)
+	if (SPT.base == NULL)
 		return;
 
 	if (fmt) {
 		va_start(ap, fmt);
-		len = vsnprintf(buf, sizeof buf, fmt, ap);
+		len = vsnprintf(buf, sizeof(buf), fmt, ap);
 		va_end(ap);
 	} else {
-		len = snprintf(buf, sizeof buf, "%s", SPT.arg0);
+		len = snprintf(buf, sizeof(buf), "%s", SPT.arg0);
 	}
 
-	if (len <= 0)
-		{ error = errno; goto error; }
+	if (len <= 0) {
+		SPT.error = errno;
+		return;
+	}
 
 	if (!SPT.reset) {
 		memset(SPT.base, 0, SPT.end - SPT.base);
-		SPT.reset = 1;
+		SPT.reset = true;
 	} else {
-		memset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base));
+		memset(SPT.base, 0, spt_min(sizeof(buf), SPT.end - SPT.base));
 	}
 
-	len = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1);
+	len = spt_min(len, spt_min(sizeof(buf), SPT.end - SPT.base) - 1);
 	memcpy(SPT.base, buf, len);
 	nul = &SPT.base[len];
 
@@ -249,12 +232,4 @@ void setproctitle(const char *fmt, ...) {
 		*SPT.nul = ' ';
 		*++nul = '\0';
 	}
-
-	return;
-error:
-	SPT.error = error;
-} /* setproctitle() */
-
-
-#endif /* __linux || __APPLE__ */
-#endif /* !HAVE_SETPROCTITLE */
+}
commit 2a0260d08c5f9ecc43fef99c4e180c0d977deba5
Author: William Ahern <william at 25thandClement.com>
Date:   Wed Nov 28 11:09:02 2012 +0100

    Add a setproctitle() implementation
    
    Taken from libnostd.
    
    Signed-off-by: Guillem Jover <guillem at hadrons.org>

diff --git a/COPYING b/COPYING
index 417a884..56375e8 100644
--- a/COPYING
+++ b/COPYING
@@ -431,6 +431,29 @@ The rest of the licenses apply to code and/or man pages.
 
     --
 
+    Copyright © 2010 William Ahern
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to permit
+    persons to whom the Software is furnished to do so, subject to the
+    following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+    NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+    USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    --
+
     This code implements the MD5 message-digest algorithm.
     The algorithm is due to Ron Rivest. This code was
     written by Colin Plumb in 1993, no copyright is claimed.
diff --git a/src/setproctitle.c b/src/setproctitle.c
index 239fb01..7ef5a0a 100644
--- a/src/setproctitle.c
+++ b/src/setproctitle.c
@@ -1,32 +1,260 @@
-/*
- * Copyright © 2010 Guillem Jover <guillem at hadrons.org>
+/* ==========================================================================
+ * setproctitle.c - Linux/Darwin setproctitle.
+ * --------------------------------------------------------------------------
+ * Copyright (C) 2010  William Ahern
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
  *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ==========================================================================
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stddef.h>	/* NULL size_t */
+#include <stdarg.h>	/* va_list va_start va_end */
+#include <stdlib.h>	/* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */
+#include <stdio.h>	/* vsnprintf(3) snprintf(3) */
+
+#include <string.h>	/* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */
+
+#include <errno.h>	/* errno program_invocation_name program_invocation_short_name */
+
+
+#if !defined(HAVE_SETPROCTITLE)
+#define HAVE_SETPROCTITLE (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)
+#endif
+
+
+#if !HAVE_SETPROCTITLE
+#if (defined __linux || defined __APPLE__) && defined __GNUC__
+
+
+static struct {
+	/* original value */
+	const char *arg0;
+
+	/* title space available */
+	char *base, *end;
+
+	 /* pointer to original nul character within base */
+	char *nul;
+
+	_Bool reset;
+	int error;
+} SPT;
+
+
+#ifndef SPT_MIN
+#define SPT_MIN(a, b) (((a) < (b))? (a) : (b))
+#endif
+
+static inline size_t spt_min(size_t a, size_t b) {
+	return SPT_MIN(a, b);
+} /* spt_min() */
+
+
+/*
+ * For discussion on the portability of the various methods, see
+ * http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
  */
+static int spt_clearenv(void) {
+#if __GLIBC__
+	clearenv();
+
+	return 0;
+#else
+	extern char **environ;
+	char **tmp;
+
+	if (!(tmp = malloc(sizeof *tmp)))
+		return errno;
+
+	tmp[0]  = NULL;
+	environ = tmp;
+
+	return 0;
+#endif
+} /* spt_clearenv() */
+
+
+static int spt_copyenv(char *oldenv[]) {
+	extern char **environ;
+	char *eq;
+	int i, error;
+
+	if (environ != oldenv)
+		return 0;
+
+	if ((error = spt_clearenv()))
+		goto error;
+
+	for (i = 0; oldenv[i]; i++) {
+		if (!(eq = strchr(oldenv[i], '=')))
+			continue;
+
+		*eq = '\0';
+		error = (0 != setenv(oldenv[i], eq + 1, 1))? errno : 0;
+		*eq = '=';
+
+		if (error)
+			goto error;
+	}
+
+	return 0;
+error:
+	environ = oldenv;
+
+	return error;
+} /* spt_copyenv() */
+
+
+static int spt_copyargs(int argc, char *argv[]) {
+	char *tmp;
+	int i;
+
+	for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
+		if (!argv[i])
+			continue;
+
+		if (!(tmp = strdup(argv[i])))
+			return errno;
+
+		argv[i] = tmp;
+	}
+
+	return 0;
+} /* spt_copyargs() */
+
+
+void spt_init(int argc, char *argv[], char *envp[]) __attribute__((constructor));
+
+void spt_init(int argc, char *argv[], char *envp[]) {
+	char *base, *end, *nul, *tmp;
+	int i, error;
+
+	if (!(base = argv[0]))
+		return;
+
+	nul = &base[strlen(base)];
+	end = nul + 1;
+
+	for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
+		if (!argv[i] || argv[i] < end)
+			continue;
+
+		end = argv[i] + strlen(argv[i]) + 1;
+	}
+
+	for (i = 0; envp[i]; i++) {
+		if (envp[i] < end)
+			continue;
+
+		end = envp[i] + strlen(envp[i]) + 1;
+	}
+
+	if (!(SPT.arg0 = strdup(argv[0])))
+		goto syerr;
+
+#if __GLIBC__
+	if (!(tmp = strdup(program_invocation_name)))
+		goto syerr;
+
+	program_invocation_name = tmp;
+
+	if (!(tmp = strdup(program_invocation_short_name)))
+		goto syerr;
+
+	program_invocation_short_name = tmp;
+#elif __APPLE__
+	if (!(tmp = strdup(getprogname())))
+		goto syerr;
+
+	setprogname(tmp);
+#endif
+
+
+	if ((error = spt_copyenv(envp)))
+		goto error;
+
+	if ((error = spt_copyargs(argc, argv)))
+		goto error;
+
+	SPT.nul  = nul;
+	SPT.base = base;
+	SPT.end  = end;
+
+	return;
+syerr:
+	error = errno;
+error:
+	SPT.error = error;
+} /* spt_init() */
+
+
+#ifndef SPT_MAXTITLE
+#define SPT_MAXTITLE 255
+#endif
+
+void setproctitle(const char *fmt, ...) {
+	char buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */
+	va_list ap;
+	char *nul;
+	int len, error;
+
+	if (!SPT.base)
+		return;
+
+	if (fmt) {
+		va_start(ap, fmt);
+		len = vsnprintf(buf, sizeof buf, fmt, ap);
+		va_end(ap);
+	} else {
+		len = snprintf(buf, sizeof buf, "%s", SPT.arg0);
+	}
+
+	if (len <= 0)
+		{ error = errno; goto error; }
+
+	if (!SPT.reset) {
+		memset(SPT.base, 0, SPT.end - SPT.base);
+		SPT.reset = 1;
+	} else {
+		memset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base));
+	}
+
+	len = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1);
+	memcpy(SPT.base, buf, len);
+	nul = &SPT.base[len];
+
+	if (nul < SPT.nul) {
+		*SPT.nul = '.';
+	} else if (nul == SPT.nul && &nul[1] < SPT.end) {
+		*SPT.nul = ' ';
+		*++nul = '\0';
+	}
+
+	return;
+error:
+	SPT.error = error;
+} /* setproctitle() */
+
 
-void
-setproctitle(const char *fmt, ...)
-{
-	/* Stub so that we can implement it later on and programs will
-	 * automatically benefit from it, w/o needing to recompile. */
-}
+#endif /* __linux || __APPLE__ */
+#endif /* !HAVE_SETPROCTITLE */
commit f8d52ead5e913a74a44351f7a805987bfda0ac18
Author: Guillem Jover <guillem at hadrons.org>
Date:   Fri Nov 23 18:33:23 2012 +0100

    Add x32 support to nlist()

diff --git a/src/local-elf.h b/src/local-elf.h
index 37e9146..3f935ac 100644
--- a/src/local-elf.h
+++ b/src/local-elf.h
@@ -46,7 +46,11 @@
 #elif defined(__amd64__)
 
 #define ELF_TARG_MACH	EM_X86_64
+#if defined(__ILP32__)
+#define ELF_TARG_CLASS	ELFCLASS32
+#else
 #define ELF_TARG_CLASS	ELFCLASS64
+#endif
 #define ELF_TARG_DATA	ELFDATA2LSB
 
 #elif defined(__arm__)
commit cf683a275a13c2d8bd0ebc9a5953bb974aba3fae
Author: Guillem Jover <guillem at hadrons.org>
Date:   Fri Nov 23 18:32:35 2012 +0100

    Add arm64 (aka aarch64) to nlist()

diff --git a/src/local-elf.h b/src/local-elf.h
index afcc8ed..37e9146 100644
--- a/src/local-elf.h
+++ b/src/local-elf.h
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2009 Guillem Jover <guillem at hadrons.org>
+ * Copyright © 2009, 2012 Guillem Jover <guillem at hadrons.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -59,6 +59,16 @@
 #define ELF_TARG_DATA	ELFDATA2LSB
 #endif
 
+#elif defined(__aarch64__)
+
+#define ELF_TARG_MACH	EM_AARCH64
+#define ELF_TARG_CLASS	ELFCLASS64
+#if defined(__AARCH64EB__)
+#define ELF_TARG_DATA	ELFDATA2MSB
+#else
+#define ELF_TARG_DATA	ELFDATA2LSB
+#endif
+
 #elif defined(__avr32__)
 
 #ifndef EM_AVR32
commit 7196b4dccaaa796dd96358162fdf143393162a8d
Author: Guillem Jover <guillem at hadrons.org>
Date:   Thu May 23 02:05:19 2013 +0200

    test: Add new fgetln() and fgetwln() unit test

diff --git a/test/.gitignore b/test/.gitignore
index 1c5d1f8..8fda062 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,3 +1,4 @@
 endian
+fgetln
 headers
 overlay
diff --git a/test/Makefile.am b/test/Makefile.am
index 1d41b86..f36b408 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -11,6 +11,9 @@ check_PROGRAMS = \
 	headers \
 	overlay \
 	endian \
+	fgetln \
 	$(nil)
 
+fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la
+
 TESTS = $(check_PROGRAMS)
diff --git a/test/fgetln.c b/test/fgetln.c
new file mode 100644
index 0000000..83d120c
--- /dev/null
+++ b/test/fgetln.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2013 Guillem Jover <guillem at hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/wait.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <wchar.h>
+
+#define skip(msg) \
+	do { \
+		printf("skip: %s\n", (msg)); \
+		return; \
+	} while (0)
+
+#define DATA_LINES 3
+
+static const char *data_ascii[] = {
+	"this represents an ascii sequence of lines to test the\n",
+	"fgetln() family of functions\n",
+	"last line without an ending newline",
+};
+static const wchar_t *data_wide[] = {
+	L"this represénts an utf-8 seqüence of lînes to test the\n",
+	L"«fgetln()» family of functions § but with an extremely long "
+	 "line to test that the reallocation logic works fine, and that "
+	 "the strings end up being equal…\n",
+	L"last line ☭ without an ‽ ending newline ♥",
+};
+
+#define FILE_COUNT 32
+
+#define LINE_COUNT 2
+#define LINE_LEN 2
+
+struct file {
+	FILE *fp;
+	const void **lines;
+
+	const void *got_buf;
+	int got_len;
+};
+
+static FILE *
+pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
+{
+	FILE *fp;
+	int rc;
+	int pipefd[2];
+	pid_t pid;
+
+	rc = pipe(pipefd);
+	assert(rc >= 0);
+
+	pid = fork();
+	assert(pid >= 0);
+
+	if (pid == 0) {
+		int line;
+
+		/* Child writes data to pipe. */
+		rc = close(pipefd[0]);
+		assert(rc >= 0);
+
+		fp = fdopen(pipefd[1], "w");
+		assert(fp);
+
+		for (line = 0; line < buf_nmemb; line++) {
+			rc = fprintf(fp, fmt, buf[line]);
+			assert(rc >= 0);
+		}
+
+		rc = fclose(fp);
+		assert(rc >= 0);
+
+		_exit(0);
+	} else {
+		/* Parent gets a FILE and reads from it. */
+		rc = close(pipefd[1]);
+		assert(rc >= 0);
+
+		fp = fdopen(pipefd[0], "r");
+		assert(fp);
+
+		return fp;
+	}
+}
+
+static void
+pipe_close(FILE *fp)
+{
+	fclose(fp);
+	wait(NULL);
+}
+
+static void
+test_fgetln_single(void)
+{
+	FILE *fp;
+	size_t len;
+	int i;
+
+	fp = pipe_feed("%s", (const void **)data_ascii, DATA_LINES);
+	for (i = 0; i < DATA_LINES; i++) {
+		char *str = fgetln(fp, &len);
+
+		assert(str);
+		assert(memcmp(str, data_ascii[i], len) == 0);
+	}
+	assert(fgetln(fp, &len) == NULL);
+	pipe_close(fp);
+}
+
+static void
+test_fgetln_multi(void)
+{
+	struct file files[FILE_COUNT];
+	int i, l;
+
+	for (i = 0; i < FILE_COUNT; i++) {
+		char *str;
+
+		str = strdup("A\n");
+		str[0] += i;
+
+		files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
+		files[i].lines[0] = str;
+		files[i].lines[1] = str;
+		files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
+	}
+
+	for (l = 0; l < LINE_COUNT; l++) {
+		for (i = 0; i < FILE_COUNT; i++) {
+			size_t len;
+			char *str;
+
+			str = fgetln(files[i].fp, &len);
+
+			assert(str);
+			assert(len == LINE_LEN);
+
+			files[i].got_len = len;
+			files[i].got_buf = str;
+		}
+
+		for (i = 0; i < FILE_COUNT; i++) {
+			assert(memcmp(files[i].lines[l], files[i].got_buf,
+			              files[i].got_len) == 0);
+		}
+	}
+
+	for (i = 0; i < LINE_COUNT; i++)
+		pipe_close(files[i].fp);
+}
+
+static void
+test_fgetwln_single(void)
+{
+	FILE *fp;
+	size_t len;
+	int i;
+
+	fp = pipe_feed("%ls", (const void **)data_wide, DATA_LINES);
+	for (i = 0; i < DATA_LINES; i++) {
+		wchar_t *wstr;
+
+		wstr = fgetwln(fp, &len);
+		assert(wstr);
+
+		assert(wmemcmp(data_wide[i], wstr, len) == 0);
+	}
+	assert(fgetwln(fp, &len) == NULL);
+	pipe_close(fp);
+}
+
+static void
+test_fgetwln_multi(void)
+{
+	struct file files[FILE_COUNT];
+	int i, l;
+
+	for (i = 0; i < FILE_COUNT; i++) {
+		wchar_t *wstr;
+
+		wstr = wcsdup(L"A\n");
+		wstr[0] += i;
+
+		files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
+		files[i].lines[0] = wstr;
+		files[i].lines[1] = wstr;
+		files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);
+	}
+
+	for (l = 0; l < LINE_COUNT; l++) {
+		for (i = 0; i < FILE_COUNT; i++) {
+			size_t len;
+			wchar_t *wstr;
+
+			wstr = fgetwln(files[i].fp, &len);
+
+			assert(wstr);
+			assert(len == LINE_LEN);
+
+			files[i].got_len = len;
+			files[i].got_buf = wstr;
+		}
+
+		for (i = 0; i < FILE_COUNT; i++) {
+			assert(wmemcmp(files[i].lines[l], files[i].got_buf,
+			               files[i].got_len) == 0);
+		}
+	}
+
+	for (i = 0; i < LINE_COUNT; i++)
+		pipe_close(files[i].fp);
+}
+
+static void
+test_fgetwln(void)
+{
+	if (setlocale(LC_ALL, "C.UTF-8") == NULL &&
+	    setlocale(LC_ALL, "en_US.UTF-8") == NULL)
+		skip("no default UTF-8 locale found");
+
+	test_fgetwln_single();
+	test_fgetwln_multi();
+}
+
+int
+main(int argc, char **argv)
+{
+	test_fgetln_single();
+	test_fgetln_multi();
+	test_fgetwln();
+
+	return 0;
+}
commit a97ce513e031b29a47965b740be14fb9a84277fc
Author: Guillem Jover <guillem at hadrons.org>
Date:   Fri Nov 23 21:19:45 2012 +0100

    Add new fgetwln() function
    
    Man page taken from FreeBSD.

diff --git a/include/bsd/wchar.h b/include/bsd/wchar.h
index 9b16f53..a7e25bf 100644
--- a/include/bsd/wchar.h
+++ b/include/bsd/wchar.h
@@ -38,6 +38,8 @@
 #include <sys/types.h>
 
 __BEGIN_DECLS
+wchar_t *fgetwln(FILE *stream, size_t *len);
+
 size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
 size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
 __END_DECLS
diff --git a/man/Makefile.am b/man/Makefile.am
index 6881f12..eb9c133 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -24,6 +24,7 @@ dist_man_MANS = \
 	dehumanize_number.3 \
 	expand_number.3 \
 	fgetln.3 \
+	fgetwln.3 \
 	flopen.3 \
 	fmtcheck.3 \
 	fparseln.3 \
diff --git a/man/fgetwln.3 b/man/fgetwln.3
new file mode 100644
index 0000000..0372d21
--- /dev/null
+++ b/man/fgetwln.3
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)fgetln.3	8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd July 16, 2004
+.Dt FGETWLN 3
+.Os
+.Sh NAME
+.Nm fgetwln
+.Nd get a line of wide characters from a stream
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.Lb libbsd
+.Sh SYNOPSIS
+.In stdio.h
+.In bsd/wchar.h
+.Ft wchar_t *
+.Fn fgetwln "FILE * restrict stream" "size_t * restrict len"
+.Sh DESCRIPTION
+The
+.Fn fgetwln
+function
+returns a pointer to the next line from the stream referenced by
+.Fa stream .
+This line is
+.Em not
+a standard wide character string as it does not end with a terminating
+null wide character.
+The length of the line, including the final newline,
+is stored in the memory location to which
+.Fa len
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
+.Sh RETURN VALUES
+Upon successful completion a pointer is returned;
+this pointer becomes invalid after the next
+.Tn I/O
+operation on
+.Fa stream
+(whether successful or not)
+or as soon as the stream is closed.
+Otherwise,
+.Dv NULL
+is returned.
+The
+.Fn fgetwln
+function
+does not distinguish between end-of-file and error; the routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used
+to determine which occurred.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv NULL
+until the condition is
+cleared with
+.Xr clearerr 3 .
+.Pp
+The text to which the returned pointer points may be modified,
+provided that no changes are made beyond the returned size.
+These changes are lost as soon as the pointer becomes invalid.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa stream
+is not a stream open for reading.
+.El
+.Pp
+The
+.Fn fgetwln
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr mbrtowc 3 ,
+.Xr realloc 3 ,
+or
+.Xr read 2 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgetln 3 ,
+.Xr fgetws 3 ,
+.Xr fopen 3
diff --git a/src/Makefile.am b/src/Makefile.am
index 2146438..95ebbb9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,7 @@ libbsd_la_SOURCES = \
 	err.c \
 	expand_number.c \
 	fgetln.c \
+	fgetwln.c \
 	flopen.c \
 	fmtcheck.c \
 	fparseln.c \
diff --git a/src/fgetwln.c b/src/fgetwln.c
new file mode 100644
index 0000000..2473932
--- /dev/null
+++ b/src/fgetwln.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2012 Guillem Jover <guillem at hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+
+struct filewbuf {
+	FILE *fp;
+	wchar_t *wbuf;
+	size_t len;
+};
+
+#define FILEWBUF_INIT_LEN	128
+#define FILEWBUF_POOL_ITEMS	32
+
+static struct filewbuf fb_pool[FILEWBUF_POOL_ITEMS];
+static int fb_pool_cur;
+
+wchar_t *
+fgetwln(FILE *stream, size_t *lenp)
+{
+	struct filewbuf *fb;
+	wint_t wc;
+	size_t wused = 0;
+
+	/* Try to diminish the possibility of several fgetwln() calls being
+	 * used on different streams, by using a pool of buffers per file. */
+	fb = &fb_pool[fb_pool_cur];
+	if (fb->fp != stream && fb->fp != NULL) {
+		fb_pool_cur++;
+		fb_pool_cur %= FILEWBUF_POOL_ITEMS;
+		fb = &fb_pool[fb_pool_cur];
+	}
+	fb->fp = stream;
+
+	while ((wc = fgetwc(stream)) != WEOF) {
+		if (!fb->len || wused > fb->len) {
+			wchar_t *wp;
+
+			if (fb->len)
+				fb->len *= 2;
+			else
+				fb->len = FILEWBUF_INIT_LEN;
+
+			wp = realloc(fb->wbuf, fb->len * sizeof(wchar_t));
+			if (wp == NULL) {
+				wused = 0;
+				break;
+			}
+			fb->wbuf = wp;
+		}
+
+		fb->wbuf[wused++] = wc;
+
+		if (wc == L'\n')
+			break;
+	}
+
+	*lenp = wused;
+	return wused ? fb->wbuf : NULL;
+}
diff --git a/src/libbsd.map b/src/libbsd.map
index 488267c..e900ee3 100644
--- a/src/libbsd.map
+++ b/src/libbsd.map
@@ -96,6 +96,7 @@ LIBBSD_0.4 {
 } LIBBSD_0.3;
 
 LIBBSD_0.5 {
+    fgetwln;
     fparseln;
 
     strnstr;
commit ee0489eb2bd09298f547c57a59f28dcd094d781e
Author: Strake <strake888 at gmail.com>
Date:   Tue Aug 7 08:44:30 2012 -0500

    Add new fparseln() function
    
    Taken from NetBSD.
    
    [guillem at hadrons.org:
     - Import from NetBSD instead of FreeBSD to get a 3-clause BSD license,
       instead of a 4-clause one.
     - Define compatibility macros.
     - Change library from libc to libbsd and header in man page.
     - Add copyright information to COPYING.
     - Add symbol to map file. ]
    
    Signed-off-by: Guillem Jover <guillem at hadrons.org>

diff --git a/COPYING b/COPYING
index 5a42e50..417a884 100644
--- a/COPYING
+++ b/COPYING
@@ -283,6 +283,9 @@ The rest of the licenses apply to code and/or man pages.
 
     --
 
+    Copyright © 1997 Christos Zoulas.
+    All rights reserved.
+
     Copyright © 2002 Niels Provos <provos at citi.umich.edu>
     All rights reserved.
 
diff --git a/include/bsd/libutil.h b/include/bsd/libutil.h
index 648473c..ebb6160 100644
--- a/include/bsd/libutil.h
+++ b/include/bsd/libutil.h
@@ -40,8 +40,10 @@
 #define _LIBUTIL_H_
 
 #include <features.h>
+#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <stdint.h>
+#include <stdio.h>
 
 /* for pidfile.c */
 struct pidfh {
@@ -62,6 +64,8 @@ struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
 int pidfile_write(struct pidfh *pfh);
 int pidfile_close(struct pidfh *pfh);
 int pidfile_remove(struct pidfh *pfh);
+
+char   *fparseln(FILE *, size_t *, size_t *, const char[3], int);
 __END_DECLS
 
 /* humanize_number(3) */
@@ -73,4 +77,13 @@ __END_DECLS
 #define HN_GETSCALE             0x10
 #define HN_AUTOSCALE            0x20
 
+/*
+ * fparseln() specific operation flags.
+ */
+#define FPARSELN_UNESCESC	0x01
+#define FPARSELN_UNESCCONT	0x02
+#define FPARSELN_UNESCCOMM	0x04
+#define FPARSELN_UNESCREST	0x08
+#define FPARSELN_UNESCALL	0x0f
+
 #endif /* !_LIBUTIL_H_ */
diff --git a/man/Makefile.am b/man/Makefile.am
index d43ce85..6881f12 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -26,6 +26,7 @@ dist_man_MANS = \
 	fgetln.3 \
 	flopen.3 \
 	fmtcheck.3 \
+	fparseln.3 \
 	getmode.3 \
 	getpeereid.3 \
 	getprogname.3 \
diff --git a/man/fparseln.3 b/man/fparseln.3
new file mode 100644
index 0000000..1c215ac
--- /dev/null
+++ b/man/fparseln.3
@@ -0,0 +1,149 @@
+.\"	$NetBSD: fparseln.3,v 1.4 2009/10/21 01:07:45 snj Exp $
+.\"
+.\" Copyright (c) 1997 Christos Zoulas.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd November 30, 2002
+.Dt FPARSELN 3
+.Os
+.Sh NAME
+.Nm fparseln
+.Nd return the next logical line from a stream
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.Lb libbsd
+.Sh SYNOPSIS
+.In bsd/stdio.h
+.Ft "char *"
+.Fo "fparseln"
+.Fa "FILE *stream" "size_t *len" "size_t *lineno"
+.Fa "const char delim[3]" "int flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn fparseln
+function
+returns a pointer to the next logical line from the stream referenced by
+.Fa stream .
+This string is
+.Dv NUL
+terminated and it is dynamically allocated on each invocation.
+It is the responsibility of the caller to free the pointer.
+.Pp
+By default, if a character is escaped, both it and the preceding escape
+character will be present in the returned string.
+Various
+.Fa flags
+alter this behaviour.
+.Pp
+The meaning of the arguments is as follows:
+.Bl -tag -width "lineno"
+.It Fa stream
+The stream to read from.
+.It Fa len
+If not
+.Dv NULL ,
+the length of the string is stored in the memory location to which it
+points.
+.It Fa lineno
+If not
+.Dv NULL ,
+the value of the memory location to which is pointed to, is incremented
+by the number of lines actually read from the file.
+.It Fa delim
+Contains the escape, continuation, and comment characters.
+If a character is
+.Dv NUL
+then processing for that character is disabled.
+If
+.Dv NULL ,
+all characters default to values specified below.
+The contents of
+.Fa delim
+is as follows:
+.Bl -tag -width "delim[0]"
+.It Fa delim[0]
+The escape character, which defaults to
+.Cm \e ,
+is used to remove any special meaning from the next character.
+.It Fa delim[1]
+The continuation character, which defaults to
+.Cm \e ,
+is used to indicate that the next line should be concatenated with the
+current one if this character is the last character on the current line
+and is not escaped.
+.It Fa delim[2]
+The comment character, which defaults to
+.Cm # ,
+if not escaped indicates the beginning of a comment that extends until the
+end of the current line.
+.El
+.It Fa flags
+If non-zero, alter the operation of
+.Fn fparseln .
+The various flags, which may be
+.Em or Ns -ed
+together, are:
+.Bl -tag -width "FPARSELN_UNESCCOMM"
+.It Dv FPARSELN_UNESCCOMM
+Remove escape preceding an escaped comment.
+.It Dv FPARSELN_UNESCCONT
+Remove escape preceding an escaped continuation.
+.It Dv FPARSELN_UNESCESC
+Remove escape preceding an escaped escape.
+.It Dv FPARSELN_UNESCREST
+Remove escape preceding any other character.
+.It Dv FPARSELN_UNESCALL
+All of the above.
+.El
+.Pp
+.El
+.Sh RETURN VALUES
+Upon successful completion a pointer to the parsed line is returned;
+otherwise,
+.Dv NULL
+is returned.
+.Pp
+The
+.Fn fparseln
+function uses internally
+.Xr fgetln 3 ,
+so all error conditions that apply to
+.Xr fgetln 3 ,
+apply to
+.Fn fparseln .
+In addition
+.Fn fparseln
+may set
+.Va errno
+to
+.Bq Er ENOMEM
+and return
+.Dv NULL
+if it runs out of memory.
+.Sh SEE ALSO
+.Xr fgetln 3
+.Sh HISTORY
+The
+.Fn fparseln
+function first appeared in
+.Nx 1.4 .
diff --git a/src/Makefile.am b/src/Makefile.am
index f2ef81d..2146438 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,7 @@ libbsd_la_SOURCES = \
 	fgetln.c \
 	flopen.c \
 	fmtcheck.c \
+	fparseln.c \
 	fpurge.c \
 	getpeereid.c \
 	hash/md5.c \
diff --git a/src/fparseln.c b/src/fparseln.c
new file mode 100644
index 0000000..0796b66
--- /dev/null
+++ b/src/fparseln.c
@@ -0,0 +1,230 @@
+/*	$NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $	*/
+
+/*
+ * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define FLOCKFILE(fp)
+#define FUNLOCKFILE(fp)
+#define _DIAGASSERT(t)
+
+static int isescaped(const char *, const char *, int);
+
+/* isescaped():
+ *	Return true if the character in *p that belongs to a string
+ *	that starts in *sp, is escaped by the escape character esc.
+ */
+static int
+isescaped(const char *sp, const char *p, int esc)
+{
+	const char     *cp;
+	size_t		ne;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(p != NULL);
+
+	/* No escape character */
+	if (esc == '\0')
+		return 0;
+
+	/* Count the number of escape characters that precede ours */
+	for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
+		continue;
+
+	/* Return true if odd number of escape characters */
+	return (ne & 1) != 0;
+}
+
+
+/* fparseln():
+ *	Read a line from a file parsing continuations ending in \
+ *	and eliminating trailing newlines, or comments starting with
+ *	the comment char.
+ */
+char *
+fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
+{
+	static const char dstr[3] = { '\\', '\\', '#' };
+
+	size_t	s, len;
+	char   *buf;
+	char   *ptr, *cp;
+	int	cnt;
+	char	esc, con, nl, com;
+
+	_DIAGASSERT(fp != NULL);
+
+	len = 0;
+	buf = NULL;
+	cnt = 1;
+
+	if (str == NULL)
+		str = dstr;
+
+	esc = str[0];
+	con = str[1];
+	com = str[2];
+	/*
+	 * XXX: it would be cool to be able to specify the newline character,
+	 * but unfortunately, fgetln does not let us
+	 */
+	nl  = '\n';
+
+	FLOCKFILE(fp);
+
+	while (cnt) {
+		cnt = 0;
+
+		if (lineno)
+			(*lineno)++;
+
+		if ((ptr = fgetln(fp, &s)) == NULL)
+			break;
+
+		if (s && com) {		/* Check and eliminate comments */
+			for (cp = ptr; cp < ptr + s; cp++)
+				if (*cp == com && !isescaped(ptr, cp, esc)) {
+					s = cp - ptr;
+					cnt = s == 0 && buf == NULL;
+					break;
+				}
+		}
+
+		if (s && nl) { 		/* Check and eliminate newlines */
+			cp = &ptr[s - 1];
+
+			if (*cp == nl)
+				s--;	/* forget newline */
+		}
+
+		if (s && con) {		/* Check and eliminate continuations */
+			cp = &ptr[s - 1];
+
+			if (*cp == con && !isescaped(ptr, cp, esc)) {
+				s--;	/* forget continuation char */
+				cnt = 1;
+			}
+		}
+
+		if (s == 0) {
+			/*
+			 * nothing to add, skip realloc except in case
+			 * we need a minimal buf to return an empty line
+			 */
+			if (cnt || buf != NULL)
+				continue;
+		}
+
+		if ((cp = realloc(buf, len + s + 1)) == NULL) {
+			FUNLOCKFILE(fp);
+			free(buf);
+			return NULL;
+		}
+		buf = cp;
+
+		(void) memcpy(buf + len, ptr, s);
+		len += s;
+		buf[len] = '\0';
+	}
+
+	FUNLOCKFILE(fp);
+
+	if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
+	    strchr(buf, esc) != NULL) {
+		ptr = cp = buf;
+		while (cp[0] != '\0') {
+			int skipesc;
+
+			while (cp[0] != '\0' && cp[0] != esc)
+				*ptr++ = *cp++;
+			if (cp[0] == '\0' || cp[1] == '\0')
+				break;
+
+			skipesc = 0;
+			if (cp[1] == com)
+				skipesc += (flags & FPARSELN_UNESCCOMM);
+			if (cp[1] == con)
+				skipesc += (flags & FPARSELN_UNESCCONT);
+			if (cp[1] == esc)
+				skipesc += (flags & FPARSELN_UNESCESC);
+			if (cp[1] != com && cp[1] != con && cp[1] != esc)
+				skipesc = (flags & FPARSELN_UNESCREST);
+
+			if (skipesc)
+				cp++;
+			else
+				*ptr++ = *cp++;
+			*ptr++ = *cp++;
+		}
+		*ptr = '\0';
+		len = strlen(buf);
+	}
+
+	if (size)
+		*size = len;
+	return buf;
+}
+
+#ifdef TEST
+
+int main(int, char **);
+
+int
+main(int argc, char **argv)
+{
+	char   *ptr;
+	size_t	size, line;
+
+	line = 0;
+	while ((ptr = fparseln(stdin, &size, &line, NULL,
+	    FPARSELN_UNESCALL)) != NULL)
+		printf("line %d (%d) |%s|\n", line, size, ptr);
+	return 0;
+}
+
+/*
+
+# This is a test
+line 1
+line 2 \
+line 3 # Comment
+line 4 \# Not comment \\\\
+
+# And a comment \
+line 5 \\\
+line 6
+
+*/
+
+#endif /* TEST */
diff --git a/src/libbsd.map b/src/libbsd.map
index 2f518d9..488267c 100644
--- a/src/libbsd.map
+++ b/src/libbsd.map
@@ -96,6 +96,8 @@ LIBBSD_0.4 {
 } LIBBSD_0.3;
 
 LIBBSD_0.5 {
+    fparseln;
+
     strnstr;
 
     wcslcat;
commit cb7bc0d85ea9ec5eb8e9c922c2ad0ea7498620e9
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sun Nov 25 22:09:43 2012 +0100

    Add file buffer pool support to fgetln()
    
    This avoids buffer overwrites during concurrent or intermixed calls to
    fgetln() when using more than one different stream (currently 32), which
    the original interface supports natively by using an internal buffer
    from the FILE structure. Although this workaround is rudimentary, it
    should cover most of the theoretically problematic cases.

diff --git a/COPYING b/COPYING
index b84fb6f..5a42e50 100644
--- a/COPYING
+++ b/COPYING
@@ -66,7 +66,7 @@ for man/arc4random.3, man/tree.3 and man/getprogname.3.
 The rest of the licenses apply to code and/or man pages.
 
 
-    Copyright © 2004-2006, 2008-2011 Guillem Jover <guillem at hadrons.org>
+    Copyright © 2004-2006, 2008-2012 Guillem Jover <guillem at hadrons.org>
     Copyright © 2005 Hector Garcia Alvarez
     Copyright © 2005 Aurelien Jarno
     Copyright © 2006 Robert Millan
diff --git a/src/fgetln.c b/src/fgetln.c
index 183e853..6de804b 100644
--- a/src/fgetln.c
+++ b/src/fgetln.c
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2005 Hector Garcia Alvarez
- * Copyright © 2005, 2008, 2009, 2011 Guillem Jover <guillem at hadrons.org>
+ * Copyright © 2005, 2008-2012 Guillem Jover <guillem at hadrons.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,21 +31,41 @@
 #include <string.h>
 
 #ifdef HAVE_GETLINE
+struct filebuf {
+	FILE *fp;
+	char *buf;
+	size_t len;
+};
+
+#define FILEBUF_POOL_ITEMS 32
+
+static struct filebuf fb_pool[FILEBUF_POOL_ITEMS];
+static int fb_pool_cur;
+
 char *
 fgetln(FILE *stream, size_t *len)
 {
-	static char *line = NULL;
-	static size_t line_len = 0;
+	struct filebuf *fb;
 	ssize_t nread;
 
-	nread = getline(&line, &line_len, stream);
+	/* Try to diminish the possibility of several fgetln() calls being
+	 * used on different streams, by using a pool of buffers per file. */
+	fb = &fb_pool[fb_pool_cur];
+	if (fb->fp != stream && fb->fp != NULL) {
+		fb_pool_cur++;
+		fb_pool_cur %= FILEBUF_POOL_ITEMS;
+		fb = &fb_pool[fb_pool_cur];
+	}
+	fb->fp = stream;
+
+	nread = getline(&fb->buf, &fb->len, stream);
 	/* Note: the getdelim/getline API ensures nread != 0. */
 	if (nread == -1) {
 		*len = 0;
 		return NULL;
 	} else {
 		*len = (size_t)nread;
-		return line;
+		return fb->buf;
 	}
 }
 #else
commit 1be0bdb2c98be6ce1126fd2b400060198c78a8e3
Author: Guillem Jover <guillem at hadrons.org>
Date:   Sun Nov 25 21:13:38 2012 +0100

    Add new strnstr() function
    
    Taken from FreeBSD.

diff --git a/COPYING b/COPYING
index f47f5fc..b84fb6f 100644
--- a/COPYING
+++ b/COPYING
@@ -97,6 +97,7 @@ The rest of the licenses apply to code and/or man pages.
 
     Copyright © 1980, 1982, 1986, 1989-1994
 	The Regents of the University of California.  All rights reserved.
+    Copyright © 2001 Mike Barcroft <mike at FreeBSD.org>
 
     Some code is derived from software contributed to Berkeley by
     the American National Standards Committee X3, on Information
@@ -114,6 +115,9 @@ The rest of the licenses apply to code and/or man pages.
     Some code is derived from software contributed to Berkeley by
     Paul Vixie.
 
+    Some code is derived from software contributed to Berkeley by
+    Chris Torek.
+
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
diff --git a/include/bsd/string.h b/include/bsd/string.h
index f385947..a2d54b3 100644
--- a/include/bsd/string.h
+++ b/include/bsd/string.h
@@ -39,6 +39,7 @@
 __BEGIN_DECLS
 size_t strlcpy(char *dst, const char *src, size_t siz);
 size_t strlcat(char *dst, const char *src, size_t siz);
+char *strnstr(const char *str, const char *find, size_t str_len);
 void strmode(mode_t mode, char *str);
 __END_DECLS
 
diff --git a/man/Makefile.am b/man/Makefile.am
index 17bf46f..d43ce85 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -45,6 +45,7 @@ dist_man_MANS = \
 	sradixsort.3 \
 	strlcat.3 \
 	strlcpy.3 \
+	strnstr.3 \
 	strmode.3 \
 	strtonum.3 \
 	tree.3 \
diff --git a/man/strnstr.3 b/man/strnstr.3
new file mode 100644
index 0000000..28bb0f8
--- /dev/null
+++ b/man/strnstr.3
@@ -0,0 +1,110 @@
+.\" Copyright (c) 2001 Mike Barcroft <mike at FreeBSD.org>
+.\" Copyright (c) 1990, 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)strstr.3	8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 11, 2001
+.Dt STRSTR 3
+.Os
+.Sh NAME
+.Nm strnstr
+.Nd locate a substring in a string
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.Lb libbsd
+.Sh SYNOPSIS
+.In bsd/string.h
+.Ft char *
+.Fn strnstr "const char *big" "const char *little" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn strnstr
+function
+locates the first occurrence of the null-terminated string
+.Fa little
+in the string
+.Fa big ,
+where not more than
+.Fa len
+characters are searched.
+Characters that appear after a
+.Ql \e0
+character are not searched.
+Since the
+.Fn strnstr
+function is a
+.Fx
+specific API, it should only be used when portability is not a concern.
+.Sh RETURN VALUES
+If
+.Fa little
+is an empty string,
+.Fa big
+is returned;
+if
+.Fa little
+occurs nowhere in
+.Fa big ,
+.Dv NULL
+is returned;
+otherwise a pointer to the first character of the first occurrence of
+.Fa little
+is returned.
+.Sh EXAMPLES
+The following sets the pointer
+.Va ptr
+to
+.Dv NULL ,
+because only the first 4 characters of
+.Va largestring
+are searched:
+.Bd -literal -offset indent
+const char *largestring = "Foo Bar Baz";
+const char *smallstring = "Bar";
+char *ptr;
+
+ptr = strnstr(largestring, smallstring, 4);
+.Ed
+.Sh SEE ALSO
+.Xr strstr 3 ,
+.Xr strcasestr 3 ,
+.Xr memchr 3 ,
+.Xr memmem 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strtok 3 ,
+.Xr wcsstr 3
diff --git a/src/Makefile.am b/src/Makefile.am
index df159de..f2ef81d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -65,6 +65,7 @@ libbsd_la_SOURCES = \
 	strlcat.c \
 	strlcpy.c \
 	strmode.c \
+	strnstr.c \
 	strtonum.c \
 	unvis.c \
 	vis.c \
diff --git a/src/libbsd.map b/src/libbsd.map
index 034d2e8..2f518d9 100644
--- a/src/libbsd.map
+++ b/src/libbsd.map
@@ -96,6 +96,8 @@ LIBBSD_0.4 {
 } LIBBSD_0.3;
 
 LIBBSD_0.5 {
+    strnstr;
+
     wcslcat;
     wcslcpy;
 } LIBBSD_0.4;
diff --git a/src/strnstr.c b/src/strnstr.c
new file mode 100644
index 0000000..4de757d
--- /dev/null
+++ b/src/strnstr.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike at FreeBSD.org>
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s, where the search is limited to the
+ * first slen characters of s.
+ */
+char *
+strnstr(const char *s, const char *find, size_t slen)
+{
+	char c, sc;
+	size_t len;
+
+	if ((c = *find++) != '\0') {
+		len = strlen(find);
+		do {
+			do {
+				if (slen-- < 1 || (sc = *s++) == '\0')
+					return (NULL);
+			} while (sc != c);
+			if (len > slen)
+				return (NULL);
+		} while (strncmp(s, find, len) != 0);
+		s--;
+	}
+	return ((char *)s);
+}
commit ff0d700df095a4eb2091ccf197d213e43a89edd4
Author: Guillem Jover <guillem at hadrons.org>
Date:   Fri Nov 23 17:16:43 2012 +0100

    Add new wcslcat() and wcslcpy() functions
    
    Taken from FreeBSD.

diff --git a/include/Makefile.am b/include/Makefile.am
index 2141570..9b8e4c3 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -21,4 +21,5 @@ nobase_include_HEADERS = \
 	bsd/string.h \
 	bsd/unistd.h \
 	bsd/vis.h \
+	bsd/wchar.h \
 	$(nil)
diff --git a/include/bsd/wchar.h b/include/bsd/wchar.h
new file mode 100644
index 0000000..9b16f53
--- /dev/null
+++ b/include/bsd/wchar.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2012 Guillem Jover <guillem at hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef LIBBSD_OVERLAY
+#include_next <wchar.h>
+#else
+#include <wchar.h>
+#endif
+
+#ifndef LIBBSD_WCHAR_H
+#define LIBBSD_WCHAR_H
+
+#include <stddef.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
+size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
+__END_DECLS
+
+#endif
diff --git a/man/Makefile.am b/man/Makefile.am
index 16d3cb0..17bf46f 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -50,4 +50,6 @@ dist_man_MANS = \
 	tree.3 \
 	unvis.3 \
 	vis.3 \
+	wcslcat.3 \
+	wcslcpy.3 \
 	$(nil)
diff --git a/man/wcslcat.3 b/man/wcslcat.3
new file mode 100644
index 0000000..15cde50
--- /dev/null
+++ b/man/wcslcat.3
@@ -0,0 +1 @@
+.so man3/wcslcpy.3
diff --git a/man/wcslcpy.3 b/man/wcslcpy.3
new file mode 100644
index 0000000..64cbe73
--- /dev/null
+++ b/man/wcslcpy.3
@@ -0,0 +1,67 @@
+.\"	$NetBSD: wmemchr.3,v 1.4 2001/01/02 11:26:23 itojun Exp $
+.\"
+.\" Copyright (c) 1990, 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     from: @(#)strcpy.3	8.1 (Berkeley) 6/4/93
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 4, 2009
+.Dt WCSLCPY 3
+.Os
+.Sh NAME
+.Nm wcslcat ,
+.Nm wcslcpy ,
+.Nd wide character string manipulation operations
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.Lb libbsd
+.Sh SYNOPSIS
+.In bsd/wchar.h
+.Ft size_t
+.Fn wcslcat "wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft size_t
+.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Sh DESCRIPTION
+The functions implement string manipulation operations over wide character
+strings.
+For a detailed description, refer to documents for the respective single-byte
+counterpart, such as
+.Xr strlcpy 3 .
+.Sh SEE ALSO
+.Xr strlcat 3 ,
+.Xr strlcpy 3 ,
+.Sh STANDARDS
+.Fn wcslcat
+and
+.Fn wcslcpy ,
+which are BSD extensions.
diff --git a/src/Makefile.am b/src/Makefile.am
index 8b2b91a..df159de 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,6 +68,8 @@ libbsd_la_SOURCES = \
 	strtonum.c \
 	unvis.c \
 	vis.c \
+	wcslcat.c \
+	wcslcpy.c \
 	$(nil)
 
 runtimelibdir = $(libdir)
diff --git a/src/libbsd.map b/src/libbsd.map
index 5c4b174..034d2e8 100644
--- a/src/libbsd.map
+++ b/src/libbsd.map
@@ -94,3 +94,8 @@ LIBBSD_0.4 {
     closefrom;
     expand_number;
 } LIBBSD_0.3;
+
+LIBBSD_0.5 {
+    wcslcat;
+    wcslcpy;
+} LIBBSD_0.4;
diff --git a/src/wcslcat.c b/src/wcslcat.c
new file mode 100644
index 0000000..f5f1e1e
--- /dev/null
+++ b/src/wcslcat.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	from OpenBSD: strlcat.c,v 1.3 2000/11/24 11:10:02 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Appends src to string dst of size siz (unlike wcsncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns wcslen(initial dst) + wcslen(src); if retval >= siz,
+ * truncation occurred.
+ */
+size_t
+wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
+{
+	wchar_t *d = dst;
+	const wchar_t *s = src;
+	size_t n = siz;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (*d != '\0' && n-- != 0)
+		d++;
+	dlen = d - dst;
+	n = siz - dlen;
+
+	if (n == 0)
+		return(dlen + wcslen(s));
+	while (*s != '\0') {
+		if (n != 1) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return(dlen + (s - src));	/* count does not include NUL */
+}
diff --git a/src/wcslcpy.c b/src/wcslcpy.c
new file mode 100644
index 0000000..b104a06
--- /dev/null
+++ b/src/wcslcpy.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns wcslen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
+{
+	wchar_t *d = dst;
+	const wchar_t *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
commit 386276487229a5ee0635130e4886f1d89b1c31d0
Author: Guillem Jover <guillem at hadrons.org>
Date:   Tue May 21 04:13:55 2013 +0200

    Coalesce identical BSD-2-clause licenses

diff --git a/COPYING b/COPYING
index 1a4fdce..f47f5fc 100644
--- a/COPYING
+++ b/COPYING
@@ -233,60 +233,27 @@ The rest of the licenses apply to code and/or man pages.
 
     --
 
-    Copyright (c) 2009 Advanced Computing Technologies LLC
-    Written by: John H. Baldwin <jhb at FreeBSD.org>
+    Copyright © 1998, M. Warner Losh <imp at freebsd.org>
     All rights reserved.
 
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-    SUCH DAMAGE.
-
-    --
+    Copyright © 2001 Dima Dorfman.
+    All rights reserved.
 
-    Copyright © 1998, M. Warner Losh <imp at freebsd.org>
+    Copyright © 2002 Thomas Moestl <tmm at FreeBSD.org>
     All rights reserved.
 
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
+    Copyright © 2005 Pawel Jakub Dawidek <pjd at FreeBSD.org>
+    All rights reserved.
 
-    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-    SUCH DAMAGE.
+    Copyright © 2007 Eric Anderson <anderson at FreeBSD.org>
+    Copyright © 2007 Pawel Jakub Dawidek <pjd at FreeBSD.org>
+    All rights reserved.
 
-    --
+    Copyright © 2007 Dag-Erling Coïdan Smørgrav
+    All rights reserved.
 
-    Copyright © 2001 Dima Dorfman.
+    Copyright © 2009 Advanced Computing Technologies LLC
+    Written by: John H. Baldwin <jhb at FreeBSD.org>
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -337,110 +304,6 @@ The rest of the licenses apply to code and/or man pages.
 
     --
 
-    Copyright © 2002 Thomas Moestl <tmm at FreeBSD.org>
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-    SUCH DAMAGE.
-
-    --
-
-    Copyright © 2005 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-    SUCH DAMAGE.
-
-    --
-
-    Copyright © 2007 Eric Anderson <anderson at FreeBSD.org>
-    Copyright © 2007 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-    SUCH DAMAGE.
-
-    --
-
-    Copyright © 2007 Dag-Erling Coïdan Smørgrav
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-
-    --
-
     Copyright © 2007 Dag-Erling Coïdan Smørgrav
     All rights reserved.
 


More information about the libbsd mailing list