X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=src%2Fcoloredstderr.c;h=2640410aa040a4f72b5c6d24a6aa7facc780d75d;hb=cfad8a624c73178b2c82df44efdfefc91bacdeea;hp=eb9d92cc3c1148d6160e87c4aade4171d8fd2c91;hpb=1068648718dad86471451266fcdf4248bb79f3fe;p=coloredstderr%2Fcoloredstderr.git diff --git a/src/coloredstderr.c b/src/coloredstderr.c index eb9d92c..2640410 100644 --- a/src/coloredstderr.c +++ b/src/coloredstderr.c @@ -36,8 +36,12 @@ #include #include #include +#include #include +#ifdef HAVE_ERR_H +# include +#endif #ifdef HAVE_ERROR_H # include #endif @@ -45,11 +49,12 @@ # include #endif -/* Conflicting declaration in glibc. */ +/* The following functions may be macros. Undefine them or they cause build + * failures when used in our hook macros below. */ + +/* In glibc, real fwrite_unlocked() is called in macro. */ #undef fwrite_unlocked -/* These functions may be macros when compiling with hardening flags (fortify) - * which cause build failures when used in our hook macros below. Observed - * with Clang on Debian Wheezy. */ +/* In Clang when compiling with hardening flags (fortify) on Debian Wheezy. */ #undef printf #undef fprintf @@ -256,8 +261,14 @@ 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. */ +/* glibc defines (_IO_)putc_unlocked() to a macro which either updates the + * output buffer or calls __overflow(). As this code is inlined we can't + * handle the first case, but if __overflow() is called we can color that + * part. As writes to stderr are never buffered, __overflow() is always called + * and everything works fine. This is only a problem if stdout is dupped to + * stderr (which shouldn't be the case too often). */ #ifdef HAVE_STRUCT__IO_FILE__FILENO +/* _IO_FILE is glibc's representation of FILE. */ HOOK_FD2(int, __overflow, f->_fileno, _IO_FILE *, f, int, ch) #endif @@ -265,6 +276,33 @@ HOOK_FD2(int, __overflow, f->_fileno, _IO_FILE *, f, int, ch) HOOK_VOID1(void, perror, STDERR_FILENO, char const *, s) +/* err(3), non standard BSD extension */ +#ifdef HAVE_ERR_H +HOOK_VAR_VOID2(void, err, STDERR_FILENO, verr, + int, eval, char const *, fmt) +HOOK_VAR_VOID2(void, errx, STDERR_FILENO, verrx, + int, eval, char const *, fmt) +HOOK_VAR_VOID1(void, warn, STDERR_FILENO, vwarn, + char const *, fmt) +HOOK_VAR_VOID1(void, warnx, STDERR_FILENO, vwarnx, + char const *, fmt) +HOOK_FUNC_SIMPLE3(void, verr, int, eval, const char *, fmt, va_list, args) { + /* Can't use verr() directly as it terminates the process which prevents + * the post string from being printed. */ + vwarn(fmt, args); + exit(eval); +} +HOOK_FUNC_SIMPLE3(void, verrx, int, eval, const char *, fmt, va_list, args) { + /* See verr(). */ + vwarnx(fmt, args); + exit(eval); +} +HOOK_VOID2(void, vwarn, STDERR_FILENO, + char const *, fmt, va_list, args) +HOOK_VOID2(void, vwarnx, STDERR_FILENO, + char const *, fmt, va_list, args) +#endif + /* error(3), non-standard GNU extension */ #ifdef HAVE_ERROR_H static void error_vararg(int status, int errnum,