/* Did we already (try to) parse the environment and setup the necessary
* variables? */
static int initialized;
+/* Force hooked writes even when not writing to a tty. Used for tests. */
+static int force_write_to_non_tty;
#include "constants.h"
/* Should the "action" handler be invoked for this file descriptor? */
static int check_handle_fd(int fd) {
- /* Never touch anything not going to a terminal. */
- if (!isatty(fd)) {
- return 0;
- }
-
/* Load state from environment. Only necessary once per process. */
if (!initialized) {
init_from_environment();
}
+ /* Never touch anything not going to a terminal - unless we are explicitly
+ * asked to do so. */
+ if (!force_write_to_non_tty && !isatty(fd)) {
+ return 0;
+ }
+
if (tracked_fds_count == 0) {
return 0;
}
HOOK_FILE1(int, puts_unlocked, stdout,
const char *, s)
+/* perror(3) */
+HOOK_VOID1(void, perror, STDERR_FILENO,
+ const char *, s)
+
/* Hook functions which duplicate file descriptors to track them. */
close_fd(fileno(fp));
return real_fclose(fp);
}
+
+
+/* Hook functions which are necessary for correct tracking. */
+
+pid_t vfork(void) {
+ /* vfork() is similar to fork() but the address space is shared between
+ * father and child. It's designed for fork()/exec() usage because it's
+ * faster than fork(). However according to the POSIX standard the "child"
+ * isn't allowed to perform any memory-modifications before the exec()
+ * (except the pid_t result variable of vfork()).
+ *
+ * As some programs don't adhere to the standard (e.g. the "child" closes
+ * or dups a descriptor before the exec()) and this breaks our tracking of
+ * file descriptors (e.g. it gets closed in the parent as well), we just
+ * fork() instead. This is in compliance with the POSIX standard and as
+ * most systems use copy-on-write anyway not a performance issue. */
+ return fork();
+}