X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=src%2Fcoloredstderr.c;h=63c4a61411b308855046b7c207e7173fda08da82;hb=d475e5ec892390e3f43c5fb4cb373cedc33211fd;hp=3e5dac2c770ca1f44481529911effab60a7b092c;hpb=7d4d8e0784059412a7ab3dfdfe3ad011b894a6e4;p=coloredstderr%2Fcoloredstderr.git diff --git a/src/coloredstderr.c b/src/coloredstderr.c index 3e5dac2..63c4a61 100644 --- a/src/coloredstderr.c +++ b/src/coloredstderr.c @@ -42,6 +42,8 @@ static size_t (*real_fwrite)(const void *, size_t, size_t, FILE *); /* 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" @@ -56,16 +58,17 @@ static int initialized; /* 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; } @@ -74,7 +77,7 @@ static int check_handle_fd(int fd) { static void dup_fd(int oldfd, int newfd) { #ifdef DEBUG - debug("%d -> %d\t\t\t[%d]\n", oldfd, newfd, getpid()); + debug("%3d -> %3d\t\t\t[%d]\n", oldfd, newfd, getpid()); #endif if (!initialized) { @@ -102,7 +105,7 @@ static void dup_fd(int oldfd, int newfd) { static void close_fd(int fd) { #ifdef DEBUG - debug("%d -> .\t\t\t[%d]\n", fd, getpid()); + debug("%3d -> .\t\t\t[%d]\n", fd, getpid()); #endif if (!initialized) { @@ -227,6 +230,10 @@ HOOK_FILE1(int, putchar_unlocked, stdout, 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. */ @@ -319,3 +326,23 @@ int fclose(FILE *fp) { close_fd(fileno(fp)); return real_fclose(fp); } + + +/* Hook functions which are necessary for correct tracking. */ + +#if defined(HAVE_VFORK) && defined(HAVE_FORK) +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(); +} +#endif