 .gitignore                                         |    3 +
 README                                             |    3 +
 doc/guide.rst                                      |   15 +++---
 libfiu/Makefile                                    |   50 +++++++++++++-------
 libfiu/fiu-control.h                               |   14 ++++++
 libfiu/fiu-rc.c                                    |   20 ++++----
 libfiu/fiu.c                                       |    8 ++--
 libfiu/fiu.h                                       |    9 ++++
 libfiu/{libfiu.skel.pc => libfiu.pc.in}            |    2 +-
 preload/posix/Makefile                             |   37 +++++++++++----
 preload/posix/codegen.c                            |   10 +++-
 preload/posix/codegen.h                            |   13 +++++-
 .../posix/{function_list.skel => function_list.in} |    0
 preload/posix/generate                             |   17 +++++--
 preload/posix/modules/libc.mm.custom.c             |    2 +-
 preload/posix/modules/posix.custom.c               |    2 +-
 preload/posix/modules/posix.io.mod                 |   20 ++++++++
 preload/posix/utils/extract_from_man               |    4 +-
 preload/run/Makefile                               |   42 ++++++++++++-----
 preload/run/fiu-run.in                             |   10 +++-
 preload/run/run.c                                  |   11 ++--
 utils/Makefile                                     |   13 ++++--
 utils/fiu-ctrl                                     |   11 ++--
 utils/fiu-ls                                       |   48 +++++++++++++++++++
 utils/fiu-ls.1                                     |   31 ++++++++++++
 25 files changed, 305 insertions(+), 90 deletions(-)

diff --git a/.gitignore b/.gitignore
index 68ac8d0..1011ae1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,8 +5,10 @@ libfiu/*.o
 libfiu/libfiu.a
 libfiu/libfiu.pc
 libfiu/libfiu.so
+libfiu/build-flags
 preload/posix/*.o
 preload/posix/*.so
+preload/posix/build-flags
 preload/posix/function_list
 preload/posix/modules/*.o
 preload/posix/modules/*.mod.c
@@ -14,4 +16,5 @@ preload/posix/modules/*.mod.fl
 preload/run/*.o
 preload/run/*.so
 preload/run/fiu-run
+preload/run/build-flags
 
diff --git a/README b/README
index 312e4ed..7dc7bd4 100644
--- a/README
+++ b/README
@@ -35,6 +35,9 @@ To build the Python bindings, use "make python2"; to install them you can run
 "make python3_install".
 
 
+Solaris users must use "gmake INSTALL=ginstall" instead of "make".
+
+
 Where to report bugs
 --------------------
 
diff --git a/doc/guide.rst b/doc/guide.rst
index cf2ff3f..e4ef6fc 100644
--- a/doc/guide.rst
+++ b/doc/guide.rst
@@ -79,10 +79,9 @@ failure. As the point of failure is enabled, *free_space()* will return 0, so
 you can test how your code behaves under that condition, which was otherwise
 hard to trigger.
 
-As you can see, libfiu's API has to "sides": a core API and a control API. The
-core API is used inside the code wanting to perform fault injection on. The
-control API is used inside the testing code, in order to control the injection
-of failures.
+As you can see, libfiu's API has two "sides": a core API and a control API.
+The core API is used inside the code to be fault injected. The control API is
+used inside the testing code, in order to control the injection of failures.
 
 In the example above, *fiu_return_on()* is a part of the core API, and
 *fiu_enable()* is a part of the control API.
@@ -122,9 +121,9 @@ First, you should ``#include "fiu-local.h"`` in the files you want to add
 points of failure to. That header allows you to avoid libfiu as a build-time
 dependency, as mentioned in the last section.
 
-Then, you to insert points of failure, you sprinkle your code with calls like
+Then, to insert points of failure, you sprinkle your code with calls like
 ``fiu_return_on("name", -1)``, ``fiu_exit_on("name")``, or more complex code
-using ``fiu_fail("name")``. Consult the libfiu's manpage for the details on
+using ``fiu_fail("name")``. See the libfiu's manpage for the details on
 the API.
 
 It is recommended that you use meaningful names for your points of failure, to
@@ -165,7 +164,7 @@ of failure that begin with the given name (excluding the asterisk, of course).
 
 Check libfiu's manpage for more details about the API.
 
-Using the Python bindings, you can also write and/or control your tests using
-Python.
+If you prefer to avoid writing the test code in C, you can use the Python
+bindings, and/or the *fiu-run* and *fiu-ctrl* utilities.
 
 
diff --git a/libfiu/Makefile b/libfiu/Makefile
index 425056c..e312976 100644
--- a/libfiu/Makefile
+++ b/libfiu/Makefile
@@ -1,6 +1,6 @@
 
 CFLAGS += -std=c99 -pedantic -Wall -O3
-ALL_CFLAGS = -D_XOPEN_SOURCE=500 -fPIC -DFIU_ENABLE=1 $(CFLAGS)
+ALL_CFLAGS = -D_XOPEN_SOURCE=600 -fPIC -DFIU_ENABLE=1 $(CFLAGS)
 
 ifdef DEBUG
 ALL_CFLAGS += -g
@@ -14,6 +14,9 @@ endif
 # prefix for installing the binaries
 PREFIX=/usr/local
 
+# install utility, we assume it's GNU/BSD compatible
+INSTALL=install
+
 
 OBJS = fiu.o fiu-rc.o
 
@@ -29,49 +32,60 @@ default: all
 
 all: libs libfiu.pc
 
-libfiu.pc: libfiu.skel.pc
+libfiu.pc: build-flags libfiu.pc.in
 	@echo "generating libfiu.pc"
-	@cat libfiu.skel.pc | \
+	@cat libfiu.pc.in | \
 		sed 's@++PREFIX++@$(PREFIX)@g' \
 		> libfiu.pc
 
 libs: libfiu.so libfiu.a
 
-libfiu.so: fiu.h $(OBJS)
+libfiu.so: build-flags fiu.h $(OBJS)
 	$(NICE_CC) $(ALL_CFLAGS) -shared -fPIC $(OBJS) -lpthread -o libfiu.so
 
-libfiu.a: fiu.h $(OBJS)
+libfiu.a: build-flags fiu.h $(OBJS)
 	$(AR) cr libfiu.a $(OBJS)
 
 
 install-lib: libs libfiu.pc
-	install -d $(PREFIX)/lib
-	install -m 0755 libfiu.so $(PREFIX)/lib
-	install -m 0755 libfiu.a $(PREFIX)/lib
-	install -d $(PREFIX)/include
-	install -m 0644 fiu.h $(PREFIX)/include
-	install -m 0644 fiu-control.h $(PREFIX)/include
-	install -m 0644 fiu-local.h $(PREFIX)/include
-	install -d $(PREFIX)/lib/pkgconfig
-	install -m 644 libfiu.pc $(PREFIX)/lib/pkgconfig
+	$(INSTALL) -d $(PREFIX)/lib
+	$(INSTALL) -m 0755 libfiu.so $(PREFIX)/lib
+	$(INSTALL) -m 0755 libfiu.a $(PREFIX)/lib
+	$(INSTALL) -d $(PREFIX)/include
+	$(INSTALL) -m 0644 fiu.h $(PREFIX)/include
+	$(INSTALL) -m 0644 fiu-control.h $(PREFIX)/include
+	$(INSTALL) -m 0644 fiu-local.h $(PREFIX)/include
+	$(INSTALL) -d $(PREFIX)/lib/pkgconfig
+	$(INSTALL) -m 644 libfiu.pc $(PREFIX)/lib/pkgconfig
 	@echo
 	@echo "Please run ldconfig to update your library cache"
 	@echo
 
 install-man:
-	install -d $(PREFIX)/man/man3
-	install -m 0644 libfiu.3 $(PREFIX)/man/man3/
+	$(INSTALL) -d $(PREFIX)/man/man3
+	$(INSTALL) -m 0644 libfiu.3 $(PREFIX)/man/man3/
 
 install: install-lib install-man
 
+BF = $(ALL_CFLAGS) ~ $(PREFIX)
+build-flags: .force-build-flags
+	@if [ x"$(BF)" != x"`cat build-flags 2>/dev/null`" ]; then \
+		if [ -f build-flags ]; then \
+			echo "build flags changed, rebuilding"; \
+		fi; \
+		echo "$(BF)" > build-flags; \
+	fi
+
+$(OBJS): build-flags
 
 .c.o:
 	$(NICE_CC) $(ALL_CFLAGS) -c $< -o $@
 
 clean:
-	rm -f libfiu.pc $(OBJS) libfiu.so libfiu.a
+	rm -f libfiu.pc $(OBJS) libfiu.so libfiu.a build-flags
 	rm -f *.bb *.bbg *.da *.gcov *.gcda *.gcno gmon.out
 
-.PHONY: default all libs install-lib install-man install clean
+.PHONY: default all libs install-lib install-man install clean \
+	.force-build-flags
 
 
diff --git a/libfiu/fiu-control.h b/libfiu/fiu-control.h
index c1859ee..30ed4f1 100644
--- a/libfiu/fiu-control.h
+++ b/libfiu/fiu-control.h
@@ -1,4 +1,11 @@
 
+#ifndef _FIU_CONTROL_H
+#define _FIU_CONTROL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Control API for libfiu
  */
@@ -66,3 +73,10 @@ int fiu_disable(const char *name);
  * - returns: 0 on success, -1 on errors. */
 int fiu_rc_fifo(const char *basename);
 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _FIU_CONTROL_H
+
diff --git a/libfiu/fiu-rc.c b/libfiu/fiu-rc.c
index 83dcb83..92ef78c 100644
--- a/libfiu/fiu-rc.c
+++ b/libfiu/fiu-rc.c
@@ -6,11 +6,11 @@
 #include <stdio.h>		/* snprintf() */
 #include <string.h>		/* strncpy() */
 #include <stdlib.h>		/* malloc()/free() */
-#include <sys/param.h>		/* PATH_MAX */
-#include <sys/types.h>		/* getpid(), mknod() */
-#include <unistd.h>		/* getpid(), mknod() */
-#include <sys/stat.h>		/* mknod() */
-#include <fcntl.h>		/* mknod() */
+#include <limits.h>		/* PATH_MAX */
+#include <sys/types.h>		/* getpid(), mkfifo() */
+#include <unistd.h>		/* getpid() */
+#include <sys/stat.h>		/* mkfifo() */
+#include <fcntl.h>		/* open() and friends */
 #include <pthread.h>		/* pthread_create() and friends */
 #include <errno.h>		/* errno and friends */
 
@@ -116,7 +116,7 @@ static int rc_process_cmd(char *cmd)
 			tok = strtok_r(NULL, " ", &state);
 			if (tok == NULL)
 				return -1;
-			probability = strtof(tok, NULL);
+			probability = strtod(tok, NULL);
 			if (probability < 0 || probability > 1)
 				return -1;
 		}
@@ -232,15 +232,15 @@ static int _fiu_rc_fifo(const char *basename)
 	/* see rc_fifo_thread() */
 	rec_count++;
 
-	snprintf(npipe_path_in, PATH_MAX,"%s-%d.in", basename, getpid());
-	snprintf(npipe_path_out, PATH_MAX,"%s-%d.out", basename, getpid());
+	snprintf(npipe_path_in, PATH_MAX, "%s-%d.in", basename, getpid());
+	snprintf(npipe_path_out, PATH_MAX, "%s-%d.out", basename, getpid());
 
-	if (mknod(npipe_path_in, S_IFIFO | 0600, 0) != 0) {
+	if (mkfifo(npipe_path_in, 0600) != 0) {
 		rec_count--;
 		return -1;
 	}
 
-	if (mknod(npipe_path_out, S_IFIFO | 0600, 0) != 0) {
+	if (mkfifo(npipe_path_out, 0600) != 0) {
 		unlink(npipe_path_in);
 		rec_count--;
 		return -1;
diff --git a/libfiu/fiu.c b/libfiu/fiu.c
index f0c344b..2a01c91 100644
--- a/libfiu/fiu.c
+++ b/libfiu/fiu.c
@@ -88,9 +88,6 @@ __thread int rec_count = 0;
 /* Used to keep the last failinfo via TLS */
 static pthread_key_t last_failinfo_key;
 
-/* Used to avoid re-initialization, protected by enabled_fails_lock */
-static int initialized = 0;
-
 
 /*
  * Miscelaneous internal functions
@@ -219,6 +216,9 @@ static void atfork_child(void)
  * time without clashes. */
 int fiu_init(unsigned int flags)
 {
+	/* Used to avoid re-initialization, protected by enabled_fails_lock */
+	static int initialized = 0;
+
 	rec_count++;
 	ef_wlock();
 	if (initialized) {
@@ -396,7 +396,7 @@ static int insert_new_fail(const char *name, int failnum, void *failinfo,
 
 	/* There are no free slots in enabled_fails, so we must grow it */
 	enabled_fails = realloc(enabled_fails,
-			enabled_fails_len + EF_GROW * sizeof(struct pf_info));
+			(enabled_fails_len + EF_GROW) * sizeof(struct pf_info));
 	if (enabled_fails == NULL) {
 		enabled_fails_last = NULL;
 		enabled_fails_len = 0;
diff --git a/libfiu/fiu.h b/libfiu/fiu.h
index 645c456..ea35cd6 100644
--- a/libfiu/fiu.h
+++ b/libfiu/fiu.h
@@ -15,6 +15,11 @@
 /* Controls whether the external code enables libfiu or not. */
 #ifdef FIU_ENABLE
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 /* Initializes the library.
  *
  * - flags: unused.
@@ -50,6 +55,10 @@ void *fiu_failinfo(void);
 #define fiu_return_on(name, retval) fiu_do_on(name, return retval)
 
 
+#ifdef __cplusplus
+}
+#endif
+
 #else
 /* fiu not enabled, this should match fiu-local.h but we don't include it
  * because it includes us assuming we're installed system-wide */
diff --git a/libfiu/libfiu.skel.pc b/libfiu/libfiu.pc.in
similarity index 93%
rename from libfiu/libfiu.skel.pc
rename to libfiu/libfiu.pc.in
index ced4173..4f1907d 100644
--- a/libfiu/libfiu.skel.pc
+++ b/libfiu/libfiu.pc.in
@@ -6,7 +6,7 @@ includedir=${prefix}/include
 Name: libfiu
 Description: Fault injection in userspace
 URL: http://blitiri.com.ar/p/libfiu/
-Version: 0.11
+Version: 0.12
 Libs: -L${libdir} -lfiu
 Cflags: -I${includedir}
 
diff --git a/preload/posix/Makefile b/preload/posix/Makefile
index e470e70..ce0be4e 100644
--- a/preload/posix/Makefile
+++ b/preload/posix/Makefile
@@ -1,6 +1,6 @@
 
 CFLAGS += -std=c99 -Wall -O3
-ALL_CFLAGS = -D_XOPEN_SOURCE=500 -fPIC -DFIU_ENABLE=1 \
+ALL_CFLAGS = -D_XOPEN_SOURCE=600 -fPIC -DFIU_ENABLE=1 \
 		-I. -I../../libfiu/ -L../../libfiu/ $(CFLAGS)
 
 ifdef DEBUG
@@ -14,6 +14,10 @@ endif
 # prefix for installing the binaries
 PREFIX=/usr/local
 
+# install utility, we assume it's GNU/BSD compatible
+INSTALL=install
+
+
 MODS = $(wildcard modules/*.mod)
 GEN_C = $(addsuffix .c,$(MODS))
 GEN_OBJS = $(addsuffix .o,$(MODS))
@@ -37,16 +41,31 @@ default: all
 	
 all: fiu_posix_preload.so function_list
 
+BF = $(ALL_CFLAGS) ~ $(PREFIX)
+build-flags: .force-build-flags
+	@if [ x"$(BF)" != x"`cat build-flags 2>/dev/null`" ]; then \
+		if [ -f build-flags ]; then \
+			echo "build flags changed, rebuilding"; \
+		fi; \
+		echo "$(BF)" > build-flags; \
+	fi
+
 $(GEN_OBJS): $(GEN_C)
 
+$(OBJS): build-flags
+
 %.mod.c: %.mod
 	$(NICE_GEN) $< $@ $<.fl
 
 .c.o:
 	$(NICE_CC) $(ALL_CFLAGS) -c $< -o $@
 
-fiu_posix_preload.so: $(OBJS)
-	$(NICE_CC) $(ALL_CFLAGS) -shared -fPIC $(OBJS) -lfiu -ldl \
+# some platforms do not have libdl, we only use it if available
+NEED_LIBDL := $(shell ld -o dlcheck.so -shared -ldl 2>/dev/null && echo -ldl; \
+	rm -f dlcheck.so)
+
+fiu_posix_preload.so: build-flags $(OBJS)
+	$(NICE_CC) $(ALL_CFLAGS) -shared -fPIC $(OBJS) -lfiu $(NEED_LIBDL) \
 		-o fiu_posix_preload.so
 
 # this should only be needed when building the function list and not the
@@ -54,20 +73,20 @@ fiu_posix_preload.so: $(OBJS)
 %.mod.fl: %.mod
 	$(NICE_GEN) $< $<.c $@
 
-function_list: $(GEN_FL) function_list.skel
+function_list: $(GEN_FL) function_list.in
 	@echo "  function_list"
-	$(Q) cp function_list.skel function_list
+	$(Q) cp function_list.in function_list
 	$(Q) for i in $(GEN_FL); do cat $$i >> function_list; done
 
 install: fiu_posix_preload.so
-	install -d $(PREFIX)/lib
-	install -m 0755 fiu_posix_preload.so $(PREFIX)/lib
+	$(INSTALL) -d $(PREFIX)/lib
+	$(INSTALL) -m 0755 fiu_posix_preload.so $(PREFIX)/lib
 
 clean:
-	rm -f $(OBJS) $(GEN_OBJS:.o=.c) $(GEN_FL)
+	rm -f $(OBJS) $(GEN_OBJS:.o=.c) $(GEN_FL) build-flags
 	rm -f function_list fiu_posix_preload.so
 	rm -f *.bb *.bbg *.da *.gcov *.gcda *.gcno gmon.out
 
-.PHONY: default install clean
+.PHONY: default install clean .force-build-flags
 
 
diff --git a/preload/posix/codegen.c b/preload/posix/codegen.c
index e783861..0f078e8 100644
--- a/preload/posix/codegen.c
+++ b/preload/posix/codegen.c
@@ -11,7 +11,13 @@ void *_fiu_libc;
 /* Recursion counter, per-thread */
 int __thread _fiu_called;
 
-static void __attribute__((constructor(200))) _fiu_init(void)
+/* Let the user know if there is no constructor priorities support, just in
+ * case there are bugs when building/running without them */
+#ifdef NO_CONSTRUCTOR_PRIORITIES
+#warning "Building without using constructor priorities"
+#endif
+
+static void constructor_attr(200) _fiu_init(void)
 {
 	_fiu_called = 0;
 
@@ -25,7 +31,7 @@ static void __attribute__((constructor(200))) _fiu_init(void)
 }
 
 /* this runs after all function-specific constructors */
-static void __attribute__((constructor(250))) _fiu_init_final(void)
+static void constructor_attr(250) _fiu_init_final(void)
 {
 	struct timeval tv;
 
diff --git a/preload/posix/codegen.h b/preload/posix/codegen.h
index bcae5d9..04d00ee 100644
--- a/preload/posix/codegen.h
+++ b/preload/posix/codegen.h
@@ -12,6 +12,17 @@ extern void *_fiu_libc;
 /* Recursion counter, per-thread */
 extern int __thread _fiu_called;
 
+/* GCC >= 4.3 supports constructor priorities only on some platforms. Since we
+ * don't rely on them, but use them for clarity purposes, use a macro so
+ * libfiu builds on systems where they're not supported. */
+#if (defined __linux__) && (defined __GNUC__) \
+	&& __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
+  #define constructor_attr(prio) __attribute__((constructor(prio)))
+#else
+  #define NO_CONSTRUCTOR_PRIORITIES 1
+  #define constructor_attr(prio) __attribute__((constructor))
+#endif
+
 /* Useful macros for recursion and debugging */
 #if 1
 	#define rec_inc() do { _fiu_called++; } while(0)
@@ -59,7 +70,7 @@ extern int __thread _fiu_called;
 #define mkwrap_top(RTYPE, NAME, PARAMS, PARAMSN, PARAMST)	\
 	static RTYPE (*_fiu_orig_##NAME) PARAMS = NULL;		\
 								\
-	static void __attribute__((constructor(201))) _fiu_init_##NAME(void) \
+	static void constructor_attr(201) _fiu_init_##NAME(void) \
 	{							\
 		rec_inc();					\
 		_fiu_orig_##NAME = (RTYPE (*) PARAMST)		\
diff --git a/preload/posix/function_list.skel b/preload/posix/function_list.in
similarity index 100%
rename from preload/posix/function_list.skel
rename to preload/posix/function_list.in
diff --git a/preload/posix/generate b/preload/posix/generate
index dc3e6f4..b5a3989 100755
--- a/preload/posix/generate
+++ b/preload/posix/generate
@@ -92,8 +92,8 @@ class Function:
 		f.write('/* Wrapper for %s() */\n' % self.name)
 
 		# extract params names and types
-		paramst = ', '.join(i[0] for i in self.params_info)
-		paramsn = ', '.join(i[1] for i in self.params_info)
+		paramst = ', '.join([i[0] for i in self.params_info])
+		paramsn = ', '.join([i[1] for i in self.params_info])
 
 		f.write('mkwrap_top(%s, %s, (%s), (%s), (%s))\n' % \
 				(self.ret_type, self.name, self.params,
@@ -107,9 +107,7 @@ class Function:
 
 			# We can't put this as a macro parameter, so it has to
 			# be explicit 
-			valid_errnos = '{ ' + ', '.join(self.valid_errnos) \
-				+ ' }'
-			f.write("\tint valid_errnos[] = %s;\n" % valid_errnos)
+			self.write_valid_errnos(f)
 
 			f.write('mkwrap_body_errno("%s", %s, %d)\n' % \
 					(self.fiu_name, self.on_error,
@@ -124,6 +122,15 @@ class Function:
 		f.write('mkwrap_bottom(%s, (%s))\n' % (self.name, paramsn))
 		f.write('\n\n')
 
+	def write_valid_errnos(self, f):
+		"Generates the code for the static list of valid errnos."
+		f.write("\tint valid_errnos[] = {\n")
+		for e in self.valid_errnos:
+			f.write("\t  #ifdef %s\n" % e)
+			f.write("\t\t%s,\n" % e)
+			f.write("\t  #endif\n")
+		f.write("\t};\n");
+
 
 class Include:
 	"Represents an include directive"
diff --git a/preload/posix/modules/libc.mm.custom.c b/preload/posix/modules/libc.mm.custom.c
index 8e0210b..9878ea3 100644
--- a/preload/posix/modules/libc.mm.custom.c
+++ b/preload/posix/modules/libc.mm.custom.c
@@ -34,7 +34,7 @@ static void *fiu_realloc_hook(void *ptr, size_t size, const void *caller);
  * will run after them just to make things tidier (NOT because it is
  * necessary). */
 
-static void __attribute__((constructor(202))) fiu_init_malloc(void)
+static void constructor_attr(202) fiu_init_malloc(void)
 {
 	/* Save original hooks, used in ours to prevent unwanted recursion */
 	old_malloc_hook = __malloc_hook;
diff --git a/preload/posix/modules/posix.custom.c b/preload/posix/modules/posix.custom.c
index e85adee..55329fa 100644
--- a/preload/posix/modules/posix.custom.c
+++ b/preload/posix/modules/posix.custom.c
@@ -18,7 +18,7 @@
  * of arguments */
 static int (*_fiu_orig_open) (const char *pathname, int flags, ...) = NULL;
 
-static void __attribute__((constructor(201))) _fiu_init_open(void)
+static void constructor_attr(201) _fiu_init_open(void)
 {
 	rec_inc();
 	_fiu_orig_open = (int (*) (const char *, int, ...))
diff --git a/preload/posix/modules/posix.io.mod b/preload/posix/modules/posix.io.mod
index 23b99d4..62b918a 100644
--- a/preload/posix/modules/posix.io.mod
+++ b/preload/posix/modules/posix.io.mod
@@ -59,6 +59,16 @@ ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
 	on error: -1
 	valid errnos: EBADFD EFAULT EFBIG EINTR EINVAL EIO ENOSPC
 
+int truncate(const char *path, off_t length);
+	on error: -1
+	valid errnos: EACCES EFAULT EFBIG EINTR EINVAL EIO EISDIR ELOOP \
+		ENAMETOOLONG ENOENT ENOTDIR EPERM EROFS ETXTBSY
+
+int ftruncate(int fd, off_t length);
+	on error: -1
+	valid errnos: EACCES EBADF EFAULT EFBIG EINTR EINVAL EIO EISDIR ELOOP \
+		ENAMETOOLONG ENOENT ENOTDIR EPERM EROFS ETXTBSY
+
 
 fiu name base: posix/io/dir/
 
@@ -83,6 +93,16 @@ int closedir(DIR *dirp);
 	on error: -1
 	valid errnos: EBADF
 
+int unlink(const char *pathname);
+        on error: -1
+	valid errnos: EACCES EBUSY EFAULT EIO EISDIR ELOOP ENAMETOOLONG ENOENT \
+		ENOMEM ENOTDIR EPERM EROFS
+
+int rename(const char *oldpath, const char *newpath);
+	on error: -1
+	valid errnos: EACCES EBUSY EFAULT EINVAL EISDIR ELOOP EMLINK ENAMETOOLONG \
+		ENOENT ENOMEM ENOSPC ENOTDIR ENOTEMPTY EPERM EROFS EXDEV
+
 
 fiu name base: posix/io/stat/
 
diff --git a/preload/posix/utils/extract_from_man b/preload/posix/utils/extract_from_man
index 00b65f0..7e3d1bf 100755
--- a/preload/posix/utils/extract_from_man
+++ b/preload/posix/utils/extract_from_man
@@ -158,7 +158,7 @@ if __name__ == '__main__':
 		print '\ton error:', ' || '.join(on_error)
 
 	if errnos:
-		print '\tvalid errnos:', wrap(' '.join(errnos), 60,
-				indent = 2)
+		print '\tvalid errnos:', wrap(' '.join(sorted(set(errnos))),
+				60, indent = 2)
 
 
diff --git a/preload/run/Makefile b/preload/run/Makefile
index cb11220..4328548 100644
--- a/preload/run/Makefile
+++ b/preload/run/Makefile
@@ -1,6 +1,6 @@
 
 CFLAGS += -std=c99 -Wall -O3
-ALL_CFLAGS = -D_XOPEN_SOURCE=500 -fPIC -DFIU_ENABLE=1 \
+ALL_CFLAGS = -D_XOPEN_SOURCE=600 -fPIC -DFIU_ENABLE=1 \
 		-I. -I../../libfiu/ -L../../libfiu/ $(CFLAGS)
 
 ifdef DEBUG
@@ -14,6 +14,9 @@ endif
 # prefix for installing the binaries
 PREFIX=/usr/local
 
+# install utility, we assume it's GNU/BSD compatible
+INSTALL=install
+
 
 OBJS = run.o
 
@@ -29,29 +32,44 @@ default: all
 	
 all: fiu_run_preload.so fiu-run
 
+BF = $(ALL_CFLAGS) ~ $(PREFIX)
+build-flags: .force-build-flags
+	@if [ x"$(BF)" != x"`cat build-flags 2>/dev/null`" ]; then \
+		if [ -f build-flags ]; then \
+			echo "build flags changed, rebuilding"; \
+		fi; \
+		echo "$(BF)" > build-flags; \
+	fi
+
+$(OBJS): build-flags
+
 .c.o:
 	$(NICE_CC) $(ALL_CFLAGS) -c $< -o $@
 
-fiu_run_preload.so: $(OBJS)
-	$(NICE_CC) $(ALL_CFLAGS) -shared -fPIC $(OBJS) -lfiu -ldl \
+# some platforms do not have libdl, we only use it if available
+NEED_LIBDL := $(shell ld -o dlcheck.so -shared -ldl 2>/dev/null && echo -ldl; \
+	rm -f dlcheck.so)
+
+fiu_run_preload.so: build-flags $(OBJS)
+	$(NICE_CC) $(ALL_CFLAGS) -shared -fPIC $(OBJS) -lfiu $(NEED_LIBDL) \
 		-o fiu_run_preload.so
 
-fiu-run: fiu-run.in
+fiu-run: build-flags fiu-run.in
 	cat fiu-run.in | sed "s+@@PREFIX@@+$(PREFIX)+g" > fiu-run
 	chmod +x fiu-run
 
 install: fiu_run_preload.so fiu-run
-	install -d $(PREFIX)/lib
-	install -m 0755 fiu_run_preload.so $(PREFIX)/lib
-	install -d $(PREFIX)/bin
-	install -m 0755 fiu-run $(PREFIX)/bin
-	install -d $(PREFIX)/man/man1
-	install -m 0644 fiu-run.1 $(PREFIX)/man/man1/
+	$(INSTALL) -d $(PREFIX)/lib
+	$(INSTALL) -m 0755 fiu_run_preload.so $(PREFIX)/lib
+	$(INSTALL) -d $(PREFIX)/bin
+	$(INSTALL) -m 0755 fiu-run $(PREFIX)/bin
+	$(INSTALL) -d $(PREFIX)/man/man1
+	$(INSTALL) -m 0644 fiu-run.1 $(PREFIX)/man/man1/
 
 clean:
-	rm -f $(OBJS) fiu_run_preload.so fiu-run
+	rm -f $(OBJS) fiu_run_preload.so fiu-run build-flags
 	rm -f *.bb *.bbg *.da *.gcov *.gcda *.gcno gmon.out
 
-.PHONY: default install clean
+.PHONY: default install clean .force-build-flags
 
 
diff --git a/preload/run/fiu-run.in b/preload/run/fiu-run.in
index 8b97267..4870097 100644
--- a/preload/run/fiu-run.in
+++ b/preload/run/fiu-run.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 # This script aims to make the use of the fiu_run_preload library a little
 # easier by providing a more friendly user interface, and abstracting the
@@ -17,6 +17,8 @@ ENABLE=""
 # additional preloader libraries to use
 PRELOAD_LIBS=""
 
+# use the POSIX preload library?
+USE_POSIX_PRELOAD=0
 
 HELP_MSG="
 Usage: fiu-run [options] program [arguments]
@@ -92,7 +94,7 @@ while getopts "+e:p:u:i:f:l:xh" opt; do
 		PLIBPATH="$OPTARG"
 		;;
 	x)
-		PRELOAD_LIBS="$PRELOAD_LIBS $PLIBPATH/fiu_posix_preload.so"
+		USE_POSIX_PRELOAD=1
 		;;
 	h|*)
 		echo "$HELP_MSG"
@@ -110,6 +112,10 @@ fi
 # eat the parameters we already processed
 shift $(( $OPTIND - 1 ))
 
+# Allow user to give -l and -x in any order.
+if [ $USE_POSIX_PRELOAD -eq 1 ] ; then
+	PRELOAD_LIBS="$PRELOAD_LIBS $PLIBPATH/fiu_posix_preload.so"
+fi
 
 #
 # Run the application
diff --git a/preload/run/run.c b/preload/run/run.c
index cf0dfa6..8687b32 100644
--- a/preload/run/run.c
+++ b/preload/run/run.c
@@ -71,9 +71,7 @@ static void parse_enable(const char *s, struct enable_option *enopt)
 	enopt->failinfo = atol(tok);
 }
 
-/* We set the constructor with priority 300 so it runs after the other
- * libfiu preloaders (if they're enabled), which use the 200 range */
-static void __attribute__((constructor(300))) fiu_run_init(void)
+static void __attribute__((constructor)) fiu_run_init(void)
 {
 	int r;
 	struct enable_option enopt;
@@ -83,8 +81,11 @@ static void __attribute__((constructor(300))) fiu_run_init(void)
 	fiu_init(0);
 
 	fiu_fifo_env = getenv("FIU_CTRL_FIFO");
-	if (fiu_fifo_env != NULL && *fiu_fifo_env != '\0')
-		fiu_rc_fifo(fiu_fifo_env);
+	if (fiu_fifo_env != NULL && *fiu_fifo_env != '\0') {
+		if (fiu_rc_fifo(fiu_fifo_env) < 0) {
+			perror("fiu_run_preload: Error opening RC fifo");
+		}
+	}
 
 	fiu_enable_env = getenv("FIU_ENABLE");
 	if (fiu_enable_env == NULL)
diff --git a/utils/Makefile b/utils/Makefile
index a0ac66e..3943711 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -2,14 +2,19 @@
 # prefix for installing the binaries
 PREFIX=/usr/local
 
+# install utility, we assume it's GNU/BSD compatible
+INSTALL=install
+
 
 default:
 	
 install:
-	install -d $(PREFIX)/bin
-	install -m 0755 fiu-ctrl $(PREFIX)/bin
-	install -d $(PREFIX)/man/man1
-	install -m 0644 fiu-ctrl.1 $(PREFIX)/man/man1/
+	$(INSTALL) -d $(PREFIX)/bin
+	$(INSTALL) -m 0755 fiu-ctrl $(PREFIX)/bin
+	$(INSTALL) -m 0755 fiu-ls $(PREFIX)/bin
+	$(INSTALL) -d $(PREFIX)/man/man1
+	$(INSTALL) -m 0644 fiu-ctrl.1 $(PREFIX)/man/man1/
+	$(INSTALL) -m 0644 fiu-ls.1 $(PREFIX)/man/man1/
 
 clean:
 
diff --git a/utils/fiu-ctrl b/utils/fiu-ctrl
index d2feeac..a08e06d 100755
--- a/utils/fiu-ctrl
+++ b/utils/fiu-ctrl
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 # This scripts present a friendly interface to the fiu remote control
 # capabilities. Currently, it supports only the named pipe method (the only
@@ -67,9 +67,10 @@ function opts_reset() {
 function add_cmd() {
 	if [ "$NAME" != "" ]; then
 		if [ $PROB -ge 0 ]; then
-			CMDS+="enable_random $NAME $PROB $FAILNUM $FAILINFO"
+			C="enable_random $NAME $PROB $FAILNUM $FAILINFO"
+			CMDS[${#CMDS[*]}]="$C"
 		else
-			CMDS+="enable $NAME $FAILNUM $FAILINFO"
+			CMDS[${#CMDS[*]}]="enable $NAME $FAILNUM $FAILINFO"
 		fi
 		opts_reset;
 	fi
@@ -97,7 +98,7 @@ while getopts "+e:p:u:i:d:f:h" opt; do
 		FIFO_PREFIX="$OPTARG"
 		;;
 	d)
-		CMDS+="disable $OPTARG"
+		CMDS[${#CMDS[*]}]="disable $OPTARG"
 		opts_reset;
 		;;
 	h|*)
@@ -140,7 +141,7 @@ function send_cmd_fifo() {
 	# echoes the reply
 	P=$1
 	shift 1
-	echo $@ > $P.in
+	echo "$@" > $P.in
 	R="`cat $P.out`"
 	if [ "$R" -eq -1 ]; then
 		echo "$P: Command returned error"
diff --git a/utils/fiu-ls b/utils/fiu-ls
new file mode 100755
index 0000000..4ee4dc1
--- /dev/null
+++ b/utils/fiu-ls
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+# Lists processes that can be controlled with fiu-ctrl.
+
+# default remote control over named pipes prefix; we use the same one as
+# fiu-run so it's easier to use
+FIFO_PREFIX="${TMPDIR:-/tmp}/fiu-ctrl"
+
+declare -a PIDS
+
+HELP_MSG="
+Usage: fiu-ls [options]
+
+The following options are supported:
+
+  -f ctrlpath	Set the default prefix for remote control over named pipes.
+		(defaults to \"$FIFO_PREFIX\", which is usually correct if
+		the program was run using fiu-run(1)).
+"
+
+while getopts "f:h" opt; do
+	case $opt in
+	f)
+		FIFO_PREFIX="$OPTARG"
+		;;
+	h|*)
+		echo "$HELP_MSG"
+		exit 1
+		;;
+	esac;
+done
+
+for P in `ls -1 $FIFO_PREFIX-*.in 2>/dev/null` ; do
+	if [ -n "$P" ] ; then
+		OUT="`echo $P | cut -d. -f1`.out"
+		if [ -p "$P" -a -w "$P" -a -p "$OUT" -a -r "$OUT" ] ; then
+			PID="`echo $P | cut -d- -f3 | cut -d. -f1`"
+			if [ -n "$PID" ] && \
+			   kill -0 "$PID" >/dev/null 2>/dev/null ; then
+				PIDS[${#PIDS[*]}]="$PID"
+			fi
+		fi
+	fi
+done
+
+for P in "${PIDS[@]}"; do
+	CMDLINE="`tr '\0' ' ' < /proc/$P/cmdline 2>/dev/null`"
+	printf "%5d: %s\n" "$P" "$CMDLINE"
+done
diff --git a/utils/fiu-ls.1 b/utils/fiu-ls.1
new file mode 100644
index 0000000..c56b569
--- /dev/null
+++ b/utils/fiu-ls.1
@@ -0,0 +1,31 @@
+.TH fiu-ls 1 "7/Jul/2009"
+.SH NAME
+fiu-ls - list processes available for libfiu remote control
+.SH SYNOPSIS
+fiu-ls [options]
+
+.SH DESCRIPTION
+fiu-ls lists process that are available to be controlled using the libfiu
+\fBfiu-ctrl\fR(1) utility. Such processes have the remote control pipes
+available.
+
+For additional documentation, go to the project's website at
+.IR http://blitiri.com.ar/p/libfiu .
+
+.SH OPTIONS
+.TP
+.B "-f ctrlpath"
+Set the default prefix for remote control over named pipes. Defaults to
+"$TMPDIR/fiu-ctrl", or "/tmp/fiu-ctrl" if "$TMPDIR" is not set, which is the
+usually correct for programs launched using \fBfiu-run\fR(1).
+
+.SH SEE ALSO
+.BR libfiu (3),
+.BR fiu-ctrl (1),
+.BR fiu-run (1).
+
+.SH BUGS
+If you want to report bugs, or have any questions or comments, just let me
+know at albertito@blitiri.com.ar. For more information about libfiu, you can
+go to http://blitiri.com.ar/p/libfiu.
+

