chiark / gitweb /
journal: add native protocol to journald, and client side API to send journal messages
[elogind.git] / src / journal / journald.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/epoll.h>
23 #include <sys/socket.h>
24 #include <errno.h>
25 #include <sys/signalfd.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/acl.h>
29 #include <acl/libacl.h>
30 #include <stddef.h>
31 #include <sys/ioctl.h>
32 #include <linux/sockios.h>
33
34 #include "hashmap.h"
35 #include "journal-file.h"
36 #include "sd-daemon.h"
37 #include "socket-util.h"
38 #include "acl-util.h"
39 #include "cgroup-util.h"
40
41 typedef struct Server {
42         int epoll_fd;
43         int signal_fd;
44         int syslog_fd;
45         int native_fd;
46
47         JournalFile *runtime_journal;
48         JournalFile *system_journal;
49         Hashmap *user_journals;
50
51         uint64_t seqnum;
52
53         char *buffer;
54         size_t buffer_size;
55 } Server;
56
57 static void fix_perms(JournalFile *f, uid_t uid) {
58         acl_t acl;
59         acl_entry_t entry;
60         acl_permset_t permset;
61         int r;
62
63         assert(f);
64
65         r = fchmod_and_fchown(f->fd, 0640, 0, 0);
66         if (r < 0)
67                 log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
68
69         if (uid <= 0)
70                 return;
71
72         acl = acl_get_fd(f->fd);
73         if (!acl) {
74                 log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
75                 return;
76         }
77
78         r = acl_find_uid(acl, uid, &entry);
79         if (r <= 0) {
80
81                 if (acl_create_entry(&acl, &entry) < 0 ||
82                     acl_set_tag_type(entry, ACL_USER) < 0 ||
83                     acl_set_qualifier(entry, &uid) < 0) {
84                         log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
85                         goto finish;
86                 }
87         }
88
89         if (acl_get_permset(entry, &permset) < 0 ||
90             acl_add_perm(permset, ACL_READ) < 0 ||
91             acl_calc_mask(&acl) < 0) {
92                 log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
93                 goto finish;
94         }
95
96         if (acl_set_fd(f->fd, acl) < 0)
97                 log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
98
99 finish:
100         acl_free(acl);
101 }
102
103 static JournalFile* find_journal(Server *s, uid_t uid) {
104         char *p;
105         int r;
106         JournalFile *f;
107         char ids[33];
108         sd_id128_t machine;
109
110         assert(s);
111
112         /* We split up user logs only on /var, not on /run */
113         if (!s->system_journal)
114                 return s->runtime_journal;
115
116         if (uid <= 0)
117                 return s->system_journal;
118
119         r = sd_id128_get_machine(&machine);
120         if (r < 0)
121                 return s->system_journal;
122
123         f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
124         if (f)
125                 return f;
126
127         if (asprintf(&p, "/var/log/journal/%s/user-%lu.journal", sd_id128_to_string(machine, ids), (unsigned long) uid) < 0)
128                 return s->system_journal;
129
130         r = journal_file_open(p, O_RDWR|O_CREAT, 0640, s->system_journal, &f);
131         free(p);
132
133         if (r < 0)
134                 return s->system_journal;
135
136         fix_perms(f, uid);
137
138         r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
139         if (r < 0) {
140                 journal_file_close(f);
141                 return s->system_journal;
142         }
143
144         return f;
145 }
146
147 static void dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, struct ucred *ucred, struct timeval *tv) {
148         char *pid = NULL, *uid = NULL, *gid = NULL,
149                 *source_time = NULL, *boot_id = NULL, *machine_id = NULL,
150                 *comm = NULL, *cmdline = NULL, *hostname = NULL,
151                 *audit_session = NULL, *audit_loginuid = NULL,
152                 *exe = NULL, *cgroup = NULL;
153
154         char idbuf[33];
155         sd_id128_t id;
156         int r;
157         char *t;
158         uid_t loginuid = 0, realuid = 0;
159         JournalFile *f;
160
161         assert(s);
162         assert(iovec || n == 0);
163
164         if (n == 0)
165                 return;
166
167         assert(n + 13 <= m);
168
169         if (ucred) {
170                 uint32_t session;
171                 char *path;
172
173                 realuid = ucred->uid;
174
175                 if (asprintf(&pid, "_PID=%lu", (unsigned long) ucred->pid) >= 0)
176                         IOVEC_SET_STRING(iovec[n++], pid);
177
178                 if (asprintf(&uid, "_UID=%lu", (unsigned long) ucred->uid) >= 0)
179                         IOVEC_SET_STRING(iovec[n++], uid);
180
181                 if (asprintf(&gid, "_GID=%lu", (unsigned long) ucred->gid) >= 0)
182                         IOVEC_SET_STRING(iovec[n++], gid);
183
184                 r = get_process_comm(ucred->pid, &t);
185                 if (r >= 0) {
186                         comm = strappend("_COMM=", t);
187                         if (comm)
188                                 IOVEC_SET_STRING(iovec[n++], comm);
189                         free(t);
190                 }
191
192                 r = get_process_exe(ucred->pid, &t);
193                 if (r >= 0) {
194                         exe = strappend("_EXE=", t);
195                         if (comm)
196                                 IOVEC_SET_STRING(iovec[n++], exe);
197                         free(t);
198                 }
199
200                 r = get_process_cmdline(ucred->pid, LINE_MAX, false, &t);
201                 if (r >= 0) {
202                         cmdline = strappend("_CMDLINE=", t);
203                         if (cmdline)
204                                 IOVEC_SET_STRING(iovec[n++], cmdline);
205                         free(t);
206                 }
207
208                 r = audit_session_from_pid(ucred->pid, &session);
209                 if (r >= 0)
210                         if (asprintf(&audit_session, "_AUDIT_SESSION=%lu", (unsigned long) session) >= 0)
211                                 IOVEC_SET_STRING(iovec[n++], audit_session);
212
213                 r = audit_loginuid_from_pid(ucred->pid, &loginuid);
214                 if (r >= 0)
215                         if (asprintf(&audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0)
216                                 IOVEC_SET_STRING(iovec[n++], audit_loginuid);
217
218                 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, ucred->pid, &path);
219                 if (r >= 0) {
220                         cgroup = strappend("_SYSTEMD_CGROUP=", path);
221                         if (cgroup)
222                                 IOVEC_SET_STRING(iovec[n++], cgroup);
223                         free(path);
224                 }
225         }
226
227         if (tv) {
228                 if (asprintf(&source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu",
229                              (unsigned long long) timeval_load(tv)) >= 0)
230                         IOVEC_SET_STRING(iovec[n++], source_time);
231         }
232
233         /* Note that strictly speaking storing the boot id here is
234          * redundant since the entry includes this in-line
235          * anyway. However, we need this indexed, too. */
236         r = sd_id128_get_boot(&id);
237         if (r >= 0)
238                 if (asprintf(&boot_id, "_BOOT_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
239                         IOVEC_SET_STRING(iovec[n++], boot_id);
240
241         r = sd_id128_get_machine(&id);
242         if (r >= 0)
243                 if (asprintf(&machine_id, "_MACHINE_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
244                         IOVEC_SET_STRING(iovec[n++], machine_id);
245
246         t = gethostname_malloc();
247         if (t) {
248                 hostname = strappend("_HOSTNAME=", t);
249                 if (hostname)
250                         IOVEC_SET_STRING(iovec[n++], hostname);
251                 free(t);
252         }
253
254         assert(n <= m);
255
256         f = find_journal(s, realuid == 0 ? 0 : loginuid);
257         if (!f)
258                 log_warning("Dropping message, as we can't find a place to store the data.");
259         else {
260                 r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
261
262                 if (r < 0)
263                         log_error("Failed to write entry, ignoring: %s", strerror(-r));
264         }
265
266         free(pid);
267         free(uid);
268         free(gid);
269         free(comm);
270         free(exe);
271         free(cmdline);
272         free(source_time);
273         free(boot_id);
274         free(machine_id);
275         free(hostname);
276         free(audit_session);
277         free(audit_loginuid);
278         free(cgroup);
279
280 }
281
282 static void process_syslog_message(Server *s, const char *buf, struct ucred *ucred, struct timeval *tv) {
283         char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL;
284         struct iovec iovec[16];
285         unsigned n = 0;
286         int priority = LOG_USER | LOG_INFO;
287
288         assert(s);
289         assert(buf);
290
291         parse_syslog_priority((char**) &buf, &priority);
292         skip_syslog_date((char**) &buf);
293
294         if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
295                 IOVEC_SET_STRING(iovec[n++], syslog_priority);
296
297         if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
298                 IOVEC_SET_STRING(iovec[n++], syslog_facility);
299
300         message = strappend("MESSAGE=", buf);
301         if (message)
302                 IOVEC_SET_STRING(iovec[n++], message);
303
304         dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv);
305
306         free(message);
307         free(syslog_facility);
308         free(syslog_priority);
309 }
310
311 static void process_native_message(Server *s, const void *buffer, size_t buffer_size, struct ucred *ucred, struct timeval *tv) {
312         struct iovec *iovec = NULL;
313         unsigned n = 0, m = 0, j;
314         const char *p;
315         size_t remaining;
316
317         assert(s);
318         assert(buffer || n == 0);
319
320         p = buffer;
321         remaining = buffer_size;
322
323         while (remaining > 0) {
324                 const char *e, *q;
325
326                 e = memchr(p, '\n', remaining);
327
328                 if (!e) {
329                         /* Trailing noise, let's ignore it, and flush what we collected */
330                         log_debug("Received message with trailing noise, ignoring.");
331                         break;
332                 }
333
334                 if (e == p) {
335                         /* Entry separator */
336                         dispatch_message(s, iovec, n, m, ucred, tv);
337                         n = 0;
338
339                         p++;
340                         remaining--;
341                         continue;
342                 }
343
344                 if (*p == '.') {
345                         /* Control command, ignore for now */
346                         remaining -= (e - p) + 1;
347                         p = e + 1;
348                         continue;
349                 }
350
351                 /* A property follows */
352
353                 if (n+13 >= m) {
354                         struct iovec *c;
355                         unsigned u;
356
357                         u = MAX((n+13U) * 2U, 4U);
358                         c = realloc(iovec, u * sizeof(struct iovec));
359                         if (!c) {
360                                 log_error("Out of memory");
361                                 break;
362                         }
363
364                         iovec = c;
365                         m = u;
366                 }
367
368                 q = memchr(p, '=', e - p);
369                 if (q) {
370                         iovec[n].iov_base = (char*) p;
371                         iovec[n].iov_len = e - p;
372                         n++;
373
374                         remaining -= (e - p) + 1;
375                         p = e + 1;
376                         continue;
377                 } else {
378                         uint64_t l;
379                         char *k;
380
381                         if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
382                                 log_debug("Failed to parse message, ignoring.");
383                                 break;
384                         }
385
386                         memcpy(&l, e + 1, sizeof(uint64_t));
387                         l = le64toh(l);
388
389                         if (remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
390                             e[1+sizeof(uint64_t)+l] != '\n') {
391                                 log_debug("Failed to parse message, ignoring.");
392                                 break;
393                         }
394
395                         k = malloc((e - p) + 1 + l);
396                         if (!k) {
397                                 log_error("Out of memory");
398                                 break;
399                         }
400
401                         memcpy(k, p, e - p);
402                         k[e - p] = '=';
403                         memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
404
405                         iovec[n].iov_base = k;
406                         iovec[n].iov_len = (e - p) + 1 + l;
407                         n++;
408
409                         remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
410                         p = e + 1 + sizeof(uint64_t) + l + 1;
411                 }
412         }
413
414         dispatch_message(s, iovec, n, m, ucred, tv);
415
416         for (j = 0; j < n; j++)
417                 if (iovec[j].iov_base < buffer ||
418                     (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
419                         free(iovec[j].iov_base);
420 }
421
422 static int process_event(Server *s, struct epoll_event *ev) {
423         assert(s);
424
425         if (ev->events != EPOLLIN) {
426                 log_info("Got invalid event from epoll.");
427                 return -EIO;
428         }
429
430         if (ev->data.fd == s->signal_fd) {
431                 struct signalfd_siginfo sfsi;
432                 ssize_t n;
433
434                 n = read(s->signal_fd, &sfsi, sizeof(sfsi));
435                 if (n != sizeof(sfsi)) {
436
437                         if (n >= 0)
438                                 return -EIO;
439
440                         if (errno == EINTR || errno == EAGAIN)
441                                 return 0;
442
443                         return -errno;
444                 }
445
446                 log_debug("Received SIG%s", signal_to_string(sfsi.ssi_signo));
447                 return 0;
448
449         }
450
451         if (ev->data.fd == s->native_fd ||
452             ev->data.fd == s->syslog_fd) {
453                 for (;;) {
454                         struct msghdr msghdr;
455                         struct iovec iovec;
456                         struct ucred *ucred = NULL;
457                         struct timeval *tv = NULL;
458                         struct cmsghdr *cmsg;
459                         union {
460                                 struct cmsghdr cmsghdr;
461                                 uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
462                                             CMSG_SPACE(sizeof(struct timeval))];
463                         } control;
464                         ssize_t n;
465                         int v;
466
467                         if (ioctl(ev->data.fd, SIOCINQ, &v) < 0) {
468                                 log_error("SIOCINQ failed: %m");
469                                 return -errno;
470                         }
471
472                         if (v <= 0)
473                                 return 1;
474
475                         if (s->buffer_size < (size_t) v) {
476                                 void *b;
477                                 size_t l;
478
479                                 l = MAX(LINE_MAX + (size_t) v, s->buffer_size * 2);
480                                 b = realloc(s->buffer, l+1);
481
482                                 if (!b) {
483                                         log_error("Couldn't increase buffer.");
484                                         return -ENOMEM;
485                                 }
486
487                                 s->buffer_size = l;
488                                 s->buffer = b;
489                         }
490
491                         zero(iovec);
492                         iovec.iov_base = s->buffer;
493                         iovec.iov_len = s->buffer_size;
494
495                         zero(control);
496                         zero(msghdr);
497                         msghdr.msg_iov = &iovec;
498                         msghdr.msg_iovlen = 1;
499                         msghdr.msg_control = &control;
500                         msghdr.msg_controllen = sizeof(control);
501
502                         n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT);
503                         if (n < 0) {
504
505                                 if (errno == EINTR || errno == EAGAIN)
506                                         return 1;
507
508                                 log_error("recvmsg() failed: %m");
509                                 return -errno;
510                         }
511
512                         for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
513
514                                 if (cmsg->cmsg_level == SOL_SOCKET &&
515                                     cmsg->cmsg_type == SCM_CREDENTIALS &&
516                                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
517                                         ucred = (struct ucred*) CMSG_DATA(cmsg);
518                                 else if (cmsg->cmsg_level == SOL_SOCKET &&
519                                          cmsg->cmsg_type == SO_TIMESTAMP &&
520                                          cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
521                                         tv = (struct timeval*) CMSG_DATA(cmsg);
522                         }
523
524                         if (ev->data.fd == s->syslog_fd) {
525                                 char *e;
526
527                                 e = memchr(s->buffer, '\n', n);
528                                 if (e)
529                                         *e = 0;
530                                 else
531                                         s->buffer[n] = 0;
532
533                                 process_syslog_message(s, strstrip(s->buffer), ucred, tv);
534                         } else
535                                 process_native_message(s, s->buffer, n, ucred, tv);
536                 }
537
538                 return 1;
539         }
540
541         log_error("Unknown event.");
542         return 0;
543 }
544
545 static int system_journal_open(Server *s) {
546         int r;
547         char *fn;
548         sd_id128_t machine;
549         char ids[33];
550
551         r = sd_id128_get_machine(&machine);
552         if (r < 0)
553                 return r;
554
555         /* First try to create the machine path, but not the prefix */
556         fn = strappend("/var/log/journal/", sd_id128_to_string(machine, ids));
557         if (!fn)
558                 return -ENOMEM;
559         (void) mkdir(fn, 0755);
560         free(fn);
561
562         /* The create the system journal file */
563         fn = join("/var/log/journal/", ids, "/system.journal", NULL);
564         if (!fn)
565                 return -ENOMEM;
566
567         r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal);
568         free(fn);
569
570         if (r >= 0) {
571                 fix_perms(s->system_journal, 0);
572                 return r;
573         }
574
575         if (r < 0 && r != -ENOENT) {
576                 log_error("Failed to open system journal: %s", strerror(-r));
577                 return r;
578         }
579
580         /* /var didn't work, so try /run, but this time we
581          * create the prefix too */
582         fn = join("/run/log/journal/", ids, "/system.journal", NULL);
583         if (!fn)
584                 return -ENOMEM;
585
586         (void) mkdir_parents(fn, 0755);
587         r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal);
588         free(fn);
589
590         if (r < 0) {
591                 log_error("Failed to open runtime journal: %s", strerror(-r));
592                 return r;
593         }
594
595         fix_perms(s->runtime_journal, 0);
596         return r;
597 }
598
599 static int open_syslog_socket(Server *s) {
600         union sockaddr_union sa;
601         int one, r;
602
603         assert(s);
604
605         if (s->syslog_fd < 0) {
606
607                 s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
608                 if (s->syslog_fd < 0) {
609                         log_error("socket() failed: %m");
610                         return -errno;
611                 }
612
613                 zero(sa);
614                 sa.un.sun_family = AF_UNIX;
615                 strncpy(sa.un.sun_path, "/run/systemd/syslog", sizeof(sa.un.sun_path));
616
617                 unlink(sa.un.sun_path);
618
619                 r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
620                 if (r < 0) {
621                         log_error("bind() failed: %m");
622                         return -errno;
623                 }
624
625                 chmod(sa.un.sun_path, 0666);
626         }
627
628         one = 1;
629         r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
630         if (r < 0) {
631                 log_error("SO_PASSCRED failed: %m");
632                 return -errno;
633         }
634
635         one = 1;
636         r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
637         if (r < 0) {
638                 log_error("SO_TIMESTAMP failed: %m");
639                 return -errno;
640         }
641
642         return 0;
643 }
644
645 static int open_native_socket(Server*s) {
646         union sockaddr_union sa;
647         int one, r;
648
649         assert(s);
650
651         if (s->native_fd < 0) {
652
653                 s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
654                 if (s->native_fd < 0) {
655                         log_error("socket() failed: %m");
656                         return -errno;
657                 }
658
659                 zero(sa);
660                 sa.un.sun_family = AF_UNIX;
661                 strncpy(sa.un.sun_path, "/run/systemd/journal", sizeof(sa.un.sun_path));
662
663                 unlink(sa.un.sun_path);
664
665                 r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
666                 if (r < 0) {
667                         log_error("bind() failed: %m");
668                         return -errno;
669                 }
670
671                 chmod(sa.un.sun_path, 0666);
672         }
673
674         one = 1;
675         r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
676         if (r < 0) {
677                 log_error("SO_PASSCRED failed: %m");
678                 return -errno;
679         }
680
681         one = 1;
682         r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
683         if (r < 0) {
684                 log_error("SO_TIMESTAMP failed: %m");
685                 return -errno;
686         }
687
688         return 0;
689 }
690
691 static int server_init(Server *s) {
692         int n, r, fd;
693         struct epoll_event ev;
694         sigset_t mask;
695
696         assert(s);
697
698         zero(*s);
699         s->syslog_fd = s->native_fd = s->signal_fd = -1;
700
701         s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
702         if (s->epoll_fd < 0) {
703                 log_error("Failed to create epoll object: %m");
704                 return -errno;
705         }
706
707         n = sd_listen_fds(true);
708         if (n < 0) {
709                 log_error("Failed to read listening file descriptors from environment: %s", strerror(-n));
710                 return n;
711         }
712
713         for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
714
715                 if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0) {
716
717                         if (s->syslog_fd >= 0) {
718                                 log_error("Too many /dev/log sockets passed.");
719                                 return -EINVAL;
720                         }
721
722                         s->syslog_fd = fd;
723
724                 } else if (sd_is_socket(fd, AF_UNIX, SOCK_DGRAM, -1) > 0) {
725
726                         if (s->native_fd >= 0) {
727                                 log_error("Too many native sockets passed.");
728                                 return -EINVAL;
729                         }
730
731                         s->native_fd = fd;
732                 } else {
733                         log_error("Unknown socket passed.");
734                         return -EINVAL;
735                 }
736         }
737
738         r = open_syslog_socket(s);
739         if (r < 0)
740                 return r;
741
742         zero(ev);
743         ev.events = EPOLLIN;
744         ev.data.fd = s->syslog_fd;
745         if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->syslog_fd, &ev) < 0) {
746                 log_error("Failed to add syslog server fd to epoll object: %m");
747                 return -errno;
748         }
749
750         r = open_native_socket(s);
751         if (r < 0)
752                 return r;
753
754         zero(ev);
755         ev.events = EPOLLIN;
756         ev.data.fd = s->native_fd;
757         if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->native_fd, &ev) < 0) {
758                 log_error("Failed to add native server fd to epoll object: %m");
759                 return -errno;
760         }
761
762         s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func);
763         if (!s->user_journals) {
764                 log_error("Out of memory.");
765                 return -ENOMEM;
766         }
767
768         r = system_journal_open(s);
769         if (r < 0)
770                 return r;
771
772         assert_se(sigemptyset(&mask) == 0);
773         sigset_add_many(&mask, SIGINT, SIGTERM, -1);
774         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
775
776         s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
777         if (s->signal_fd < 0) {
778                 log_error("signalfd(): %m");
779                 return -errno;
780         }
781
782         zero(ev);
783         ev.events = EPOLLIN;
784         ev.data.fd = s->signal_fd;
785
786         if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->signal_fd, &ev) < 0) {
787                 log_error("epoll_ctl(): %m");
788                 return -errno;
789         }
790
791         return 0;
792 }
793
794 static void server_done(Server *s) {
795         JournalFile *f;
796         assert(s);
797
798         if (s->system_journal)
799                 journal_file_close(s->system_journal);
800
801         if (s->runtime_journal)
802                 journal_file_close(s->runtime_journal);
803
804         while ((f = hashmap_steal_first(s->user_journals)))
805                 journal_file_close(f);
806
807         hashmap_free(s->user_journals);
808
809         if (s->epoll_fd >= 0)
810                 close_nointr_nofail(s->epoll_fd);
811
812         if (s->signal_fd >= 0)
813                 close_nointr_nofail(s->signal_fd);
814
815         if (s->syslog_fd >= 0)
816                 close_nointr_nofail(s->syslog_fd);
817
818         if (s->native_fd >= 0)
819                 close_nointr_nofail(s->native_fd);
820 }
821
822 int main(int argc, char *argv[]) {
823         Server server;
824         int r;
825
826         /* if (getppid() != 1) { */
827         /*         log_error("This program should be invoked by init only."); */
828         /*         return EXIT_FAILURE; */
829         /* } */
830
831         if (argc > 1) {
832                 log_error("This program does not take arguments.");
833                 return EXIT_FAILURE;
834         }
835
836         log_set_target(LOG_TARGET_CONSOLE);
837         log_parse_environment();
838         log_open();
839
840         umask(0022);
841
842         r = server_init(&server);
843         if (r < 0)
844                 goto finish;
845
846         log_debug("systemd-journald running as pid %lu", (unsigned long) getpid());
847
848         sd_notify(false,
849                   "READY=1\n"
850                   "STATUS=Processing messages...");
851 #
852         for (;;) {
853                 struct epoll_event event;
854
855                 r = epoll_wait(server.epoll_fd, &event, 1, -1);
856                 if (r < 0) {
857
858                         if (errno == EINTR)
859                                 continue;
860
861                         log_error("epoll_wait() failed: %m");
862                         r = -errno;
863                         goto finish;
864                 } else if (r == 0)
865                         break;
866
867                 r = process_event(&server, &event);
868                 if (r < 0)
869                         goto finish;
870                 else if (r == 0)
871                         break;
872         }
873
874 finish:
875         sd_notify(false,
876                   "STATUS=Shutting down...");
877
878         server_done(&server);
879
880         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
881 }