blob: 6fc6f4d8a1e76fb9d66640dfbe66b2e3795c3885 [file] [log] [blame]
Rich Felker0b44a032011-02-12 00:22:29 -05001#include <stdarg.h>
2#include <sys/socket.h>
3#include <stdio.h>
4#include <fcntl.h>
5#include <unistd.h>
6#include <syslog.h>
7#include <time.h>
8#include <signal.h>
9#include <string.h>
10#include "libc.h"
11
12static int lock;
13static const char *log_ident;
14static int log_opt;
15static int log_facility = LOG_USER;
16static int log_mask = 0xff;
17static FILE *log_f;
18
19int setlogmask(int maskpri)
20{
21 int old = log_mask;
22 if (maskpri) log_mask = maskpri;
23 return old;
24}
25
26static const struct {
27 short sun_family;
28 char sun_path[9];
29} log_addr = {
30 AF_UNIX,
31 "/dev/log"
32};
33
34void closelog(void)
35{
36 LOCK(&lock);
37 if (log_f) fclose(log_f);
38 log_f = NULL;
39 UNLOCK(&lock);
40}
41
42static void __openlog(const char *ident, int opt, int facility)
43{
44 int fd;
45
46 log_ident = ident;
47 log_opt = opt;
48 log_facility = facility;
49
50 if (!(opt & LOG_NDELAY) || log_f) return;
51
Rich Felkera444ee32011-04-13 17:24:25 -040052 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
Rich Felker0b44a032011-02-12 00:22:29 -050053 fcntl(fd, F_SETFD, FD_CLOEXEC);
54 if (connect(fd, (void *)&log_addr, sizeof(short) + sizeof "/dev/log") < 0)
55 close(fd);
56 else log_f = fdopen(fd, "wb");
57}
58
59void openlog(const char *ident, int opt, int facility)
60{
61 LOCK(&lock);
62 __openlog(ident, opt, facility);
63 UNLOCK(&lock);
64}
65
66void syslog(int priority, const char *message, ...)
67{
Rich Felkera444ee32011-04-13 17:24:25 -040068 sigset_t set, oldset;
Rich Felker0b44a032011-02-12 00:22:29 -050069 va_list ap;
70 char timebuf[16];
71 time_t now;
72 struct tm tm;
73 //const char *fmt, *ident, *sep;
74 //int i;
75
76 if (!(log_mask & LOG_MASK(priority&7)) || (priority&~0x3ff)) return;
77
78 LOCK(&lock);
79
80 if (!log_f) __openlog(log_ident, log_opt | LOG_NDELAY, log_facility);
81 if (!log_f) {
82 UNLOCK(&lock);
83 return;
84 }
85
Rich Felkera444ee32011-04-13 17:24:25 -040086 sigemptyset(&set);
87 sigaddset(&set, SIGPIPE);
88 pthread_sigmask(SIG_BLOCK, &set, &oldset);
Rich Felker0b44a032011-02-12 00:22:29 -050089
90 now = time(NULL);
91 gmtime_r(&now, &tm);
92 strftime(timebuf, sizeof timebuf, "%b %e %T", &tm);
93
94 fprintf(log_f, "<%d>%s ", priority, timebuf);
95 if (log_ident) fprintf(log_f, "%s", log_ident);
96 if (log_opt & LOG_PID) fprintf(log_f, "[%d]", getpid());
97 if (log_ident) fprintf(log_f, ": ");
98
99 va_start(ap, message);
100 vfprintf(log_f, message, ap);
101 va_end(ap);
102 fputc(0, log_f);
103 fflush(log_f);
104
105 // Note: LOG_CONS is not supported because it is annoying!!
106 // syslogd will send messages to console if it deems them appropriate!
107
Rich Felkera444ee32011-04-13 17:24:25 -0400108 /* Clear any possible SIGPIPE generated by the socket write. */
109 sigtimedwait(&set, 0, (struct timespec [1]){0}) || (perror("x"),1);
110 pthread_sigmask(SIG_SETMASK, &oldset, 0);
Rich Felker0b44a032011-02-12 00:22:29 -0500111
112 UNLOCK(&lock);
113}