log.c (1902B)
1 #define _POSIX_C_SOURCE 199506L /* flockfile, funlockfile */ 2 3 #include <errno.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <time.h> 7 #include <unistd.h> 8 9 #include "log.h" 10 #include "rcx.h" 11 12 #define ISO8601_SIZE (sizeof "YYYY-MM-DDThh:mm:ssZ") 13 #define SGR(c) (use_color ? (c) : "") 14 #define RESET "\x1b[m" 15 #define BOLD "\x1b[1m" 16 #define FAINT "\x1b[2m" 17 18 static bool use_color = false; 19 static bool log_time = false; 20 static bool log_loc = false; 21 static int min_level = 0; 22 23 void 24 r_log_init(int color, bool log_time_, bool log_loc_, int min_level_) { 25 if (color > 0) { /* force on */ 26 use_color = true; 27 } else if (color < 0) { /* force off */ 28 use_color = false; 29 } else { /* detect */ 30 char *no_color = getenv("NO_COLOR"); /* https://no-color.org */ 31 use_color = isatty(fileno(stderr)) 32 && !(no_color && no_color[0] != '\0'); 33 } 34 log_time = log_time_; 35 log_loc = log_loc_; 36 min_level = min_level_; 37 } 38 39 static char * 40 iso8601(char *buf, time_t t) { 41 struct tm tm; 42 gmtime_r(&t, &tm); 43 if (!strftime(buf, ISO8601_SIZE, "%Y-%m-%dT%H:%M:%SZ", &tm)) 44 buf[0] = '\0'; /* strftime buffer contents are undefined on failure */ 45 return buf; 46 } 47 48 void 49 r_vlogf_generic( 50 char *file, int line, 51 int level, char *name, char *color, 52 int code, 53 char *fmt, va_list args 54 ) { 55 if (level < min_level) 56 return; 57 58 int saved_errno = errno; 59 60 char stamp[ISO8601_SIZE]; 61 if (log_time) 62 iso8601(stamp, time(0)); /* Note we do this before locking stderr. */ 63 64 /* Lock stderr so other threads' IO does not get interleaved with ours. */ 65 flockfile(stderr); 66 67 if (log_time) 68 fprintf(stderr, "%s%s%s ", SGR(FAINT), stamp, SGR(RESET)); 69 fprintf(stderr, "%s%s%-5s%s ", SGR(BOLD), SGR(color), name, SGR(RESET)); 70 if (log_loc && file) 71 fprintf(stderr, "%s%s:%d%s ", SGR(FAINT), file, line, SGR(RESET)); 72 73 vfprintf(stderr, fmt, args); 74 fputc('\n', stderr); 75 76 funlockfile(stderr); 77 78 if (code) 79 exit(code); 80 81 errno = saved_errno; 82 }