mirror of
https://github.com/FAUSheppy/colorredstderr-mirror
synced 2025-12-09 16:38:32 +01:00
Hook BSD err(), errx(), warn(), warnx(), etc. functions.
err(), errx(), warn(), warnx(), verr(), verrx(), vwarn(), vwarnx() are hooked.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -23,6 +23,8 @@
|
||||
/tests/Makefile.in
|
||||
/tests/example
|
||||
/tests/example.o
|
||||
/tests/example_err
|
||||
/tests/example_err.o
|
||||
/tests/example_error
|
||||
/tests/example_error.o
|
||||
/tests/example_exec
|
||||
@@ -31,6 +33,8 @@
|
||||
/tests/example_vfork.o
|
||||
/tests/test_environment.sh.log
|
||||
/tests/test_environment.sh.trs
|
||||
/tests/test_err.sh.log
|
||||
/tests/test_err.sh.trs
|
||||
/tests/test_error.sh.log
|
||||
/tests/test_error.sh.trs
|
||||
/tests/test_example.sh.log
|
||||
|
||||
@@ -36,7 +36,7 @@ if test "x$GCC" = xyes; then
|
||||
CFLAGS="-Wall -Wextra -Wconversion $CFLAGS"
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS([error.h])
|
||||
AC_CHECK_HEADERS([err.h error.h])
|
||||
AC_CHECK_HEADERS([fcntl.h],
|
||||
[],[AC_MSG_ERROR([header is required])])
|
||||
|
||||
@@ -81,6 +81,7 @@ AC_ARG_ENABLE([debug],
|
||||
fi])
|
||||
|
||||
dnl Used in tests/Makefile.am to build the test only if function is available.
|
||||
AM_CONDITIONAL([HAVE_ERR_H],[test "x$ac_cv_header_err_h" = xyes])
|
||||
AM_CONDITIONAL([HAVE_ERROR_H],[test "x$ac_cv_header_error_h" = xyes])
|
||||
AM_CONDITIONAL([HAVE_VFORK],[test "x$ac_cv_func_vfork_works" = xyes])
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_ERR_H
|
||||
# include <err.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERROR_H
|
||||
# include <error.h>
|
||||
#endif
|
||||
@@ -265,6 +268,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,
|
||||
|
||||
@@ -115,6 +115,9 @@
|
||||
static type (*real_ ## name)(type1, type2, ...); \
|
||||
type name(type1 arg1, type2 arg2, ...)
|
||||
|
||||
#define HOOK_FUNC_SIMPLE3(type, name, type1, arg1, type2, arg2, type3, arg3) \
|
||||
type name(type1 arg1, type2 arg2, type3 arg3)
|
||||
|
||||
#define HOOK_VOID1(type, name, fd, type1, arg1) \
|
||||
static type (*real_ ## name)(type1); \
|
||||
type name(type1 arg1) { \
|
||||
@@ -122,6 +125,35 @@
|
||||
real_ ## name(arg1); \
|
||||
_HOOK_POST_FD_(fd) \
|
||||
}
|
||||
#define HOOK_VOID2(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) \
|
||||
real_ ## name(arg1, arg2); \
|
||||
_HOOK_POST_FD_(fd) \
|
||||
}
|
||||
#define HOOK_VOID3(type, name, fd, type1, arg1, type2, arg2, type3, arg3) \
|
||||
static type (*real_ ## name)(type1, type2, type3); \
|
||||
type name(type1 arg1, type2 arg2, type3 arg3) { \
|
||||
_HOOK_PRE_FD_(type, name, fd) \
|
||||
real_ ## name(arg1, arg2, arg3); \
|
||||
_HOOK_POST_FD_(fd) \
|
||||
}
|
||||
|
||||
#define HOOK_VAR_VOID1(type, name, fd, func, type1, arg1) \
|
||||
type name(type1 arg1, ...) { \
|
||||
va_list ap; \
|
||||
va_start(ap, arg1); \
|
||||
func(arg1, ap); \
|
||||
va_end(ap); \
|
||||
}
|
||||
#define HOOK_VAR_VOID2(type, name, fd, func, type1, arg1, type2, arg2) \
|
||||
type name(type1 arg1, type2 arg2, ...) { \
|
||||
va_list ap; \
|
||||
va_start(ap, arg2); \
|
||||
func(arg1, arg2, ap); \
|
||||
va_end(ap); \
|
||||
}
|
||||
|
||||
#define HOOK_FD2(type, name, fd, type1, arg1, type2, arg2) \
|
||||
static type (*real_ ## name)(type1, type2); \
|
||||
|
||||
@@ -12,6 +12,11 @@ check_PROGRAMS = example example_exec
|
||||
example_SOURCES = example.c
|
||||
example_exec_SOURCES = example_exec.c
|
||||
|
||||
if HAVE_ERR_H
|
||||
TESTS += test_err.sh
|
||||
check_PROGRAMS += example_err
|
||||
example_error_SOURCES = example_err.c
|
||||
endif
|
||||
if HAVE_ERROR_H
|
||||
TESTS += test_error.sh
|
||||
check_PROGRAMS += example_error
|
||||
@@ -24,9 +29,11 @@ if HAVE_VFORK
|
||||
endif
|
||||
|
||||
dist_check_SCRIPTS = $(TESTS) lib.sh
|
||||
dist_check_DATA = example.expected \
|
||||
dist_check_DATA = example.h \
|
||||
example.expected \
|
||||
example_environment.expected \
|
||||
example_environment_empty.expected \
|
||||
example_err.expected \
|
||||
example_error.expected \
|
||||
example_exec.expected \
|
||||
example_noforce.sh \
|
||||
|
||||
38
tests/example.h
Normal file
38
tests/example.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Helper functions/macros for example files.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#define FORKED_TEST(pid) \
|
||||
pid = fork(); \
|
||||
if (pid == -1) { \
|
||||
perror("fork"); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} else if (pid != 0) { \
|
||||
int status; \
|
||||
if (waitpid(pid, &status, 0) == -1) { \
|
||||
perror("waitpid"); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
if (WIFEXITED(status)) { \
|
||||
printf("exit code: %d\n", WEXITSTATUS(status)); \
|
||||
} else { \
|
||||
printf("child terminated!\n"); \
|
||||
} \
|
||||
fflush(stdout); \
|
||||
} else
|
||||
51
tests/example_err.c
Normal file
51
tests/example_err.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Test err(), verr(), ... Non-standard, BSD 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../src/compiler.h"
|
||||
#include "example.h"
|
||||
|
||||
|
||||
int main(int argc unused, char **argv unused) {
|
||||
pid_t pid;
|
||||
|
||||
FORKED_TEST(pid) { errno = ENOMEM; err(0, "error: %s", "message"); }
|
||||
FORKED_TEST(pid) { errno = ENOMEM; err(1, "error: %s", "message"); }
|
||||
|
||||
FORKED_TEST(pid) { errx(0, "error: %s", "message"); }
|
||||
FORKED_TEST(pid) { errx(1, "error: %s", "message"); }
|
||||
|
||||
errno = ENOMEM;
|
||||
warn("warning: %s", "message");
|
||||
warnx("warning: %s", "message");
|
||||
|
||||
/* v*() functions are implicitly tested - the implementation uses them. */
|
||||
|
||||
printf("\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
11
tests/example_err.expected
Normal file
11
tests/example_err.expected
Normal file
@@ -0,0 +1,11 @@
|
||||
>STDERR>example_err: error: message: Cannot allocate memory
|
||||
<STDERR<exit code: 0
|
||||
>STDERR>example_err: error: message: Cannot allocate memory
|
||||
<STDERR<exit code: 1
|
||||
>STDERR>example_err: error: message
|
||||
<STDERR<exit code: 0
|
||||
>STDERR>example_err: error: message
|
||||
<STDERR<exit code: 1
|
||||
>STDERR>example_err: warning: message: Cannot allocate memory
|
||||
<STDERR<>STDERR>example_err: warning: message
|
||||
<STDERR<
|
||||
23
tests/test_err.sh
Executable file
23
tests/test_err.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
test "x$srcdir" = x && srcdir=.
|
||||
. "$srcdir/lib.sh"
|
||||
|
||||
test_program example_err
|
||||
test_program_subshell example_err
|
||||
Reference in New Issue
Block a user