FreeRDP
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 
32 typedef struct
33 {
34  WLOG_APPENDER_COMMON();
35  char* identifier;
36  FILE* stream;
37 } wLogJournaldAppender;
38 
39 static BOOL WLog_JournaldAppender_Open(wLog* log, wLogAppender* appender)
40 {
41  int fd = 0;
42  wLogJournaldAppender* journaldAppender = NULL;
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, NULL, 0);
63  return TRUE;
64 }
65 
66 static BOOL WLog_JournaldAppender_Close(wLog* log, wLogAppender* appender)
67 {
68  if (!log || !appender)
69  return FALSE;
70 
71  return TRUE;
72 }
73 
74 static BOOL WLog_JournaldAppender_WriteMessage(wLog* log, wLogAppender* appender,
75  wLogMessage* message)
76 {
77  char* formatStr = NULL;
78  wLogJournaldAppender* journaldAppender = NULL;
79  char prefix[WLOG_MAX_PREFIX_SIZE] = { 0 };
80 
81  if (!log || !appender || !message)
82  return FALSE;
83 
84  journaldAppender = (wLogJournaldAppender*)appender;
85 
86  switch (message->Level)
87  {
88  case WLOG_TRACE:
89  case WLOG_DEBUG:
90  formatStr = "<7>%s%s\n";
91  break;
92  case WLOG_INFO:
93  formatStr = "<6>%s%s\n";
94  break;
95  case WLOG_WARN:
96  formatStr = "<4>%s%s\n";
97  break;
98  case WLOG_ERROR:
99  formatStr = "<3>%s%s\n";
100  break;
101  case WLOG_FATAL:
102  formatStr = "<2>%s%s\n";
103  break;
104  case WLOG_OFF:
105  return TRUE;
106  default:
107  (void)fprintf(stderr, "%s: unknown level %" PRIu32 "\n", __func__, message->Level);
108  return FALSE;
109  }
110 
111  message->PrefixString = prefix;
112  WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
113 
114  if (message->Level != WLOG_OFF)
115  {
116  WINPR_PRAGMA_DIAG_PUSH
117  WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL(void)
118  fprintf(journaldAppender->stream, formatStr, message->PrefixString, message->TextString);
119  WINPR_PRAGMA_DIAG_POP
120  }
121  return TRUE;
122 }
123 
124 static BOOL WLog_JournaldAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
125  wLogMessage* message)
126 {
127  if (!log || !appender || !message)
128  return FALSE;
129 
130  return TRUE;
131 }
132 
133 static BOOL WLog_JournaldAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
134  wLogMessage* message)
135 {
136  if (!log || !appender || !message)
137  return FALSE;
138 
139  return TRUE;
140 }
141 
142 static BOOL WLog_JournaldAppender_Set(wLogAppender* appender, const char* setting, void* value)
143 {
144  wLogJournaldAppender* journaldAppender = (wLogJournaldAppender*)appender;
145 
146  /* Just check the value string is not empty */
147  if (!value || (strnlen(value, 2) == 0))
148  return FALSE;
149 
150  if (strcmp("identifier", setting))
151  return FALSE;
152 
153  /* If the stream is already open the identifier can't be changed */
154  if (journaldAppender->stream)
155  return FALSE;
156 
157  if (journaldAppender->identifier)
158  free(journaldAppender->identifier);
159 
160  return ((journaldAppender->identifier = _strdup((const char*)value)) != NULL);
161 }
162 
163 static void WLog_JournaldAppender_Free(wLogAppender* appender)
164 {
165  wLogJournaldAppender* journaldAppender = NULL;
166  if (appender)
167  {
168  journaldAppender = (wLogJournaldAppender*)appender;
169  if (journaldAppender->stream)
170  (void)fclose(journaldAppender->stream);
171  free(journaldAppender->identifier);
172  free(journaldAppender);
173  }
174 }
175 
176 wLogAppender* WLog_JournaldAppender_New(wLog* log)
177 {
178  wLogJournaldAppender* appender = NULL;
179  DWORD nSize = 0;
180  LPCSTR name = "WLOG_JOURNALD_ID";
181 
182  appender = (wLogJournaldAppender*)calloc(1, sizeof(wLogJournaldAppender));
183  if (!appender)
184  return NULL;
185 
186  appender->Type = WLOG_APPENDER_JOURNALD;
187  appender->Open = WLog_JournaldAppender_Open;
188  appender->Close = WLog_JournaldAppender_Close;
189  appender->WriteMessage = WLog_JournaldAppender_WriteMessage;
190  appender->WriteDataMessage = WLog_JournaldAppender_WriteDataMessage;
191  appender->WriteImageMessage = WLog_JournaldAppender_WriteImageMessage;
192  appender->Set = WLog_JournaldAppender_Set;
193  appender->Free = WLog_JournaldAppender_Free;
194 
195  nSize = GetEnvironmentVariableA(name, NULL, 0);
196  if (nSize)
197  {
198  appender->identifier = (LPSTR)malloc(nSize);
199  if (!appender->identifier)
200  goto error_open;
201 
202  if (GetEnvironmentVariableA(name, appender->identifier, nSize) != nSize - 1)
203  goto error_open;
204 
205  if (!WLog_JournaldAppender_Open(log, (wLogAppender*)appender))
206  goto error_open;
207  }
208 
209  return (wLogAppender*)appender;
210 
211 error_open:
212  free(appender->identifier);
213  free(appender);
214  return NULL;
215 }