1 /*
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * All rights reserved.
5  *
6  * Author: Angus Salkeld <asalkeld@redhat.com>
7  *
8  * libqb is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * libqb is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with libqb.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 #include "os_base.h"
22 
23 #ifdef HAVE_SYSLOG_H
24 #include <syslog.h>
25 #endif /* HAVE_SYSLOG_H */
26 #ifdef USE_JOURNAL
27 #define SD_JOURNAL_SUPPRESS_LOCATION
28 #include <systemd/sd-journal.h>
29 #endif
30 
31 #include "log_int.h"
32 
33 static void
_syslog_logger(int32_t target,struct qb_log_callsite * cs,struct timespec * timestamp,const char * msg)34 _syslog_logger(int32_t target,
35 	       struct qb_log_callsite *cs, struct timespec *timestamp, const char *msg)
36 {
37 	char buffer[QB_LOG_MAX_LEN];
38 	char *output_buffer = buffer;
39 	struct qb_log_target *t = qb_log_target_get(target);
40 	int32_t final_priority = cs->priority;
41 
42 	if (final_priority > LOG_INFO) {
43 		/*
44 		 * only bump the priority if it is greater than info.
45 		 */
46 		final_priority += t->priority_bump;
47 	}
48 	if (final_priority > LOG_DEBUG) {
49 		return;
50 	}
51 
52 	if (t->max_line_length > QB_LOG_MAX_LEN) {
53 		output_buffer = malloc(t->max_line_length);
54 		if (!output_buffer) {
55 			return;
56 		}
57 	}
58 
59 	output_buffer[0] = '\0';
60 	qb_log_target_format(target, cs, timestamp, msg, output_buffer);
61 
62 	if (final_priority < LOG_EMERG) {
63 		final_priority = LOG_EMERG;
64 	}
65 #ifdef USE_JOURNAL
66 	if (t->use_journal) {
67 		if (cs->message_id) {
68 			sd_journal_send("MESSAGE_ID=%s", cs->message_id,
69 				"PRIORITY=%d", final_priority,
70 				"CODE_LINE=%d", cs->lineno,
71 				"CODE_FILE=%s", cs->filename,
72 				"CODE_FUNC=%s", cs->function,
73 				"SYSLOG_IDENTIFIER=%s", t->name,
74 				"MESSAGE=%s", output_buffer,
75 				NULL);
76 		} else {
77 			sd_journal_send("PRIORITY=%d", final_priority,
78 				"CODE_LINE=%d", cs->lineno,
79 				"CODE_FILE=%s", cs->filename,
80 				"CODE_FUNC=%s", cs->function,
81 				"SYSLOG_IDENTIFIER=%s", t->name,
82 				"MESSAGE=%s", output_buffer,
83 				NULL);
84 		}
85 	} else {
86 #endif
87 		syslog(final_priority, "%s", output_buffer);
88 #ifdef USE_JOURNAL
89 	}
90 #endif
91 	if (t->max_line_length > QB_LOG_MAX_LEN) {
92 		free(output_buffer);
93 	}
94 }
95 
96 static void
_syslog_close(int32_t target)97 _syslog_close(int32_t target)
98 {
99 	struct qb_log_target *t = qb_log_target_get(target);
100 
101 	if (!t->use_journal) {
102 		closelog();
103 	}
104 }
105 
106 static void
_syslog_reload(int32_t target)107 _syslog_reload(int32_t target)
108 {
109 	struct qb_log_target *t = qb_log_target_get(target);
110 
111 	closelog();
112 	if (!t->use_journal) {
113 		openlog(t->name, LOG_PID, t->facility);
114 	}
115 }
116 
117 int32_t
qb_log_syslog_open(struct qb_log_target * t)118 qb_log_syslog_open(struct qb_log_target *t)
119 {
120 	t->logger = _syslog_logger;
121 	t->reload = _syslog_reload;
122 	t->close = _syslog_close;
123 
124 	if (!t->use_journal) {
125 		openlog(t->name, LOG_PID, t->facility);
126 	}
127 	return 0;
128 }
129