rcx

miscellaneous C library
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

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 }