75487ec322c9c30f666499b1c681d67fb4f119e4
[platform/core/system/dlog.git] / src / logger / logger.c
1 /*
2  * Copyright (c) 2016, Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef _GNU_SOURCE
18 #define _GNU_SOURCE
19 #endif
20
21 #include "logger_internal.h"
22 #include <metrics.h>
23 #include <getopt.h>
24 #include <dynamic_config.h>
25 #include <qos_defaults.h>
26
27 /**
28  * @addtogroup DLOG_IMPLEMENTATION
29  * @{
30  * @defgroup DLOG_LOGGER Logger
31  * @brief Logger daemon
32  * @details The logger is the core component of the logging framework. It is responsible for collecting, processing and exposing logs.
33  * @{
34  */
35
36 // function prototypes
37 static void logger_free(struct logger* l);
38 static int initialize_epoll_size(struct epoll_event **events, unsigned *size);
39
40 /** global state when logger is not interrupted by any handled signals */
41 static volatile sig_atomic_t g_logger_run = 1;
42
43 static const int DEFAULT_EPOLL_TIME_MS = 1000;
44
45 static const int DEFAULT_LAZY_POLLING_TOTAL_MS = 0;
46 static const int DEFAULT_LAZY_POLLING_SLEEP_MS = 1000;
47
48 static const int S_TO_MS = 1000;
49 static const int MS_TO_NS = 1000000;
50
51 struct backend_data g_backend = {};
52
53 /**
54  * @brief Parse permissions
55  * @details Parse a string representation of permissions to the internal integral one
56  * @param[in] str The string representation
57  * @return The integer representation
58  */
59 int parse_permissions(const char * str)
60 {
61         int ret, parsed;
62         char * parse_safety;
63
64         if (!str)
65                 return S_IWUSR | S_IWGRP | S_IWOTH; // 0222: everyone can write
66
67         parsed = strtol(str, & parse_safety, 8); // note, rights are octal
68         if (parse_safety != (str + strlen(str)))
69                 return 0;
70
71         ret = 0;
72
73         // note that R and X are pretty useless, only W makes sense
74         if (parsed & 00001) ret |= S_IXOTH;
75         if (parsed & 00002) ret |= S_IWOTH;
76         if (parsed & 00004) ret |= S_IROTH;
77         if (parsed & 00010) ret |= S_IXGRP;
78         if (parsed & 00020) ret |= S_IWGRP;
79         if (parsed & 00040) ret |= S_IRGRP;
80         if (parsed & 00100) ret |= S_IXUSR;
81         if (parsed & 00200) ret |= S_IWUSR;
82         if (parsed & 00400) ret |= S_IRUSR;
83         if (parsed & 01000) ret |= S_ISVTX;
84         if (parsed & 02000) ret |= S_ISGID;
85         if (parsed & 04000) ret |= S_ISUID;
86
87         if (parsed & ~07777)
88                 printf("Warning: useless bits in permissions %s!", str);
89
90         return ret;
91 }
92
93 /**
94  * @brief Get numerical ids for specified user and group
95  * @details Converts user and group strings to proper uid and gid identifiers
96  * @param[in] user The new user
97  * @param[in] group The new group
98  * @param[out] uid The uid for user
99  * @param[out] gid The numerical gid for group
100  * @return 0 on success, else -errno
101  */
102 int usergr2id(const char * user, const char * group, uid_t *uid, gid_t *gid)
103 {
104         struct passwd pwd, *ppwd;
105         struct group  grp, *pgrp;
106         int bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
107
108         assert(user);
109         assert(group);
110
111         if (bufsize == -1)
112                 bufsize = 1024;
113
114         char *const buffer = (char *)alloca(bufsize);
115
116         if (getgrnam_r(user, &grp, buffer, bufsize, &pgrp))
117                 return -errno;
118         if (!pgrp)
119                 return -ENOENT;
120
121         if (getpwnam_r(group, &pwd, buffer, bufsize, &ppwd))
122                 return -errno;
123         if (!ppwd)
124                 return -ENOENT;
125
126         *uid = pwd.pw_uid;
127         *gid = grp.gr_gid;
128
129         return 0;
130 }
131
132 /**
133  * @brief Reset privileges
134  * @details Resets privileges to those specified at build-time
135  * @return 0 on success, else -errno
136  */
137 int reset_self_privileges()
138 {
139         uid_t uid;
140         gid_t gid;
141         int r;
142
143         r = usergr2id(DLOG_SERVER_USER, DLOG_SERVER_GROUP, &uid, &gid);
144         if (r < 0)
145                 return r;
146
147         if (getegid() != gid && setgid(gid) < 0)
148                 return -errno;
149         if (geteuid() != uid && setuid(uid) < 0)
150                 return -errno; // should never happen
151
152         return 0;
153 }
154
155 static bool cond_reader_logger_free(void *ptr, void *user_data)
156 {
157         struct reader_logger *reader = (struct reader_logger *)ptr;
158         struct logger *logger = (struct logger *)user_data;
159         assert(reader);
160         // TODO: This is absurd, why isn't this in the reader_logger_free function?
161         if (reader->common.fd_entity_sink.fd >= 0)
162                 remove_fd_entity(&logger->epoll_common, &reader->common.fd_entity_sink);
163         if (reader->common.fd_entity_source.fd >= 0)
164                 remove_fd_entity(&logger->epoll_common, &reader->common.fd_entity_source);
165         reader_logger_free(reader);
166         return true;
167 }
168
169 void qos_periodic_check(struct logger *server)
170 {
171         struct qos_module *const qos = &server->qos;
172         struct timespec const now = server->time.mono;
173
174         if (now.tv_sec < qos->cancel_limits_at.tv_sec)
175                 return;
176         if (now.tv_sec == qos->cancel_limits_at.tv_sec
177         &&  now.tv_nsec < qos->cancel_limits_at.tv_nsec)
178                 return;
179
180         if (metrics_get_total(qos->log_metrics) >= qos->threshold)
181                 qos_apply_limits(qos);
182         else
183                 qos_relax_limits(qos);
184
185         qos_set_next_update_time(qos, now);
186         metrics_clear(qos->log_metrics);
187 }
188
189 /**
190  * @brief FD limit handler
191  * @details Checks whether the FD limit was reached and leaves logs about it if so
192  * @param[in] server The logger server
193  * @param[in] err errno from the call that failed to create an FD
194  */
195 void check_if_fd_limit_reached(struct logger *server, int err)
196 {
197         assert(server);
198
199         if (err != ENFILE && err != EMFILE)
200                 return;
201
202         printf("ERROR: dlog_logger fd limit reached!\n");
203
204         /* pick one representative buffer to send the log to;
205          * no point spamming all the buffers, especially since
206          * default dlogutil invocations display 3 buffers so
207          * it would appear multiple times */
208         struct log_buffer *const buf = server->buffers[LOG_ID_MAIN];
209         if (!buf)
210                 return;
211
212         struct dlogutil_entry_with_msg entry;
213         create_pipe_message(&entry,
214                 DLOG_FATAL, /* not really FATAL, but since we're at the FD limit
215                              * there are thousands of logging programs so this one
216                              * would likely get lost in the flood since developers
217                              * tend to overuse ERROR (and FATAL is the one above) */
218                 "DLOG",
219                 "\x1b[31m DLOG DAEMON FD LIMIT REACHED \x1b[0m" // make it stand out
220         );
221         set_pipe_message_sent_timestamp((struct pipe_logger_entry *) &entry, &server->time.mono, &server->time.real);
222
223         if (buffer_append(&entry.header, buf))
224                 printf("ERROR: not enough memory either, please check platform settings as the daemon is seriously resource-starved!\n");
225 }
226
227 void reader_notify_losing_log(const dlogutil_entry_s *le, void *reader_)
228 {
229         struct reader_pipe *reader = (struct reader_pipe *) reader_;
230         assert(le);
231         assert(reader);
232         reader_print_out_single_log(reader, (dlogutil_entry_s *)le);
233 }
234
235 /**
236  * @brief Add reader to log buffer
237  * @details Adds a reader to the log buffers reader list
238  * @param[in] log_buffer The buffer whither to add the reader
239  * @param[in] reader The reader to add to the buffer
240  * @return 0 on success, -ENOMEM on memory allocation error
241  */
242 int add_buffer_reader(struct log_buffer *buffer, struct reader_pipe *reader)
243 {
244         assert(reader);
245         assert(buffer);
246
247         reader->log_storage_reader_ptr = log_storage_new_reader(buffer->log_storage_ptr,
248                         reader->is_dumping, reader->monitor, reader_notify_losing_log, reader);
249
250         if (!reader->log_storage_reader_ptr)
251                 return -ENOMEM;
252
253         return list_add(&buffer->readers_pipe, reader) ? 0 : -ENOMEM;
254 }
255
256 int add_reader_pipe(struct logger *server, struct reader_pipe *reader)
257 {
258         assert(reader);
259         assert(server);
260
261         if (reader->common.fd_entity_sink.fd >= 0) {
262                 /* Readers who write to file have no sink FD entity (or, strictly
263                  * speaking, they do have one but it is not filled) since a file
264                  * is not eligible to be added to epoll. However, the entity primarily
265                  * serves to handle pipes getting clogged mid-write (which cannot
266                  * happen for files) and is not involved in starting a write,
267                  * which is handled by the source FD entity, not sink (and which is
268                  * also done periodically for all readers anyway regardless
269                  * of whether they've been added to epoll or not). The other use
270                  * case for epoll - the one where connection FDs leak for unused
271                  * buffers - is not a problem here because the daemon is not
272                  * supposed to ever stop writing to files. */
273
274                 int r = add_fd_entity(&server->epoll_common, &reader->common.fd_entity_sink);
275                 if (r < 0)
276                         return r;
277         }
278
279         int ret;
280         ret = add_buffer_reader(reader->buf_ptr, reader);
281         if (ret < 0 && reader->common.fd_entity_sink.fd >= 0)
282                 remove_fd_entity(&server->epoll_common, &reader->common.fd_entity_sink);
283
284         return ret;
285 }
286
287 static int add_reader_logger(struct logger *server, struct reader_logger *reader)
288 {
289         assert(reader);
290         assert(server);
291
292         if (reader->common.fd_entity_sink.fd >= 0) {
293                 /* Readers who write to file have no sink FD entity (or, strictly
294                  * speaking, they do have one but it is not filled) since a file
295                  * is not eligible to be added to epoll. However, the entity primarily
296                  * serves to handle pipes getting clogged mid-write (which cannot
297                  * happen for files) and is not involved in starting a write,
298                  * which is handled by the source FD entity, not sink (and which is
299                  * also done periodically for all readers anyway regardless
300                  * of whether they've been added to epoll or not). The other use
301                  * case for epoll - the one where connection FDs leak for unused
302                  * buffers - is not a problem here because the daemon is not
303                  * supposed to ever stop writing to files. */
304
305                 int r = add_fd_entity(&server->epoll_common, &reader->common.fd_entity_sink);
306                 if (r < 0)
307                         return r;
308         }
309
310         int ret;
311
312         assert(reader->common.fd_entity_source.fd >= 0);
313         ret = add_fd_entity(&server->epoll_common, &reader->common.fd_entity_source);
314         if (ret < 0)
315                 goto failure;
316
317         if (!list_add(&server->readers_logger, reader)) {
318                 remove_fd_entity(&server->epoll_common, &reader->common.fd_entity_source);
319                 ret = -ENOMEM;
320                 goto failure;
321         }
322
323         return 0;
324
325 failure:
326         if (reader->common.fd_entity_sink.fd >= 0)
327                 remove_fd_entity(&server->epoll_common, &reader->common.fd_entity_sink);
328
329         return ret;
330 }
331
332 int create_fifo_fds(struct logger *server, int fifo_id, int *write_fd, int *read_fd, bool dump)
333 {
334         assert(write_fd);
335         assert(read_fd);
336
337         char fifo_path[64];
338         if (snprintf(fifo_path, sizeof fifo_path, "/run/dlog/priv/fifo/%d", fifo_id) < 0)
339                 return -errno;
340
341         if (mkfifo(fifo_path, 0600) < 0) {
342                 assert(errno != EEXIST);
343                 return -errno;
344         }
345
346         int ret = 0;
347
348         *read_fd = open(fifo_path, O_RDONLY | O_NONBLOCK);
349         if (*read_fd < 0) {
350                 check_if_fd_limit_reached(server, errno);
351                 ret = -errno;
352                 goto finish;
353         }
354
355         *write_fd = open(fifo_path, O_WRONLY | O_NONBLOCK);
356         if (*write_fd < 0) {
357                 check_if_fd_limit_reached(server, errno);
358                 ret = -errno;
359                 close(*read_fd);
360                 goto finish;
361         }
362
363         /* Speed up dumping dlogutils by increasing their pipe size,
364          * as otherwise this pipe's size becomes a major bottleneck.
365          *
366          * Continuous connections don't really care if the initial
367          * burst of "historic" logs is slow and the following flow
368          * of logs is just fine with a small pipe. Meanwhile they
369          * live for a long time during which they would take away
370          * from the valuable total pipe size. */
371         if (dump)
372                 if (fcntl(*write_fd, F_SETPIPE_SZ, DUMPING_READER_PIPE_SIZE) < 0) {
373                         /* Ignore; this is just a performance optimisation
374                          * and doesn't affect functionality so while errors
375                          * are worrisome they not a big deal or something
376                          * we can do anything about, at any rate. */
377                 }
378
379 finish:
380         unlink(fifo_path);
381         return ret;
382 }
383
384 static int create_logger_subreader_from_dlogutil_line(struct dlogutil_line_params *params)
385 {
386         if (params->file_path) {
387                 int retval = logfile_set_path(&params->file, params->file_path);
388                 if (retval < 0)
389                         return retval;
390
391                 retval = logfile_open(&params->file);
392                 if (retval < 0)
393                         return retval;
394         }
395
396         if (params->buf_id == LOG_ID_INVALID)
397                 return -EINVAL;
398
399         if (params->file.path == NULL)
400                 return -EINVAL;
401
402         struct reader_logger *const reader = g_backend.logger_readers[params->buf_id];
403         if (!reader)
404                 return -ENOENT;
405
406         return reader_logger_add_subreader_file(reader, params->filter, &params->file);
407 }
408
409 static int create_reader_pipe_from_dlogutil_line(struct dlogutil_line_params *params, struct logger *server, struct reader_pipe **rd)
410 {
411         assert(server);
412         assert(rd);
413
414         __attribute__((cleanup(reader_pipe_cleanup))) struct reader_pipe *reader = NULL;
415         int retval;
416
417         if (params->file_path) {
418                 retval = logfile_set_path(&params->file, params->file_path);
419                 if (retval < 0)
420                         return retval;
421
422                 retval = logfile_open(&params->file);
423                 if (retval < 0)
424                         return retval;
425         }
426
427         if (params->buf_id == LOG_ID_INVALID)
428                 return -EINVAL;
429
430         if (params->file.path == NULL)
431                 return -EINVAL;
432
433         retval = reader_pipe_init(&reader, params->buf_id, server, params->filter, &params->file, params->monitor, params->is_dumping);
434         if (retval != 0)
435                 return retval;
436
437         *rd = reader;
438         reader = NULL;
439
440         return 0;
441 }
442
443 /**
444  * @brief Service a socket request
445  * @details Handle a socket request
446  * @param[in] server The logger server
447  * @param[in] wr The writer who sent the request
448  * @param[in] event The event containing the request
449  * @return 0 on success, else -errno
450  */
451 int service_writer_socket(struct logger* server, struct writer* wr, struct epoll_event* event)
452 {
453         int r = 0;
454
455         assert(wr);
456         struct dlog_control_msg* const msg = (struct dlog_control_msg*) wr->buffer;
457
458         assert(event);
459         if (event->events & EPOLLIN)
460                 r = read(wr->fd_entity.fd, wr->buffer + wr->readed, sizeof wr->buffer - wr->readed);
461
462         if ((r == 0 || r == -1) && event->events & EPOLLHUP)
463                 return -EINVAL;
464
465         do {
466                 if (r > 0)
467                         wr->readed += r;
468
469                 /* The socket is SOCK_STREAM (see `listen_fd_create`), so one message
470                  * could be split into chunks returned across multiple read() calls. */
471                 if (wr->readed < sizeof(msg->length)
472                 ||  wr->readed < msg->length)
473                         goto dont_process_yet_and_read_more_data;
474
475                 assert(wr->service_socket);
476                 r = wr->service_socket(server, wr, msg);
477                 if (r <= 0)
478                         return r;
479
480 dont_process_yet_and_read_more_data:
481                 r = read(wr->fd_entity.fd, wr->buffer + wr->readed, sizeof wr->buffer - wr->readed);
482         } while (r > 0 || ((wr->readed >= sizeof(msg->length) && wr->readed >= msg->length)));
483
484         return (r >= 0 || errno == EAGAIN)  ? 0 : r;
485 }
486
487 /**
488  * @brief Service /dev/kmsg
489  * @details Read from the /dev/kmsg device
490  * @param[in] server The logger server
491  * @param[in] wr The writer who sent the request
492  * @param[in] event The relevant event
493  * @return 0 on success, else -errno
494  */
495 int service_writer_kmsg(struct logger* server, struct writer* wr, struct epoll_event* event)
496 {
497         (void) server;
498         if (event->events & EPOLLHUP)
499                 return -EBADF;
500         if (!(event->events & EPOLLIN))
501                 return 0;
502
503         /* The KMSG device returns just 1 log per read() so it is done in a loop.
504          * In theory this could starve everything else out if logs appeared faster
505          * than the daemon could process them, which would then necessitate some
506          * sort of throttling. In practice, KMSG doesn't really get flooded with
507          * logs the same way Android Logger devices are so the throttling is mostly
508          * there because we get it for free anyway and consistency doesn't hurt. */
509
510         int max_loop_iterations = g_backend.logger_device_throttling[LOG_ID_KMSG];
511         while (max_loop_iterations--) {
512                 int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
513
514                 if (r == -1 && (errno == EAGAIN || errno == EPIPE))
515                         return 0;
516                 else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
517                         return -EINVAL;
518                 else if (r == 0)
519                         return -EBADF;
520                 else if (r == -1)
521                         return -errno;
522
523                 wr->buffer[r] = '\0';
524                 struct dlogutil_entry_with_msg lem;
525                 if (parse_kmsg_message(wr->buffer, &lem, r)) {
526                         // don't signal an error: KMSG writer is too important to remove; besides, it would not get fixed that way.
527                         return 0;
528                 }
529                 add_recv_timestamp(&lem.header, server->time);
530                 r = buffer_append(&lem.header, wr->buf_ptr);
531                 if (r < 0)
532                         return r;
533         }
534
535         return 0;
536 }
537
538 void remove_reader_fd_entities(struct logger *server, struct reader *reader)
539 {
540         assert(reader);
541
542         if (reader->fd_entity_sink.fd >= 0)
543                 remove_fd_entity(&server->epoll_common, &reader->fd_entity_sink);
544         if (reader->fd_entity_source.fd >= 0)
545                 remove_fd_entity(&server->epoll_common, &reader->fd_entity_source);
546 }
547
548 static bool cond_service_reader_pipe(void *ptr, void *user_data)
549 {
550         assert(ptr);
551         assert(user_data);
552         struct reader_pipe *reader = (struct reader_pipe *)ptr;
553         struct logger *logger = (struct logger *)user_data;
554
555         if (!logger->exiting && reader_should_buffer(reader, &logger->buf_params, logger->time.mono))
556                 return false;
557
558         int r = print_out_logs(reader, logger->time);
559
560         if (r > 0) {
561                 remove_reader_fd_entities(logger, &reader->common);
562                 reader_pipe_free(reader);
563                 return true;
564         }
565
566         /* `service_reader()` returns -1 if everything was flushed, or 0 if
567          * a mild error happened that can be recovered from simply by waiting,
568          * the prime example being the pipe getting clogged. As soon as the
569          * reader is available again, we'd like to know about it to ensure
570          * logs are flushed as quickly as possible, which is why the EPOLLOUT.
571          *
572          * On the other hand, we don't want to remove readers from epoll even
573          * if they successfully flushed and have no logs to wait for. Consider
574          * the case where a buffer is unused (for example through libdlog's
575          * buffer disabling feature). If we relied on receiving an error on
576          * calling `write()` to learn that the connection had been closed,
577          * we would never learn about it because there would be no incoming
578          * logs to trigger the flush and so any FDs representing connections
579          * to such buffer would leak until a log finally arrived (which could
580          * be never). This is why waiting is also done on EPOLLHUP. */
581         if (modify_fd_entity(&logger->epoll_common, &reader->common.fd_entity_sink, (r == 0) ? EPOLLOUT : EPOLLHUP) < 0) {
582                 /* ignore, can't really happen and it's not
583                  * like we can do anything about it either */
584         }
585
586         return false;
587 }
588
589 static bool cond_service_reader_logger(void *ptr, void *user_data)
590 {
591         assert(ptr);
592         assert(user_data);
593         struct reader_logger *reader = (struct reader_logger *)ptr;
594         struct logger *logger = (struct logger *)user_data;
595
596         int r = service_reader_logger(reader, logger->time);
597
598         if (r > 0) {
599                 remove_reader_fd_entities(logger, &reader->common);
600                 reader_logger_free(reader);
601                 return true;
602         }
603
604         /* `service_reader()` returns -1 if everything was flushed, or 0 if
605          * a mild error happened that can be recovered from simply by waiting,
606          * the prime example being the pipe getting clogged. As soon as the
607          * reader is available again, we'd like to know about it to ensure
608          * logs are flushed as quickly as possible, which is why the EPOLLOUT.
609          *
610          * On the other hand, we don't want to remove readers from epoll even
611          * if they successfully flushed and have no logs to wait for. Consider
612          * the case where a buffer is unused (for example through libdlog's
613          * buffer disabling feature). If we relied on receiving an error on
614          * calling `write()` to learn that the connection had been closed,
615          * we would never learn about it because there would be no incoming
616          * logs to trigger the flush and so any FDs representing connections
617          * to such buffer would leak until a log finally arrived (which could
618          * be never). This is why waiting is also done on EPOLLHUP. */
619         if (modify_fd_entity(&logger->epoll_common, &reader->common.fd_entity_sink, (r == 0) ? EPOLLOUT : EPOLLHUP) < 0) {
620                 /* ignore, can't really happen and it's not
621                  * like we can do anything about it either */
622         }
623
624         return false;
625 }
626
627 /**
628  * @brief Service syslog
629  * @details Read from the syslog socket
630  * @param[in] server The logger server
631  * @param[in] wr The writer who sent the request
632  * @param[in] event The relevant event
633  * @return 0 on success, else -errno
634  */
635 int service_writer_syslog(struct logger* server, struct writer* wr, struct epoll_event* event)
636 {
637         if (event->events & EPOLLHUP)
638                 return -EBADF;
639         if (!(event->events & EPOLLIN))
640                 return 0;
641
642         int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
643
644         if (r == -1 && (errno == EAGAIN || errno == EPIPE))
645                 return 0;
646         else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
647                 return -EINVAL;
648         else if (r == 0)
649                 return -EBADF;
650         else if (r == -1)
651                 return -errno;
652
653         wr->buffer[r] = '\0';
654
655         struct dlogutil_entry_with_msg lem;
656         if (parse_syslog_datagram(wr->buffer, r + 1, &lem.header)) {
657                 /* don't return parse error as writers are removed then */
658                 return 0;
659         }
660
661         add_recv_timestamp(&lem.header, server->time);
662         return buffer_append(&lem.header, wr->buf_ptr);
663 }
664
665 /**
666  * @brief Service all readers
667  * @details Update all readers with latest data
668  * @param[in] server The logger server
669  * @param[in] force_push Whether to force logs to be pushed to the readers
670  */
671 static void service_all_readers(struct logger *server)
672 {
673         for (int i = 0; i < LOG_ID_MAX; i++) {
674                 struct log_buffer *const buffer = server->buffers[i];
675                 if (!buffer)
676                         continue;
677
678                 list_remove_if(&buffer->readers_pipe, server, cond_service_reader_pipe);
679         }
680         list_remove_if(&server->readers_logger, server, cond_service_reader_logger);
681 }
682
683 /**
684  * @brief Add writer to server
685  * @details Adds a writer to the server's witers list and registers its event to epoll loop
686  * @param[in] l The server to add the writer to
687  * @param[in] writer The writer to add to the server and register its working_fd to epoll loop
688  */
689 void logger_add_writer(struct logger* l, struct writer* wr)
690 {
691         assert(l);
692         assert(wr);
693
694         list_add(&l->writers, wr);
695         add_fd_entity(&l->epoll_common, &wr->fd_entity);
696 }
697
698 int epoll_metadata_initialize(struct epoll_metadata *metadata)
699 {
700         metadata->fd = epoll_create1(0);
701         if (metadata->fd < 0)
702                 return -errno;
703
704         int r = initialize_epoll_size(&metadata->events, &metadata->events_size);
705         if (r < 0) {
706                 close(metadata->fd);
707                 metadata->fd = -1;
708                 return r;
709         }
710
711         metadata->cnt = 0;
712         return 0;
713 }
714
715 void epoll_metadata_destroy(struct epoll_metadata *metadata)
716 {
717         if (metadata->fd >= 0)
718                 close(metadata->fd);
719
720         free(metadata->events);
721 }
722
723 /**
724  * @brief Create the logger server
725  * @details Allocate the logger server's auxiliary structures (buffers etc.)
726  * @param[in] data Initialisation data
727  * @param[out] l The logger server
728  * @return 0 on success, -errno on failure
729  */
730 static int logger_create(struct logger_config_data *data, struct logger *l)
731 {
732         memset(l, 0, sizeof *l);
733         l->epoll_socket.fd = -1;
734
735         int r = epoll_metadata_initialize(&l->epoll_common);
736         if (r < 0)
737                 return r;
738         r = epoll_metadata_initialize(&l->epoll_socket);
739         if (r < 0)
740                 return r;
741
742         l->epolltime = data->epoll_time;
743
744         l->lazy_polling_total = data->lazy_polling_total;
745         l->lazy_polling_sleep = data->lazy_polling_sleep;
746
747         l->buf_params = data->buf_params;
748
749         l->qos.log_metrics = metrics_create();
750         if (!l->qos.log_metrics)
751                 return -ENOMEM;
752
753         l->qos.max_throughput = data->qos_max_throughput;
754         l->qos.threshold = data->qos_threshold;
755         l->qos.threshold_reapply = data->qos_threshold_reapply;
756         l->qos.limit_duration = data->qos_limit_duration;
757         l->qos.file_path = data->qos_file_path;
758         data->qos_file_path = NULL;
759
760         // Check if the daemon is being launched for the first time since reboot
761         bool first_time;
762         if (data->first_time_file_path) {
763                 int fd = open(data->first_time_file_path, O_CREAT | O_EXCL | O_RDONLY, 0644);
764                 if (fd == -1) {
765                         if (errno == EEXIST)
766                                 first_time = false;
767                         else
768                                 return -errno;
769                 } else {
770                         first_time = true;
771                         close(fd);
772                 }
773         } else
774                 // If no path, assume first time
775                 first_time = true;
776
777         if (g_backend.use_logger_by_default)
778                 for (log_id_t id = 0; id < LOG_ID_MAX; ++id) {
779                         if (!is_core_buffer(id))
780                                 continue;
781
782                         int r = reader_logger_init(g_backend.logger_readers + id, id, l, !first_time);
783                         if (r < 0)
784                                 return r;
785                         if (!g_backend.logger_readers[id])
786                                 continue;
787
788                         if (qos_is_enabled(&l->qos)) {
789                                 r = reader_logger_add_subreader_metrics(g_backend.logger_readers[id], &l->qos);
790                                 if (r < 0)
791                                         return r;
792                         }
793
794                         r = add_reader_logger(l, g_backend.logger_readers[id]);
795                         if (r < 0)
796                                 return r;
797                 }
798
799         for (log_id_t id = 0; id < LOG_ID_MAX; id++)
800                 if (data->is_buffer_enabled[id]) {
801                         int r = buffer_create(&l->buffers[id], id, data->buffers + id);
802                         if (r < 0)
803                                 return r;
804                 }
805
806         for (log_id_t id = 0; id < LOG_ID_MAX; id++)
807                 if (l->buffers[id]) {
808                         add_fd_entity(&l->epoll_common, &l->buffers[id]->sock_ctl.fd_entity);
809                         add_fd_entity(&l->epoll_common, &l->buffers[id]->sock_wr.fd_entity);
810
811                         add_fd_entity(&l->epoll_socket, &l->buffers[id]->sock_ctl.fd_entity);
812                         add_fd_entity(&l->epoll_socket, &l->buffers[id]->sock_wr.fd_entity);
813                 }
814
815         /* TODO: make writers creation optional/configurable */
816         int (*writers_factories[LOG_ID_MAX])(struct writer **writer, struct log_buffer *log_buf) = {
817                 [LOG_ID_KMSG] = create_kmsg_writer,
818                 [LOG_ID_SYSLOG] = create_syslog_writer,
819         };
820         for (unsigned u = 0; u < NELEMS(writers_factories); ++u)
821                 if (writers_factories[u] && data->is_buffer_enabled[u]) {
822                         struct writer *wr;
823                         int r = writers_factories[u](&wr, l->buffers[u]);
824                         if (r < 0)
825                                 return r;
826
827                         logger_add_writer(l, wr);
828                 }
829
830         return 0;
831 }
832
833 static bool cond_writer_free(void *ptr, void *user_data)
834 {
835         writer_free((struct writer *)ptr, (struct logger *)user_data);
836         return true;
837 }
838
839 /**
840  * @brief Free logger
841  * @details Deallocate the logger and its auxiliary structures
842  * @param[in] l The logger server
843  */
844 static void logger_free(struct logger *l)
845 {
846         assert(l);
847
848         list_remove_if(&l->writers, l, cond_writer_free);
849         list_remove_if(&l->readers_logger, l, cond_reader_logger_free);
850
851         int j;
852         for (j = 0; j < LOG_ID_MAX; j++)
853                 if (l->buffers[j])
854                         buffer_free(l->buffers[j], l);
855
856         epoll_metadata_destroy(&l->epoll_common);
857         epoll_metadata_destroy(&l->epoll_socket);
858
859         qos_free(&l->qos);
860 }
861
862 /**
863  * @brief Handle interrupting/terminating signals
864  * @details Clears global flag to stop main loop
865  * @param[in] signo signal number
866  */
867 static void handle_signals(int signo)
868 {
869         (void) signo;
870         g_logger_run = 0;
871 }
872
873 static void ensure_epoll_size(struct epoll_event **events, unsigned *size, unsigned wanted_size)
874 {
875         assert(events);
876         assert(size);
877
878         if (wanted_size <= *size)
879                 return;
880
881         typeof(*events) temp = realloc(*events, wanted_size * sizeof **events);
882         if (!temp)
883                 return;
884
885         *events = temp;
886         *size = wanted_size;
887 }
888
889 static int initialize_epoll_size(struct epoll_event **events, unsigned *size)
890 {
891         assert(events);
892         assert(size);
893
894         static const size_t default_size = 16U;
895         typeof(*events) ev = malloc(default_size * sizeof *ev);
896         if (!ev)
897                 return -ENOMEM;
898
899         *events = ev;
900         *size = default_size;
901         return 0;
902 }
903
904 void dispatch_epoll_event(struct logger *server, struct epoll_event *event)
905 {
906         struct fd_entity *const entity = (struct fd_entity *) event->data.ptr;
907         assert(entity->dispatch_event);
908         entity->dispatch_event(server, event, entity->dispatch_data);
909 }
910
911 int handle_epoll_events(struct logger *server, struct epoll_metadata *metadata, int timeout)
912 {
913         ensure_epoll_size(&metadata->events, &metadata->events_size, metadata->cnt);
914
915         int nfds = epoll_wait(metadata->fd, metadata->events, metadata->events_size, timeout);
916         if (nfds < 0)
917                 return errno == EINTR ? 0 : -errno;
918
919         for (int i = 0; i < nfds; i++)
920                 dispatch_epoll_event(server, metadata->events + i);
921
922         return 0;
923 }
924
925 int sleep_while_handling_socket(struct logger *server, struct epoll_metadata *metadata, int timeout)
926 {
927         do {
928                 int r = handle_epoll_events(server, metadata, timeout);
929                 if (r < 0)
930                         return r;
931
932                 struct timespec now;
933                 clock_gettime(CLOCK_MONOTONIC, &now);
934                 timeout -= (now.tv_sec  - server->time.mono.tv_sec ) *  S_TO_MS
935                          + (now.tv_nsec - server->time.mono.tv_nsec) / MS_TO_NS;
936                 server->time.mono.tv_sec  = now.tv_sec;
937                 server->time.mono.tv_nsec = now.tv_nsec;
938
939                 clock_gettime(CLOCK_REALTIME, &server->time.real);
940         } while (timeout > 0);
941
942         return 0;
943 }
944
945 /**
946  * @brief Do logging
947  * @details The main logging loop
948  * @param[in] server The logger server
949  * @return 0 on success, else -errno
950  */
951 static int do_logger(struct logger* server)
952 {
953         struct sigaction action = {
954                 .sa_handler = handle_signals,
955                 .sa_flags   = 0
956         };
957         sigemptyset(&action.sa_mask);
958
959         static const int handled_signals[] = { SIGINT, SIGTERM };
960         for (unsigned u = 0; u < NELEMS(handled_signals); ++u)
961                 sigaction(handled_signals[u], &action, NULL);
962
963         bool use_lazy_polling = true;
964         while (g_logger_run) {
965                 clock_gettime(CLOCK_MONOTONIC, &server->time.mono);
966                 clock_gettime(CLOCK_REALTIME,  &server->time.real);
967
968                 if (server->lazy_polling_total >= 0) {
969                         server->lazy_polling_total -= server->lazy_polling_sleep;
970                         use_lazy_polling = (server->lazy_polling_total >= 0);
971                 }
972                 if (use_lazy_polling)
973                         sleep_while_handling_socket(server, &server->epoll_socket, server->lazy_polling_sleep);
974
975                 int r = handle_epoll_events(server, &server->epoll_common, server->epolltime * !use_lazy_polling);
976                 if (r < 0)
977                         break;
978
979                 service_all_readers(server);
980                 qos_periodic_check(server);
981         }
982
983         /* ensure all logs are written no matter when the program was interrupted */
984         server->exiting = 1;
985         service_all_readers(server);
986
987         return 0;
988 }
989
990 /**
991  * @brief Prepare socket data
992  * @details Extracts initialisation data specific to each socket
993  * @param[in] conf Config database
994  * @param[out] data Socket init config data
995  * @param[in] buf_name The name of the buffer the socket belongs to
996  * @param[in] type The name of the buffer type
997  * @return 0 on success, -errno on failure
998  */
999 int prepare_socket_data(const struct log_config *conf, struct socket_config_data *data, char *buf_name, const char *type)
1000 {
1001         char conf_key[MAX_CONF_KEY_LEN];
1002         int r;
1003
1004         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_%s_sock", buf_name, type);
1005         if (r < 0)
1006                 return -errno;
1007         const char * const path = log_config_get(conf, conf_key);
1008
1009         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_%s_sock_rights", buf_name, type);
1010         if (r < 0)
1011                 return -errno;
1012         const char * const permissions_str = log_config_get(conf, conf_key);
1013
1014         if (!permissions_str || !path)
1015                 return -ENOENT;
1016
1017         data->permissions = parse_permissions(permissions_str);
1018         if (data->permissions <= 0)
1019                 return -EINVAL;
1020
1021         strncpy(data->path, path, MAX_CONF_VAL_LEN - 1);
1022
1023         return 0;
1024 }
1025
1026 /**
1027  * @brief Prepare buffer data
1028  * @details Extracts data specific for each buffer
1029  * @param[in] conf Config database
1030  * @param[out] data Buffer init config data
1031  * @param[in] buf_id Index of the buffer to work with
1032  * @return 0 on success, -errno on failure
1033  */
1034 int prepare_buffer_data(const struct log_config *conf, struct buffer_config_data *data, log_id_t buf_id)
1035 {
1036         char * const buf_name = log_name_by_id(buf_id);
1037         char * validity_check_ptr;
1038         char conf_key[MAX_CONF_KEY_LEN];
1039         int r;
1040
1041         r = prepare_socket_data(conf, &data->write_socket, buf_name, "write");
1042         if (r < 0)
1043                 return r;
1044
1045         r = prepare_socket_data(conf, &data->ctl_socket, buf_name, "ctl");
1046         if (r < 0)
1047                 return r;
1048
1049         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_size", buf_name);
1050         if (r < 0)
1051                 return -errno;
1052
1053         const char * const size_str = log_config_get(conf, conf_key);
1054         if (!size_str)
1055                 return -ENOENT;
1056
1057         data->size = strtol(size_str, &validity_check_ptr, 10);
1058         if (*validity_check_ptr)
1059                 return -EINVAL;
1060         if (data->size <= 0)
1061                 return -EINVAL;
1062
1063         return 0;
1064 }
1065
1066 /**
1067  * @brief Save logfile line
1068  * @detail Saves logfile config line in user_data list
1069  * @param[in] key Config entry key
1070  * @param[in] value Config entry value
1071  * @param[in] userdata Userdata
1072  */
1073 void save_logfile_config(char const *key, char const *value, void *userdata)
1074 {
1075         assert(userdata);
1076         if (strncmp(key, CONF_PREFIX, sizeof CONF_PREFIX - 1))
1077                 return;
1078
1079         struct logger_config_data *data = (struct logger_config_data *)userdata;
1080         void *cmd = (void *)strdup(value);
1081         if (cmd)
1082                 list_add(&data->logfile_configs, cmd);
1083         //ignore errors
1084 }
1085
1086 /**
1087  * @brief Initialize config data
1088  * @param[out] The data structure to fill with initial values
1089  */
1090 void initialize_config_data(struct logger_config_data *data)
1091 {
1092         memset(data, 0, sizeof *data);
1093 }
1094
1095 /**
1096  * @brief Prepare config data
1097  * @details Extracts relevant config data for logger initialisation
1098  * @param[out] data Parsed configuration
1099  * @return 0 on success, -errno on failure
1100  */
1101 int prepare_config_data(struct logger_config_data *data)
1102 {
1103         assert(data);
1104
1105         struct log_config conf;
1106         int ret = log_config_read(&conf);
1107         if (ret < 0)
1108                 return ret;
1109
1110         const dlogutil_sorting_order_e sort_by = get_order_from_config(&conf);
1111
1112         int throttling_default = log_config_get_int(&conf, "logger_dev_throttling", LOGGER_DEVICE_THROTTLING_DEFAULT);
1113         const char *const dynamic_config_dir = log_config_get(&conf, DYNAMIC_CONFIG_CONF_KEY);
1114
1115         const char * const backend = log_config_get(&conf, "backend");
1116         if (!backend) {
1117                 ret = -ENOENT;
1118                 goto end;
1119         }
1120
1121         for (int i = 0; i < LOG_ID_MAX; i++) {
1122                 char key[MAX_CONF_KEY_LEN];
1123                 const int r = snprintf(key, sizeof key, "logger_dev_throttling_%s", log_name_by_id((log_id_t)i));
1124                 if (r < 0)
1125                         continue;
1126
1127                 g_backend.logger_device_throttling[i] = max_int(1, log_config_get_int(&conf, key, throttling_default));
1128         }
1129
1130         if (dynamic_config_dir && dynamic_config_dir[0] == '/') {
1131                 data->dynamic_config_dir = strdup(dynamic_config_dir);
1132                 if (!data->dynamic_config_dir) {
1133                         ret = -ENOMEM;
1134                         goto end;
1135                 }
1136         } else {
1137                 data->dynamic_config_dir = NULL; // Technically unnecessary but no reason not to put it
1138         }
1139
1140         data->epoll_time = log_config_get_int(&conf, "epoll_time_ms", DEFAULT_EPOLL_TIME_MS);
1141         data->lazy_polling_total = log_config_get_int(&conf, "lazy_polling_total_ms", DEFAULT_LAZY_POLLING_TOTAL_MS);
1142         data->lazy_polling_sleep = log_config_get_int(&conf, "lazy_polling_sleep_ms", DEFAULT_LAZY_POLLING_SLEEP_MS);
1143
1144         const char *const qos_file_path = log_config_get(&conf, "qos_file_path");
1145         data->qos_file_path = qos_file_path ? strdup(qos_file_path) : NULL;
1146
1147         data->qos_limit_duration = log_config_get_int(&conf, "qos_refresh_rate_s", DEFAULT_QOS_LIMIT_DURATION_S);
1148         data->qos_max_throughput = log_config_get_int(&conf, "qos_max_throughput_logs", DEFAULT_QOS_THROUGHPUT_LOGS);
1149         data->qos_threshold = log_config_get_int(&conf, "qos_threshold_logs", DEFAULT_QOS_THRESHOLD_LOGS);
1150         data->qos_threshold_reapply = log_config_get_int(&conf, "qos_threshold_reapply_logs", DEFAULT_QOS_THRESHOLD_REAPPLY_LOGS);
1151
1152         struct {
1153                 void (*func)(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count);
1154                 const char *name;
1155         } const qos_methods[] = {
1156                 { qos_distribution_proportional_raw   , "proportional_raw"    },
1157                 { qos_distribution_proportional_talmud, "proportional_talmud" },
1158                 { qos_distribution_equal              , "equal"               },
1159                 { qos_distribution_equal_dual         , "equal_dual"          },
1160                 { qos_distribution_equal_multi        , "equal_multi"         },
1161         };
1162         qos_distribution_func = qos_distribution_equal_multi; // default
1163         const char *const qos_method = log_config_get(&conf, "qos_method");
1164         if (qos_method)
1165                 for (int i = 0; i < NELEMS(qos_methods); ++i)
1166                         if (!strcmp(qos_method, qos_methods[i].name))
1167                                 qos_distribution_func = qos_methods[i].func;
1168
1169         const char *const first_time_file_path = log_config_get(&conf, "first_time_file_path");
1170         data->first_time_file_path = first_time_file_path ? strdup(first_time_file_path) : NULL;
1171
1172         memset(data->is_buffer_enabled, 0, sizeof(data->is_buffer_enabled));
1173         if (!strcmp(backend, "pipe")) {
1174                 data->is_buffer_enabled[LOG_ID_MAIN] =
1175                         data->is_buffer_enabled[LOG_ID_RADIO] =
1176                         data->is_buffer_enabled[LOG_ID_SYSTEM] =
1177                         data->is_buffer_enabled[LOG_ID_APPS] = 1;
1178                 g_backend.use_logger_by_default = false;
1179         } else if (!strcmp(backend, "logger")) {
1180                 g_backend.use_logger_by_default = true;
1181                 for (log_id_t buf_id = 0; buf_id < LOG_ID_MAX; ++buf_id) {
1182                         const char *const logger_device = log_config_get(&conf, log_name_by_id(buf_id));
1183                         if (logger_device)
1184                                 strncpy(g_backend.logger_devices[buf_id], logger_device,
1185                                         NELEMS(g_backend.logger_devices[buf_id]) - 1);
1186                 }
1187         } else {
1188                 ret = -ENOENT;
1189                 goto end;
1190         }
1191         data->is_buffer_enabled[LOG_ID_KMSG] = log_config_get_boolean(&conf, "handle_kmsg", true);
1192         data->is_buffer_enabled[LOG_ID_SYSLOG] =
1193                 dev_log_sock_get() >= 0 || log_config_get_boolean(&conf, "syslog_force", false);
1194
1195         for (log_id_t buf_id = 0; buf_id < LOG_ID_MAX; ++buf_id) {
1196                 if (data->is_buffer_enabled[buf_id]) {
1197                         ret = prepare_buffer_data(&conf, data->buffers + buf_id, buf_id);
1198                         if (ret < 0)
1199                                 goto end;
1200                         data->buffers[buf_id].sort_by = sort_by;
1201                 }
1202         }
1203         data->logfile_configs = NULL;
1204         log_config_foreach(&conf, save_logfile_config, data);
1205
1206 end:
1207         log_config_free(&conf);
1208         return ret;
1209 }
1210
1211 static bool cond_string_free(void *ptr, void *user_data)
1212 {
1213         (void) user_data;
1214         free(ptr);
1215         return true;
1216 }
1217
1218 static void free_config_data(struct logger_config_data *data)
1219 {
1220         list_remove_if(&data->logfile_configs, NULL, cond_string_free);
1221         free(data->dynamic_config_dir);
1222         free(data->qos_file_path);
1223         free(data->first_time_file_path);
1224 }
1225
1226 /**
1227  * @brief Parse logfile line
1228  * @detail Parses a logfile config line
1229  * @param[in] key Config entry key
1230  * @param[in] value Config entry value
1231  * @param[in] userdata Userdata
1232  */
1233 void parse_logfile_config(void *value, void *userdata)
1234 {
1235         assert(value);
1236         assert(userdata);
1237
1238         struct logger *server = (struct logger *) userdata;
1239         char *configline = (char *) value;
1240
1241         __attribute__((cleanup(free_dlogutil_line_params))) struct dlogutil_line_params params;
1242         if (!initialize_dlogutil_line_params(&params))
1243                 return;
1244
1245         get_dlogutil_line_params(configline, &params);
1246
1247         int r;
1248         if (g_backend.use_logger_by_default && is_core_buffer(params.buf_id)) {
1249                 r = create_logger_subreader_from_dlogutil_line(&params);
1250         } else {
1251                 struct reader_pipe *reader = NULL;
1252                 r = create_reader_pipe_from_dlogutil_line(&params, server, &reader);
1253                 if (r == 0)
1254                         add_reader_pipe(server, reader);
1255         }
1256
1257         if (r != 0) {
1258                 errno = -r;
1259                 printf("Warning: unable to add logutil reader for provided configuration. Ignoring.\n"
1260                        "  Config line: %s\n"
1261                        "  Reason given: %m\n",
1262                        configline);
1263         }
1264 }
1265
1266 #ifndef UNIT_TEST
1267 /**
1268  * @brief Print help
1269  * @details Prints basic usage tips
1270  */
1271 static void help()
1272 {
1273         printf("Usage: %s [options]\n"
1274                "\t-h    Show this help\n"
1275                "\t-b N  Set the size of the log buffer (in bytes)\n"
1276                "\t-t N  Set time between writes to file (in seconds)\n",
1277                program_invocation_short_name);
1278 }
1279
1280 /**
1281  * @brief Parse args
1282  * @details Parses execution parameters of the program
1283  * @param[in] argc Argument count
1284  * @param[in] argv Argument values
1285  * @param[out] b Buffering parameters
1286  * @return 0 or 1 on success, else -errno. Nonzero if the program is to close.
1287  */
1288 static int parse_args(int argc, char **argv, struct buf_params *b)
1289 {
1290         b->time = BUF_PARAM_TIME_DEFAULT;
1291         b->bytes = BUF_PARAM_BYTES_DEFAULT;
1292
1293         __attribute__((cleanup(reset_getopt_internals))) int option;
1294         while ((option = getopt(argc, argv, "hb:t:")) != -1) {
1295                 switch (option) {
1296                 case 't':
1297                         if (!isdigit(optarg[0]))
1298                                 return -EINVAL;
1299                         b->time = clamp_int(atoi(optarg), BUF_PARAM_TIME_MIN, BUF_PARAM_TIME_MAX);
1300                         break;
1301                 case 'b':
1302                         if (!isdigit(optarg[0]))
1303                                 return -EINVAL;
1304                         b->bytes = clamp_int(atoi(optarg), BUF_PARAM_BYTES_MIN, BUF_PARAM_BYTES_MAX);
1305                         break;
1306                 case 'h':
1307                         return 1;
1308                 default:
1309                         return -EINVAL;
1310                 }
1311         }
1312
1313         return 0;
1314 }
1315
1316 /**
1317  * @brief Finalize initialisation
1318  * @details Do misc stuff needed at the end of the initialisation
1319  * @param[in] data configuration dat to read logfiles config lines from
1320  * @param[in] server logger instance to configure
1321  * @return 0 on success, -errno on failure
1322  */
1323 static int finalize_init(struct logger_config_data *data, struct logger *server)
1324 {
1325         int r = sd_notify(0, "READY=1");
1326         if (r < 0)
1327                 return r;
1328
1329         // used to populate the first readers
1330         clock_gettime(CLOCK_MONOTONIC, &server->time.mono);
1331         clock_gettime(CLOCK_REALTIME,  &server->time.real);
1332
1333         //create files after resetting self privileges
1334         list_foreach(data->logfile_configs, server, parse_logfile_config);
1335
1336         return 0;
1337 }
1338
1339 static void precreate_logctl_file(struct logger_config_data *data)
1340 {
1341         char *logctl_file_path = NULL;
1342         if (asprintf(&logctl_file_path, "%s/%s", data->dynamic_config_dir, DYNAMIC_CONFIG_FILENAME) < 0)
1343                 // This is worrying but unimportant
1344                 return;
1345
1346         int fd = open(logctl_file_path, O_RDONLY | O_CREAT, 0644);
1347         if (fd < 0)
1348                 // Again, no big deal
1349                 return;
1350
1351         close(fd);
1352 }
1353
1354 /**
1355  * @brief The logger
1356  * @return 0 on success, nonzero on failure
1357  * @retval 1 Configuration error
1358  * @retval 2 Runtime error
1359  */
1360 int main(int argc, char** argv)
1361 {
1362         int r, ret;
1363
1364         signal(SIGPIPE, SIG_IGN);
1365
1366         r = reset_self_privileges();
1367         if (r < 0) {
1368                 errno = -r;
1369                 printf("Unable to drop privileges to build-time defaults (%m). Exiting.\n");
1370                 return DLOG_EXIT_ERR_RUNTIME;
1371         }
1372
1373         struct logger_config_data data;
1374         initialize_config_data(&data);
1375
1376         if ((r = parse_args(argc, argv, &data.buf_params)) != 0) {
1377                 help();
1378
1379                 if (r > 0)
1380                         return DLOG_EXIT_SUCCESS; // --help option
1381
1382                 errno = -r;
1383                 printf("Unable to parse command line args (%m). Exiting.\n");
1384                 return DLOG_EXIT_ERR_CONFIG;
1385         }
1386
1387         if ((r = prepare_config_data(&data)) != 0) {
1388                 errno = -r;
1389                 printf("Unable to prepare config (%m). Exiting.\n");
1390                 return DLOG_EXIT_ERR_CONFIG;
1391         }
1392
1393         precreate_logctl_file(&data);
1394
1395         struct logger server;
1396         if ((r = logger_create(&data, &server)) < 0) {
1397                 errno = -r;
1398                 printf("Unable to initialize logger with provided configuration (%m). Exiting.\n");
1399                 ret = DLOG_EXIT_ERR_CONFIG;
1400                 goto cleanup;
1401         }
1402
1403         if ((r = finalize_init(&data, &server)) < 0) {
1404                 errno = -r;
1405                 printf("Unable to finalize initialisation (%m). Exiting.\n");
1406                 ret = DLOG_EXIT_ERR_CONFIG;
1407                 goto cleanup;
1408         }
1409
1410         if ((r = do_logger(&server)) < 0) {
1411                 errno = -r;
1412                 printf("Runtime failure (%m). Exiting.\n");
1413                 ret = DLOG_EXIT_ERR_RUNTIME;
1414                 goto cleanup;
1415         }
1416
1417         ret = DLOG_EXIT_SUCCESS;
1418
1419 cleanup:
1420         free_config_data(&data);
1421         logger_free(&server);
1422         return ret;
1423 }
1424 #endif
1425
1426 /**
1427  * @}
1428  * @}
1429  */