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 
15 static mtx_t lock = MTX_INIT;
16 static char log_ident[32];
17 static int log_opt;
18 static int log_facility = LOG_USER;
19 static int log_mask = 0xff;
20 static int log_fd = -1;
21 
setlogmask(int maskpri)22 int 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 
31 static const struct {
32     short sun_family;
33     char sun_path[9];
34 } log_addr = {AF_UNIX, "/dev/log"};
35 
closelog(void)36 void closelog(void) {
37     mtx_lock(&lock);
38     close(log_fd);
39     log_fd = -1;
40     mtx_unlock(&lock);
41 }
42 
__openlog(void)43 static 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 
openlog(const char * ident,int opt,int facility)49 void 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 
is_lost_conn(int e)68 static int is_lost_conn(int e) {
69     return e == ECONNREFUSED || e == ECONNRESET || e == ENOTCONN || e == EPIPE;
70 }
71 
_vsyslog(int priority,const char * message,va_list ap)72 static 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 
__vsyslog(int priority,const char * message,va_list ap)120 void __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 
syslog(int priority,const char * message,...)128 void 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 
135 weak_alias(__vsyslog, vsyslog);
136