ap

Queue manager meant to be used as an audio player
git clone git://jacobedwards.org/ap
Log | Files | Refs | README | LICENSE

log.c (2815B)


      1 /*
      2  * Copyright 2021-2023 Jacob R. Edwards
      3  *
      4  * ap -- audio player
      5  *
      6  * This program is free software: you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation, either version 3 of the License, or
      9  * (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
     18  */
     19 
     20 /* Taken from OpenBSD /usr/include/syslog.h */
     21 #ifndef LOG_MASK
     22 #define LOG_MASK(pri)   (1 << (pri))            /* mask for one priority */
     23 #endif
     24 
     25 #ifndef LOG_UPTO
     26 #define LOG_UPTO(pri)   ((1 << ((pri)+1)) - 1)  /* all priorities through pri */
     27 #endif
     28 
     29 #include <sys/socket.h>
     30 
     31 #include <errno.h>
     32 #include <limits.h>
     33 #include <poll.h>
     34 #include <stdarg.h>
     35 #include <stdio.h>
     36 #include <string.h>
     37 #include <time.h>
     38 
     39 #include "aps.h"
     40 #include "bug.h"
     41 #include "log.h"
     42 #include "util.h"
     43 
     44 static struct {
     45 	char *s;
     46 	int i;
     47 } levels[] = {
     48 	{ "debug", DEBUG },
     49 	{ "info", INFO },
     50 	{ "warn", WARN },
     51 	{ "error", ERROR },
     52 	{ "fatal", FATAL },
     53 	{ "none", 0 }
     54 };
     55 
     56 int
     57 logstrlevel(char *s)
     58 {
     59 	int i;
     60 
     61 	for (i = 0; i < LEN(levels); ++i)
     62 		if (strcmp(levels[i].s, s) == 0)
     63 			return levels[i].i;
     64 	return -1;
     65 }
     66 
     67 char *
     68 loglevelstr(int level)
     69 {
     70 	int i;
     71 
     72 	for (i = 0; i < LEN(levels); ++i)
     73 		if (levels[i].i == level)
     74 			return levels[i].s;
     75 	return NULL;
     76 }
     77 
     78 int
     79 logmask(int level)
     80 {
     81 	return LOG_UPTO(level);
     82 }
     83 
     84 void
     85 newbuflen(int size, int *len, int newlen, char *msg)
     86 {
     87 	if (newlen < 0)
     88 		bug(msg);
     89 	if (*len + newlen >= size)
     90 		bug(msg);
     91 	*len += newlen;
     92 }
     93 
     94 void
     95 aps_log(struct aps *aps, int fd, int level, char *subject, char *fmt, ...)
     96 {
     97 	char *p;
     98 	char buf[256];
     99 	int len;
    100 	va_list ap, apc;
    101 
    102 	if (fmt == NULL || (aps && !(LOG_MASK(level) & aps->logmask)))
    103 		return;
    104 
    105 	len = 0;
    106 
    107 	if (fd) {
    108 		newbuflen(sizeof(buf), &len, snprintf(buf, sizeof(buf),
    109 		    "client %d ", fd), "aps_log client");
    110 	}
    111 
    112 	if (subject) {
    113 		assert(strchr(subject, '%') == NULL, "subject had % in it");
    114 		newbuflen(sizeof(buf), &len, snprintf(buf + len, sizeof(buf) - len,
    115 		    "%.16s ", subject), "aps_log subject");
    116 	}
    117 
    118 	if (!(p = loglevelstr(level)))
    119 		bug("invalid log level");
    120 
    121 	newbuflen(sizeof(buf), &len, snprintf(buf + len, sizeof(buf) - len,
    122 	    "%s: %s", p, fmt), "aps_log level and user format");
    123 
    124 	va_start(ap, fmt);
    125 	if (aps && aps->syslog)
    126 		vsyslog(level, buf, ap);
    127 	else {
    128 		newbuflen(sizeof(buf), &len,
    129 		    strlcpy(buf + len, "\n", sizeof(buf) - len), "newline");
    130 		vfprintf(stderr, buf, ap);
    131 	}
    132 	va_end(ap);
    133 }