]> mj.ucw.cz Git - libucw.git/blob - ucw/log-syslog.c
Opt: exit() does not return, no need to call va_end() afterwards
[libucw.git] / ucw / log-syslog.c
1 /*
2  *      UCW Library -- Logging to Syslog
3  *
4  *      (c) 2009 Martin Mares <mj@ucw.cz>
5  *      (c) 2008 Tomas Gavenciak <gavento@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include <ucw/lib.h>
12 #include <ucw/log.h>
13
14 #include <string.h>
15 #include <syslog.h>
16
17 struct syslog_stream {
18   struct log_stream ls;
19   int facility;
20 };
21
22 static int syslog_open_count;
23
24 static void
25 syslog_close(struct log_stream *ls UNUSED)
26 {
27   if (!--syslog_open_count)
28     closelog();
29 }
30
31 /* Convert syslog facility to its identifier. */
32 static int
33 syslog_facility(const char *name)
34 {
35   // Unfortunately, there is no standard way how to get at the list of facility names
36   static const struct {
37     const char *name;
38     int id;
39   } facilities[] = {
40     { "auth",           LOG_AUTH },
41     { "authpriv",       LOG_AUTHPRIV },
42     { "cron",           LOG_CRON },
43     { "daemon",         LOG_DAEMON },
44     { "ftp",            LOG_FTP },
45     { "kern",           LOG_KERN },
46     { "lpr",            LOG_LPR },
47     { "mail",           LOG_MAIL },
48     { "news",           LOG_NEWS },
49     { "syslog",         LOG_SYSLOG },
50     { "user",           LOG_USER },
51     { "uucp",           LOG_UUCP },
52     { "local0",         LOG_LOCAL0 },
53     { "local1",         LOG_LOCAL1 },
54     { "local2",         LOG_LOCAL2 },
55     { "local3",         LOG_LOCAL3 },
56     { "local4",         LOG_LOCAL4 },
57     { "local5",         LOG_LOCAL5 },
58     { "local6",         LOG_LOCAL6 },
59     { "local7",         LOG_LOCAL7 },
60   };
61
62   for (uns i=0; i < ARRAY_SIZE(facilities); i++)
63     if (!strcmp(facilities[i].name, name))
64       return facilities[i].id;
65   return -1;
66 }
67
68 /* Convert severity level to syslog constants */
69 static int
70 syslog_level(int level)
71 {
72   static const int levels[] = {
73     [L_DEBUG] =         LOG_DEBUG,
74     [L_INFO] =          LOG_INFO,
75     [L_INFO_R] =        LOG_INFO,
76     [L_WARN] =          LOG_WARNING,
77     [L_WARN_R] =        LOG_WARNING,
78     [L_ERROR] =         LOG_ERR,
79     [L_ERROR_R] =       LOG_ERR,
80     [L_FATAL] =         LOG_CRIT,
81   };
82   return ((level < (int)ARRAY_SIZE(levels)) ? levels[level] : LOG_NOTICE);
83 }
84
85 /* simple syslog write handler */
86 static int
87 syslog_handler(struct log_stream *ls, struct log_msg *m)
88 {
89   struct syslog_stream *ss = (struct syslog_stream *) ls;
90   int prio;
91   ASSERT(ls);
92   ASSERT(m);
93
94   prio = syslog_level(LS_GET_LEVEL(m->flags)) | ss->facility;
95   syslog(prio, "%s", m->m);
96   return 0;
97 }
98
99 struct log_stream *
100 log_new_syslog(const char *facility, int options)
101 {
102   int fac = syslog_facility(facility);
103   if (fac < 0)
104     die("No such syslog facility: %s", facility);
105
106   struct log_stream *ls = log_new_stream(sizeof(struct syslog_stream));
107   struct syslog_stream *ss = (struct syslog_stream *) ls;
108   ls->name = "syslog";
109   ls->msgfmt = 0;
110   ls->handler = syslog_handler;
111   ls->close = syslog_close;
112   ss->facility = fac;
113
114   if (!syslog_open_count++)
115     openlog(log_title, options, LOG_INFO);
116   return ls;
117 }
118
119 int
120 log_syslog_facility_exists(const char *facility)
121 {
122   return (syslog_facility(facility) >= 0);
123 }