]> ruderich.org/simon Gitweb - coloredstderr/coloredstderr.git/blobdiff - src/coloredstderr.c
Fix initialization if ENV_NAME_FDS was not set.
[coloredstderr/coloredstderr.git] / src / coloredstderr.c
index 32b1dd8f106f570535f614c4b410fdcc2f7ffd7e..3e5dac2c770ca1f44481529911effab60a7b092c 100644 (file)
@@ -23,9 +23,6 @@
 /* Must be loaded before the following headers. */
 #include "ldpreload.h"
 
-/* FIXME: use correct declaration for fcntl() */
-#define fcntl fcntl_ignore
-
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
@@ -33,7 +30,6 @@
 #include <string.h>
 #include <unistd.h>
 
-#undef fcntl
 /* Conflicting declaration in glibc. */
 #undef fwrite_unlocked
 
@@ -43,13 +39,17 @@ static ssize_t (*real_write)(int, const void *, size_t);
 static int (*real_close)(int);
 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;
+
 
 #include "constants.h"
 #ifdef DEBUG
 # include "debug.h"
 #endif
 
-#include "macros.h"
+#include "hookmacros.h"
 #include "trackfds.h"
 
 
@@ -62,7 +62,7 @@ static int check_handle_fd(int fd) {
     }
 
     /* Load state from environment. Only necessary once per process. */
-    if (!tracked_fds) {
+    if (!initialized) {
         init_from_environment();
     }
 
@@ -77,7 +77,7 @@ static void dup_fd(int oldfd, int newfd) {
     debug("%d -> %d\t\t\t[%d]\n", oldfd, newfd, getpid());
 #endif
 
-    if (!tracked_fds) {
+    if (!initialized) {
         init_from_environment();
     }
     if (tracked_fds_count == 0) {
@@ -105,7 +105,7 @@ static void close_fd(int fd) {
     debug("%d -> .\t\t\t[%d]\n", fd, getpid());
 #endif
 
-    if (!tracked_fds) {
+    if (!initialized) {
         init_from_environment();
     }
 
@@ -272,15 +272,31 @@ int dup3(int oldfd, int newfd, int flags) {
     return newfd;
 }
 
-static int (*real_fcntl)(int, int, int);
-int fcntl(int fd, int cmd, int arg) {
+static int (*real_fcntl)(int, int, ...);
+int fcntl(int fd, int cmd, ...) {
     int result;
+    va_list ap;
 
     DLSYM_FUNCTION(real_fcntl, "fcntl");
 
-    result = real_fcntl(fd, cmd, arg);
+    /* fcntl() takes different types of arguments depending on the cmd type
+     * (int, void and pointers are used at the moment). Handling these
+     * arguments for different systems and with possible changes in the future
+     * is error prone.
+     *
+     * Therefore always retrieve a void-pointer from our arguments (even if it
+     * wasn't there) and pass it to real_fcntl(). This shouldn't cause any
+     * problems because a void-pointer is most-likely bigger than an int
+     * (something which is not true in reverse) and shouldn't cause
+     * truncation. For register based calling conventions an invalid register
+     * content is passed, but ignored by real_fcntl(). Not perfect, but should
+     * work fine.
+     */
+    va_start(ap, cmd);
+    result = real_fcntl(fd, cmd, va_arg(ap, void *));
+    va_end(ap);
     /* We only care about duping fds. */
-    if (cmd == F_DUPFD) {
+    if (cmd == F_DUPFD && result != -1) {
         int saved_errno = errno;
         dup_fd(fd, result);
         errno = saved_errno;