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