]> ruderich.org/simon Gitweb - coloredstderr/coloredstderr.git/blobdiff - src/coloredstderr.c
Use static list of descriptors to reduce mallocs.
[coloredstderr/coloredstderr.git] / src / coloredstderr.c
index e04a2ea01be40b4d0644ed65a031b93629c6b2b9..008da266bee76fbbc51efc7280edfe5dcf41fa47 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+#ifdef HAVE_ERROR_H
+# include <error.h>
+#endif
+
 /* Conflicting declaration in glibc. */
 #undef fwrite_unlocked
 
@@ -62,7 +66,10 @@ static int check_handle_fd(int fd) {
     if (!initialized) {
         init_from_environment();
     }
-    if (tracked_fds_count == 0) {
+
+    /* tracked_fds_find() is most likely faster than calling isatty(),
+     * therefore check if we are tracking this file descriptor first. */
+    if (!tracked_fds_find(fd)) {
         return 0;
     }
 
@@ -72,7 +79,7 @@ static int check_handle_fd(int fd) {
         return 0;
     }
 
-    return tracked_fds_find(fd);
+    return 1;
 }
 
 static void dup_fd(int oldfd, int newfd) {
@@ -83,9 +90,6 @@ static void dup_fd(int oldfd, int newfd) {
     if (!initialized) {
         init_from_environment();
     }
-    if (tracked_fds_count == 0) {
-        return;
-    }
 
     /* We are already tracking this file descriptor, add newfd to the list as
      * it will reference the same descriptor. */
@@ -108,9 +112,6 @@ static void close_fd(int fd) {
     if (!initialized) {
         init_from_environment();
     }
-    if (tracked_fds_count == 0) {
-        return;
-    }
 
     tracked_fds_remove(fd);
 }
@@ -231,6 +232,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. */