They are used by some GNU programs to display error messages.
/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
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
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
#include <string.h>
#include <unistd.h>
+#ifdef HAVE_ERROR_H
+# include <error.h>
+#endif
+
/* Conflicting declaration in glibc. */
#undef fwrite_unlocked
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. */
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 \
--- /dev/null
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE /* for program_invocation_name */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <error.h>
+
+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, "<message>");
+ error_at_line(0, 0, "file", 42, "<message>");
+
+ error(0, ENOMEM, "<message>");
+ error_at_line(0, ENOMEM, "file", 42, "<message>");
+ error_at_line(0, ENOMEM, "file", 42, "<message>");
+
+ error_print_progname = print_prognmae;
+ error_one_per_line = 1;
+
+ error(0, 0, "<message>");
+ error_at_line(0, 0, "file", 42, "<message>");
+
+ error(0, ENOMEM, "<message>");
+ error_at_line(0, ENOMEM, "file", 42, "<message>");
+ error_at_line(0, ENOMEM, "file", 42, "<message>");
+
+ /* Exit codes are not tested. */
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+>STDERR>./example_error:<STDERR<>STDERR> <STDERR<>STDERR><message><STDERR<>STDERR>
+<STDERR<>STDERR>./example_error:<STDERR<>STDERR>file:42:<STDERR<>STDERR> <STDERR<>STDERR><message><STDERR<>STDERR>
+<STDERR<>STDERR>./example_error:<STDERR<>STDERR> <STDERR<>STDERR><message><STDERR<>STDERR>: Cannot allocate memory<STDERR<>STDERR>
+<STDERR<>STDERR>./example_error:<STDERR<>STDERR>file:42:<STDERR<>STDERR> <STDERR<>STDERR><message><STDERR<>STDERR>: Cannot allocate memory<STDERR<>STDERR>
+<STDERR<>STDERR>./example_error:<STDERR<>STDERR>file:42:<STDERR<>STDERR> <STDERR<>STDERR><message><STDERR<>STDERR>: Cannot allocate memory<STDERR<>STDERR>
+<STDERR<>STDERR>PROG<STDERR<>STDERR><message><STDERR<>STDERR>
+<STDERR<>STDERR>PROG<STDERR<>STDERR>file:42:<STDERR<>STDERR> <STDERR<>STDERR><message><STDERR<>STDERR>
+<STDERR<>STDERR>PROG<STDERR<>STDERR><message><STDERR<>STDERR>: Cannot allocate memory<STDERR<>STDERR>
+<STDERR<>STDERR>PROG<STDERR<>STDERR>file:42:<STDERR<>STDERR> <STDERR<>STDERR><message><STDERR<>STDERR>: Cannot allocate memory<STDERR<>STDERR>
+<STDERR<
\ No newline at end of file
test_program example
test_program example_exec
test_program example_vfork
+test -x "$builddir/example_error" && test_program example_error
test_script_subshell example-simple.sh
test_script_subshell example-redirects.sh
test_program_subshell example
test_program_subshell example_exec
test_program_subshell example_vfork
+test -x "$builddir/example_error" && test_program_subshell example_error
+
+# Necessary in case the test -x evaluates to false.
+true