FreeRDP
Loading...
Searching...
No Matches
JournaldAppender.c
1
21#include <winpr/config.h>
22
23#include "JournaldAppender.h"
24
25#include <unistd.h>
26#include <syslog.h>
27#include <systemd/sd-journal.h>
28
29#include <winpr/crt.h>
30#include <winpr/environment.h>
31
32typedef struct
33{
34 wLogAppender common;
35 char* identifier;
36 FILE* stream;
37} wLogJournaldAppender;
38
39static BOOL WLog_JournaldAppender_Open(wLog* log, wLogAppender* appender)
40{
41 int fd = 0;
42 wLogJournaldAppender* journaldAppender = nullptr;
43
44 if (!log || !appender)
45 return FALSE;
46
47 journaldAppender = (wLogJournaldAppender*)appender;
48 if (journaldAppender->stream)
49 return TRUE;
50
51 fd = sd_journal_stream_fd(journaldAppender->identifier, LOG_INFO, 1);
52 if (fd < 0)
53 return FALSE;
54
55 journaldAppender->stream = fdopen(fd, "w");
56 if (!journaldAppender->stream)
57 {
58 close(fd);
59 return FALSE;
60 }
61
62 setbuffer(journaldAppender->stream, nullptr, 0);
63 return TRUE;
64}
65
66static BOOL WLog_JournaldAppender_Close(wLog* log, wLogAppender* appender)
67{
68 wLogJournaldAppender* journaldAppender = (wLogJournaldAppender*)appender;
69 if (!log || !appender)
70 return FALSE;
71
72 if (journaldAppender->stream)
73 (void)fclose(journaldAppender->stream);
74
75 free(journaldAppender->identifier);
76
77 journaldAppender->stream = nullptr;
78 journaldAppender->identifier = nullptr;
79 return TRUE;
80}
81
82static BOOL WLog_JournaldAppender_WriteMessage(wLog* log, wLogAppender* appender,
83 const wLogMessage* cmessage)
84{
85 if (!log || !appender || !cmessage)
86 return FALSE;
87
88 wLogJournaldAppender* journaldAppender = (wLogJournaldAppender*)appender;
89
90 const char* formatStr = nullptr;
91 switch (cmessage->Level)
92 {
93 case WLOG_TRACE:
94 case WLOG_DEBUG:
95 formatStr = "<7>%s%s\n";
96 break;
97 case WLOG_INFO:
98 formatStr = "<6>%s%s\n";
99 break;
100 case WLOG_WARN:
101 formatStr = "<4>%s%s\n";
102 break;
103 case WLOG_ERROR:
104 formatStr = "<3>%s%s\n";
105 break;
106 case WLOG_FATAL:
107 formatStr = "<2>%s%s\n";
108 break;
109 case WLOG_OFF:
110 return TRUE;
111 default:
112 (void)fprintf(stderr, "%s: unknown level %" PRIu32 "\n", __func__, cmessage->Level);
113 return FALSE;
114 }
115
116 char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
117 WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
118
119 if (cmessage->Level != WLOG_OFF)
120 {
121 WINPR_PRAGMA_DIAG_PUSH
122 WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL(void)
123 fprintf(journaldAppender->stream, formatStr, prefix, cmessage->TextString);
124 WINPR_PRAGMA_DIAG_POP
125 }
126 return TRUE;
127}
128
129static BOOL WLog_JournaldAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
130 const wLogMessage* message)
131{
132 if (!log || !appender || !message)
133 return FALSE;
134
135 (void)fprintf(stderr, "[TODO: %s] data messages not implemented! Ignoring.\n", __func__);
136 return TRUE;
137}
138
139static BOOL WLog_JournaldAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
140 const wLogMessage* message)
141{
142 if (!log || !appender || !message)
143 return FALSE;
144
145 (void)fprintf(stderr, "[TODO: %s] image messages not implemented! Ignoring.\n", __func__);
146 return TRUE;
147}
148
149static BOOL WLog_JournaldAppender_Set(wLogAppender* appender, const char* setting, void* value)
150{
151 wLogJournaldAppender* journaldAppender = (wLogJournaldAppender*)appender;
152
153 /* Just check the value string is not empty */
154 if (!value || (strnlen(value, 2) == 0))
155 return FALSE;
156
157 if (strcmp("identifier", setting) != 0)
158 return FALSE;
159
160 /* If the stream is already open the identifier can't be changed */
161 if (journaldAppender->stream)
162 return FALSE;
163
164 if (journaldAppender->identifier)
165 free(journaldAppender->identifier);
166
167 return ((journaldAppender->identifier = _strdup((const char*)value)) != nullptr);
168}
169
170static void WLog_JournaldAppender_Free(wLogAppender* appender)
171{
172 wLogJournaldAppender* journaldAppender = nullptr;
173 if (appender)
174 {
175 journaldAppender = (wLogJournaldAppender*)appender;
176 if (journaldAppender->stream)
177 (void)fclose(journaldAppender->stream);
178 free(journaldAppender->identifier);
179 free(journaldAppender);
180 }
181}
182
183wLogAppender* WLog_JournaldAppender_New(wLog* log)
184{
185 LPCSTR name = "WLOG_JOURNALD_ID";
186
187 wLogJournaldAppender* appender = (wLogJournaldAppender*)calloc(1, sizeof(wLogJournaldAppender));
188 if (!appender)
189 return nullptr;
190
191 appender->common.Type = WLOG_APPENDER_JOURNALD;
192 appender->common.Open = WLog_JournaldAppender_Open;
193 appender->common.Close = WLog_JournaldAppender_Close;
194 appender->common.WriteMessage = WLog_JournaldAppender_WriteMessage;
195 appender->common.WriteDataMessage = WLog_JournaldAppender_WriteDataMessage;
196 appender->common.WriteImageMessage = WLog_JournaldAppender_WriteImageMessage;
197 appender->common.Set = WLog_JournaldAppender_Set;
198 appender->common.Free = WLog_JournaldAppender_Free;
199
200 const DWORD nSize = GetEnvironmentVariableA(name, nullptr, 0);
201 if (nSize)
202 {
203 appender->identifier = (LPSTR)malloc(nSize);
204 if (!appender->identifier)
205 goto error_open;
206
207 if (GetEnvironmentVariableA(name, appender->identifier, nSize) != nSize - 1)
208 goto error_open;
209
210 if (!WLog_JournaldAppender_Open(log, (wLogAppender*)appender))
211 goto error_open;
212 }
213
214 return (wLogAppender*)appender;
215
216error_open:
217 free(appender->identifier);
218 free(appender);
219 return nullptr;
220}