1#define _ALL_SOURCE 2#include "libc.h" 3#include <errno.h> 4#include <fcntl.h> 5#include <signal.h> 6#include <stdarg.h> 7#include <stdio.h> 8#include <string.h> 9#include <sys/socket.h> 10#include <syslog.h> 11#include <threads.h> 12#include <time.h> 13#include <unistd.h> 14 15static mtx_t lock = MTX_INIT; 16static char log_ident[32]; 17static int log_opt; 18static int log_facility = LOG_USER; 19static int log_mask = 0xff; 20static int log_fd = -1; 21 22int setlogmask(int maskpri) { 23 mtx_lock(&lock); 24 int ret = log_mask; 25 if (maskpri) 26 log_mask = maskpri; 27 mtx_unlock(&lock); 28 return ret; 29} 30 31static const struct { 32 short sun_family; 33 char sun_path[9]; 34} log_addr = {AF_UNIX, "/dev/log"}; 35 36void closelog(void) { 37 mtx_lock(&lock); 38 close(log_fd); 39 log_fd = -1; 40 mtx_unlock(&lock); 41} 42 43static void __openlog(void) { 44 log_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); 45 if (log_fd >= 0) 46 connect(log_fd, (void*)&log_addr, sizeof log_addr); 47} 48 49void openlog(const char* ident, int opt, int facility) { 50 mtx_lock(&lock); 51 52 if (ident) { 53 size_t n = strnlen(ident, sizeof log_ident - 1); 54 memcpy(log_ident, ident, n); 55 log_ident[n] = 0; 56 } else { 57 log_ident[0] = 0; 58 } 59 log_opt = opt; 60 log_facility = facility; 61 62 if ((opt & LOG_NDELAY) && log_fd < 0) 63 __openlog(); 64 65 mtx_unlock(&lock); 66} 67 68static int is_lost_conn(int e) { 69 return e == ECONNREFUSED || e == ECONNRESET || e == ENOTCONN || e == EPIPE; 70} 71 72static void _vsyslog(int priority, const char* message, va_list ap) { 73 char timebuf[16]; 74 time_t now; 75 struct tm tm; 76 char buf[1024]; 77 int errno_save = errno; 78 int pid; 79 int l, l2; 80 int hlen; 81 int fd; 82 83 if (log_fd < 0) 84 __openlog(); 85 86 if (!(priority & LOG_FACMASK)) 87 priority |= log_facility; 88 89 now = time(NULL); 90 gmtime_r(&now, &tm); 91 strftime(timebuf, sizeof timebuf, "%b %e %T", &tm); 92 93 pid = (log_opt & LOG_PID) ? getpid() : 0; 94 l = snprintf(buf, sizeof buf, "<%d>%s %n%s%s%.0d%s: ", priority, timebuf, &hlen, log_ident, 95 pid ? "[" : "", pid, pid ? "]" : ""); 96 errno = errno_save; 97 l2 = vsnprintf(buf + l, sizeof buf - l, message, ap); 98 if (l2 >= 0) { 99 if ((size_t)l2 >= sizeof(buf) - l) 100 l = sizeof(buf) - 1; 101 else 102 l += l2; 103 if (buf[l - 1] != '\n') 104 buf[l++] = '\n'; 105 if (send(log_fd, buf, l, 0) < 0 && 106 (!is_lost_conn(errno) || connect(log_fd, (void*)&log_addr, sizeof log_addr) < 0 || 107 send(log_fd, buf, l, 0) < 0) && 108 (log_opt & LOG_CONS)) { 109 fd = open("/dev/console", O_WRONLY | O_NOCTTY | O_CLOEXEC); 110 if (fd >= 0) { 111 dprintf(fd, "%.*s", l - hlen, buf + hlen); 112 close(fd); 113 } 114 } 115 if (log_opt & LOG_PERROR) 116 dprintf(2, "%.*s", l - hlen, buf + hlen); 117 } 118} 119 120void __vsyslog(int priority, const char* message, va_list ap) { 121 if (!(log_mask & LOG_MASK(priority & 7)) || (priority & ~0x3ff)) 122 return; 123 mtx_lock(&lock); 124 _vsyslog(priority, message, ap); 125 mtx_unlock(&lock); 126} 127 128void syslog(int priority, const char* message, ...) { 129 va_list ap; 130 va_start(ap, message); 131 __vsyslog(priority, message, ap); 132 va_end(ap); 133} 134 135weak_alias(__vsyslog, vsyslog); 136