From 7adfbfd2cf1d46144c41a75aa501938607a316b5 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Thu, 13 Jun 2013 12:59:12 +0200 Subject: [PATCH] Fix hook for putc_unlocked() with glibc. putc_unlocked() is a macro which expands to __overflow() in some cases. --- configure.ac | 5 +++++ src/coloredstderr.c | 7 +++++++ src/hookmacros.h | 7 +++++++ tests/example.c | 4 ++++ tests/example.expected | 1 + 5 files changed, 24 insertions(+) diff --git a/configure.ac b/configure.ac index 7ef71f9..09d90a0 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,11 @@ AC_TYPE_SSIZE_T AC_C_INLINE AX_C___ATTRIBUTE__ +AC_CHECK_MEMBER([struct _IO_FILE._fileno], + [AC_DEFINE([HAVE_STRUCT__IO_FILE__FILENO], 1, + [Define to 1 if `_fileno' is a member of `struct _IO_FILE'.])], + [],[[#include ]]) + AC_FUNC_FORK AC_CHECK_FUNCS([memmove setenv], [],[AC_MSG_ERROR([function is required])]) diff --git a/src/coloredstderr.c b/src/coloredstderr.c index cc58883..db6cb27 100644 --- a/src/coloredstderr.c +++ b/src/coloredstderr.c @@ -35,6 +35,9 @@ #ifdef HAVE_ERROR_H # include #endif +#ifdef HAVE_STRUCT__IO_FILE__FILENO +# include +#endif /* Conflicting declaration in glibc. */ #undef fwrite_unlocked @@ -241,6 +244,10 @@ HOOK_FILE2(int, putc_unlocked, stream, int, c, FILE *, stream) HOOK_FILE1(int, putchar_unlocked, stdout, int, c) +/* glibc defines (_IO_)putc_unlocked() to __overflow() in some cases. */ +#ifdef HAVE_STRUCT__IO_FILE__FILENO +HOOK_FD2(int, __overflow, f->_fileno, _IO_FILE *, f, int, ch) +#endif /* perror(3) */ HOOK_VOID1(void, perror, STDERR_FILENO, diff --git a/src/hookmacros.h b/src/hookmacros.h index b5e2cb0..b8b70ec 100644 --- a/src/hookmacros.h +++ b/src/hookmacros.h @@ -117,6 +117,13 @@ _HOOK_POST_FD_(fd) \ } +#define HOOK_FD2(type, name, fd, type1, arg1, type2, arg2) \ + static type (*real_ ## name)(type1, type2); \ + type name(type1 arg1, type2 arg2) { \ + _HOOK_PRE_FD(type, name, fd) \ + result = real_ ## name(arg1, arg2); \ + _HOOK_POST_FD(fd) \ + } #define HOOK_FD3(type, name, fd, type1, arg1, type2, arg2, type3, arg3) \ static type (*real_ ## name)(type1, type2, type3); \ type name(type1 arg1, type2 arg2, type3 arg3) { \ diff --git a/tests/example.c b/tests/example.c index 7f7d2ad..0fee973 100644 --- a/tests/example.c +++ b/tests/example.c @@ -52,5 +52,9 @@ int main(int argc, char **argv unused) { write(42, "stderr ...\n", 11); write(471, "more on stdout\n", 15); + /* Glibc uses __overflow() for this ... */ + putc_unlocked('x', stderr); + putc_unlocked('\n', stdout); + return EXIT_SUCCESS; } diff --git a/tests/example.expected b/tests/example.expected index edb9c58..ecd2461 100644 --- a/tests/example.expected +++ b/tests/example.expected @@ -6,3 +6,4 @@ >STDERR>more on stderr STDERR>stderr ... STDERR>x