putc_unlocked() is a macro which expands to __overflow() in some cases.
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 <libio.h>]])
+
AC_FUNC_FORK
AC_CHECK_FUNCS([memmove setenv],
[],[AC_MSG_ERROR([function is required])])
#ifdef HAVE_ERROR_H
# include <error.h>
#endif
+#ifdef HAVE_STRUCT__IO_FILE__FILENO
+# include <libio.h>
+#endif
/* Conflicting declaration in glibc. */
#undef fwrite_unlocked
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,
_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) { \
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;
}
>STDERR>more on stderr
<STDERR<>STDERR>stderr ...
<STDERR<more on stdout
+>STDERR>x<STDERR<