From: Simon Ruderich Date: Wed, 5 Jun 2013 21:57:05 +0000 (+0200) Subject: Hook error() and error_at_line() if available. X-Git-Tag: 0.1~106 X-Git-Url: https://ruderich.org/simon/gitweb/?p=coloredstderr%2Fcoloredstderr.git;a=commitdiff_plain;h=7f9856c5dace35f8efe5a20ee1013815e67b9550 Hook error() and error_at_line() if available. They are used by some GNU programs to display error messages. --- diff --git a/.gitignore b/.gitignore index 098d918..5139119 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,8 @@ /tests/Makefile.in /tests/example /tests/example.o +/tests/example_error +/tests/example_error.o /tests/example_exec /tests/example_exec.o /tests/example_vfork diff --git a/configure.ac b/configure.ac index a5279d0..f660e60 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ dnl Used by test suite. AC_PROG_SED AC_PROG_EGREP -AC_CHECK_HEADERS([fcntl.h]) +AC_CHECK_HEADERS([fcntl.h error.h]) AC_TYPE_PID_T AC_TYPE_SIZE_T @@ -51,5 +51,8 @@ AC_ARG_ENABLE([debug], AC_DEFINE([DEBUG], 1, [Define to enable debug output.]) fi]) +dnl Used in tests/Makefile.am to build the test only if error() is available. +AM_CONDITIONAL([HAVE_ERROR_H],[test "x$ac_cv_header_error_h" = xyes]) + AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile]) AC_OUTPUT diff --git a/src/coloredstderr.c b/src/coloredstderr.c index e04a2ea..7ffa158 100644 --- a/src/coloredstderr.c +++ b/src/coloredstderr.c @@ -30,6 +30,10 @@ #include #include +#ifdef HAVE_ERROR_H +# include +#endif + /* Conflicting declaration in glibc. */ #undef fwrite_unlocked @@ -231,6 +235,74 @@ HOOK_FILE1(int, puts_unlocked, stdout, HOOK_VOID1(void, perror, STDERR_FILENO, const char *, s) +/* error(3) */ +#ifdef HAVE_ERROR_H +static void error_vararg(int status, int errnum, + const char *filename, unsigned int linenum, + const char *format, va_list ap) { + static const char *last_filename; + static unsigned int last_linenum; + + /* Skip this error message if requested and if there was already an error + * in the same file/line. */ + if (error_one_per_line + && filename != NULL && linenum != 0 + && filename == last_filename && linenum == last_linenum) { + return; + } + last_filename = filename; + last_linenum = linenum; + + error_message_count++; + + fflush(stdout); + + if (error_print_progname) { + error_print_progname(); + } else { + fprintf(stderr, "%s:", program_invocation_name); + } + if (filename != NULL && linenum != 0) { + fprintf(stderr, "%s:%u:", filename, linenum); + if (error_print_progname) { + fprintf(stderr, " "); + } + } + if (!error_print_progname) { + fprintf(stderr, " "); + } + + + vfprintf(stderr, format, ap); + + if (errnum != 0) { + fprintf(stderr, ": %s", strerror(errnum)); + } + + fprintf(stderr, "\n"); + + if (status != 0) { + exit(status); + } +} +void error_at_line(int status, int errnum, + const char *filename, unsigned int linenum, + const char *format, ...) { + va_list ap; + + va_start(ap, format); + error_vararg(status, errnum, filename, linenum, format, ap); + va_end(ap); +} +void error(int status, int errnum, const char *format, ...) { + va_list ap; + + va_start(ap, format); + error_vararg(status, errnum, NULL, 0, format, ap); + va_end(ap); +} +#endif + /* Hook functions which duplicate file descriptors to track them. */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 025fa8a..bc3a9a9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,8 +4,14 @@ example_SOURCES = example.c example_exec_SOURCES = example_exec.c example_vfork_SOURCES = example_vfork.c +if HAVE_ERROR_H + check_PROGRAMS += example_error + example_error_SOURCES = example_error.c +endif + dist_check_SCRIPTS = run.sh lib.sh dist_check_DATA = example.expected \ + example_error.expected \ example_exec.expected \ example_vfork.expected \ example-noforce.sh \ diff --git a/tests/example_error.c b/tests/example_error.c new file mode 100644 index 0000000..04eca8d --- /dev/null +++ b/tests/example_error.c @@ -0,0 +1,57 @@ +/* + * Test error() and error_at_line(). Non-standard, GNU only. + * + * Copyright (C) 2013 Simon Ruderich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define _GNU_SOURCE /* for program_invocation_name */ +#include +#include +#include +#include + +void (*error_print_progname)(void); + + +static void print_prognmae(void) { + fprintf(stderr, "PROG"); +} + + +int main(int argc, char **argv) { + program_invocation_name = "./example_error"; + + error(0, 0, ""); + error_at_line(0, 0, "file", 42, ""); + + error(0, ENOMEM, ""); + error_at_line(0, ENOMEM, "file", 42, ""); + error_at_line(0, ENOMEM, "file", 42, ""); + + error_print_progname = print_prognmae; + error_one_per_line = 1; + + error(0, 0, ""); + error_at_line(0, 0, "file", 42, ""); + + error(0, ENOMEM, ""); + error_at_line(0, ENOMEM, "file", 42, ""); + error_at_line(0, ENOMEM, "file", 42, ""); + + /* Exit codes are not tested. */ + + return EXIT_SUCCESS; +} diff --git a/tests/example_error.expected b/tests/example_error.expected new file mode 100644 index 0000000..463f343 --- /dev/null +++ b/tests/example_error.expected @@ -0,0 +1,10 @@ +>STDERR>./example_error:STDERR> STDERR>STDERR> +STDERR>./example_error:STDERR>file:42:STDERR> STDERR>STDERR> +STDERR>./example_error:STDERR> STDERR>STDERR>: Cannot allocate memorySTDERR> +STDERR>./example_error:STDERR>file:42:STDERR> STDERR>STDERR>: Cannot allocate memorySTDERR> +STDERR>./example_error:STDERR>file:42:STDERR> STDERR>STDERR>: Cannot allocate memorySTDERR> +STDERR>PROGSTDERR>STDERR> +STDERR>PROGSTDERR>file:42:STDERR> STDERR>STDERR> +STDERR>PROGSTDERR>STDERR>: Cannot allocate memorySTDERR> +STDERR>PROGSTDERR>file:42:STDERR> STDERR>STDERR>: Cannot allocate memorySTDERR> +