chiark / gitweb /
journal: enforce limits on open journal files
[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                         iovec[n].iov_base = (char*) p;
380                         iovec[n].iov_len = e - p;
381                         n++;
382
383                         remaining -= (e - p) + 1;
384                         p = e + 1;
385                         continue;
386                 } else {
387                         uint64_t l;
388                         char *k;
389
390                         if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
391                                 log_debug("Failed to parse message, ignoring.");
392                                 break;
393                         }
394
395                         memcpy(&l, e + 1, sizeof(uint64_t));
396                         l = le64toh(l);
397
398                         if (remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
399                             e[1+sizeof(uint64_t)+l] != '\n') {
400                                 log_debug("Failed to parse message, ignoring.");
401                                 break;
402                         }
403
404                         k = malloc((e - p) + 1 + l);
405                         if (!k) {
406                                 log_error("Out of memory");
407                                 break;
408                         }
409
410                         memcpy(k, p, e - p);
411                         k[e - p] = '=';
412                         memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
413
414                         iovec[n].iov_base = k;
415                         iovec[n].iov_len = (e - p) + 1 + l;
416                         n++;
417
418                         remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
419                         p = e + 1 + sizeof(uint64_t) + l + 1;
420                 }
421         }
422
423         dispatch_message(s, iovec, n, m, ucred, tv);
424
425         for (j = 0; j < n; j++)
426                 if (iovec[j].iov_base < buffer ||
427                     (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
428                         free(iovec[j].iov_base);
429 }
430
431 static int process_event(Server *s, struct epoll_event *ev) {
432         assert(s);
433
434         if (ev->events != EPOLLIN) {
435                 log_info("Got invalid event from epoll.");
436                 return -EIO;
437         }
438
439         if (ev->data.fd == s->signal_fd) {
440                 struct signalfd_siginfo sfsi;
441                 ssize_t n;
442
443                 n = read(s->signal_fd, &sfsi, sizeof(sfsi));
444                 if (n != sizeof(sfsi)) {
445
446                         if (n >= 0)
447                                 return -EIO;
448
449                         if (errno == EINTR || errno == EAGAIN)
450                                 return 0;
451
452                         return -errno;
453                 }
454
455                 log_debug("Received SIG%s", signal_to_string(sfsi.ssi_signo));
456                 return 0;
457
458         }
459
460         if (ev->data.fd == s->native_fd ||
461             ev->data.fd == s->syslog_fd) {
462                 for (;;) {
463                         struct msghdr msghdr;
464                         struct iovec iovec;
465                         struct ucred *ucred = NULL;
466                         struct timeval *tv = NULL;
467                         struct cmsghdr *cmsg;
468                         union {
469                                 struct cmsghdr cmsghdr;
470                                 uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
471                                             CMSG_SPACE(sizeof(struct timeval))];
472                         } control;
473                         ssize_t n;
474                         int v;
475
476                         if (ioctl(ev->data.fd, SIOCINQ, &v) < 0) {
477                                 log_error("SIOCINQ failed: %m");
478                                 return -errno;
479                         }
480
481                         if (v <= 0)
482                                 return 1;
483
484                         if (s->buffer_size < (size_t) v) {
485                                 void *b;
486                                 size_t l;
487
488                                 l = MAX(LINE_MAX + (size_t) v, s->buffer_size * 2);
489                                 b = realloc(s->buffer, l+1);
490
491                                 if (!b) {
492                                         log_error("Couldn't increase buffer.");
493                                         return -ENOMEM;
494                                 }
495
496                                 s->buffer_size = l;
497                                 s->buffer = b;
498                         }
499
500                         zero(iovec);
501                         iovec.iov_base = s->buffer;
502                         iovec.iov_len = s->buffer_size;
503
504                         zero(control);
505                         zero(msghdr);
506                         msghdr.msg_iov = &iovec;
507                         msghdr.msg_iovlen = 1;
508                         msghdr.msg_control = &control;
509                         msghdr.msg_controllen = sizeof(control);
510
511                         n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT);
512                         if (n < 0) {
513
514                                 if (errno == EINTR || errno == EAGAIN)
515                                         return 1;
516
517                                 log_error("recvmsg() failed: %m");
518                                 return -errno;
519                         }
520
521                         for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
522
523                                 if (cmsg->cmsg_level == SOL_SOCKET &&
524                                     cmsg->cmsg_type == SCM_CREDENTIALS &&
525                                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
526                                         ucred = (struct ucred*) CMSG_DATA(cmsg);
527                                 else if (cmsg->cmsg_level == SOL_SOCKET &&
528                                          cmsg->cmsg_type == SO_TIMESTAMP &&
529                                          cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
530                                         tv = (struct timeval*) CMSG_DATA(cmsg);
531                         }
532
533                         if (ev->data.fd == s->syslog_fd) {
534                                 char *e;
535
536                                 e = memchr(s->buffer, '\n', n);
537                                 if (e)
538                                         *e = 0;
539                                 else
540                                         s->buffer[n] = 0;
541
542                                 process_syslog_message(s, strstrip(s->buffer), ucred, tv);
543                         } else
544                                 process_native_message(s, s->buffer, n, ucred, tv);
545                 }
546
547                 return 1;
548         }
549
550         log_error("Unknown event.");
551         return 0;
552 }
553
554 static int system_journal_open(Server *s) {
555         int r;
556         char *fn;
557         sd_id128_t machine;
558         char ids[33];
559
560         r = sd_id128_get_machine(&machine);
561         if (r < 0)
562                 return r;
563
564         /* First try to create the machine path, but not the prefix */
565         fn = strappend("/var/log/journal/", sd_id128_to_string(machine, ids));
566         if (!fn)
567                 return -ENOMEM;
568         (void) mkdir(fn, 0755);
569         free(fn);
570
571         /* The create the system journal file */
572         fn = join("/var/log/journal/", ids, "/system.journal", NULL);
573         if (!fn)
574                 return -ENOMEM;
575
576         r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal);
577         free(fn);
578
579         if (r >= 0) {
580                 fix_perms(s->system_journal, 0);
581                 return r;
582         }
583
584         if (r < 0 && r != -ENOENT) {
585                 log_error("Failed to open system journal: %s", strerror(-r));
586                 return r;
587         }
588
589         /* /var didn't work, so try /run, but this time we
590          * create the prefix too */
591         fn = join("/run/log/journal/", ids, "/system.journal", NULL);
592         if (!fn)
593                 return -ENOMEM;
594
595         (void) mkdir_parents(fn, 0755);
596         r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal);
597         free(fn);
598
599         if (r < 0) {
600                 log_error("Failed to open runtime journal: %s", strerror(-r));
601                 return r;
602         }
603
604         fix_perms(s->runtime_journal, 0);
605         return r;
606 }
607
608 static int open_syslog_socket(Server *s) {
609         union sockaddr_union sa;
610         int one, r;
611
612         assert(s);
613
614         if (s->syslog_fd < 0) {
615
616                 s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
617                 if (s->syslog_fd < 0) {
618                         log_error("socket() failed: %m");
619                         return -errno;
620                 }
621
622                 zero(sa);
623                 sa.un.sun_family = AF_UNIX;
624                 strncpy(sa.un.sun_path, "/run/systemd/syslog", sizeof(sa.un.sun_path));
625
626                 unlink(sa.un.sun_path);
627
628                 r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
629                 if (r < 0) {
630                         log_error("bind() failed: %m");
631                         return -errno;
632                 }
633
634                 chmod(sa.un.sun_path, 0666);
635         }
636
637         one = 1;
638         r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
639         if (r < 0) {
640                 log_error("SO_PASSCRED failed: %m");
641                 return -errno;
642         }
643
644         one = 1;
645         r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
646         if (r < 0) {
647                 log_error("SO_TIMESTAMP failed: %m");
648                 return -errno;
649         }
650
651         return 0;
652 }
653
654 static int open_native_socket(Server*s) {
655         union sockaddr_union sa;
656         int one, r;
657
658         assert(s);
659
660         if (s->native_fd < 0) {
661
662                 s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
663                 if (s->native_fd < 0) {
664                         log_error("socket() failed: %m");
665                         return -errno;
666                 }
667
668                 zero(sa);
669                 sa.un.sun_family = AF_UNIX;
670                 strncpy(sa.un.sun_path, "/run/systemd/journal", sizeof(sa.un.sun_path));
671
672                 unlink(sa.un.sun_path);
673
674                 r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
675                 if (r < 0) {
676                         log_error("bind() failed: %m");
677                         return -errno;
678                 }
679
680                 chmod(sa.un.sun_path, 0666);
681         }
682
683         one = 1;
684         r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
685         if (r < 0) {
686                 log_error("SO_PASSCRED failed: %m");
687                 return -errno;
688         }
689
690         one = 1;
691         r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
692         if (r < 0) {
693                 log_error("SO_TIMESTAMP failed: %m");
694                 return -errno;
695         }
696
697         return 0;
698 }
699
700 static int server_init(Server *s) {
701         int n, r, fd;
702         struct epoll_event ev;
703         sigset_t mask;
704
705         assert(s);
706
707         zero(*s);
708         s->syslog_fd = s->native_fd = s->signal_fd = -1;
709
710         s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
711         if (s->epoll_fd < 0) {
712                 log_error("Failed to create epoll object: %m");
713                 return -errno;
714         }
715
716         n = sd_listen_fds(true);
717         if (n < 0) {
718                 log_error("Failed to read listening file descriptors from environment: %s", strerror(-n));
719                 return n;
720         }
721
722         for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
723
724                 if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0) {
725
726                         if (s->syslog_fd >= 0) {
727                                 log_error("Too many /dev/log sockets passed.");
728                                 return -EINVAL;
729                         }
730
731                         s->syslog_fd = fd;
732
733                 } else if (sd_is_socket(fd, AF_UNIX, SOCK_DGRAM, -1) > 0) {
734
735                         if (s->native_fd >= 0) {
736                                 log_error("Too many native sockets passed.");
737                                 return -EINVAL;
738                         }
739
740                         s->native_fd = fd;
741                 } else {
742                         log_error("Unknown socket passed.");
743                         return -EINVAL;
744                 }
745         }
746
747         r = open_syslog_socket(s);
748         if (r < 0)
749                 return r;
750
751         zero(ev);
752         ev.events = EPOLLIN;
753         ev.data.fd = s->syslog_fd;
754         if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->syslog_fd, &ev) < 0) {
755                 log_error("Failed to add syslog server fd to epoll object: %m");
756                 return -errno;
757         }
758
759         r = open_native_socket(s);
760         if (r < 0)
761                 return r;
762
763         zero(ev);
764         ev.events = EPOLLIN;
765         ev.data.fd = s->native_fd;
766         if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->native_fd, &ev) < 0) {
767                 log_error("Failed to add native server fd to epoll object: %m");
768                 return -errno;
769         }
770
771         s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func);
772         if (!s->user_journals) {
773                 log_error("Out of memory.");
774                 return -ENOMEM;
775         }
776
777         r = system_journal_open(s);
778         if (r < 0)
779                 return r;
780
781         assert_se(sigemptyset(&mask) == 0);
782         sigset_add_many(&mask, SIGINT, SIGTERM, -1);
783         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
784
785         s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
786         if (s->signal_fd < 0) {
787                 log_error("signalfd(): %m");
788                 return -errno;
789         }
790
791         zero(ev);
792         ev.events = EPOLLIN;
793         ev.data.fd = s->signal_fd;
794
795         if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->signal_fd, &ev) < 0) {
796                 log_error("epoll_ctl(): %m");
797                 return -errno;
798         }
799
800         return 0;
801 }
802
803 static void server_done(Server *s) {
804         JournalFile *f;
805         assert(s);
806
807         if (s->system_journal)
808                 journal_file_close(s->system_journal);
809
810         if (s->runtime_journal)
811                 journal_file_close(s->runtime_journal);
812
813         while ((f = hashmap_steal_first(s->user_journals)))
814                 journal_file_close(f);
815
816         hashmap_free(s->user_journals);
817
818         if (s->epoll_fd >= 0)
819                 close_nointr_nofail(s->epoll_fd);
820
821         if (s->signal_fd >= 0)
822                 close_nointr_nofail(s->signal_fd);
823
824         if (s->syslog_fd >= 0)
825                 close_nointr_nofail(s->syslog_fd);
826
827         if (s->native_fd >= 0)
828                 close_nointr_nofail(s->native_fd);
829 }
830
831 int main(int argc, char *argv[]) {
832         Server server;
833         int r;
834
835         /* if (getppid() != 1) { */
836         /*         log_error("This program should be invoked by init only."); */
837         /*         return EXIT_FAILURE; */
838         /* } */
839
840         if (argc > 1) {
841                 log_error("This program does not take arguments.");
842                 return EXIT_FAILURE;
843         }
844
845         log_set_target(LOG_TARGET_CONSOLE);
846         log_parse_environment();
847         log_open();
848
849         umask(0022);
850
851         r = server_init(&server);
852         if (r < 0)
853                 goto finish;
854
855         log_debug("systemd-journald running as pid %lu", (unsigned long) getpid());
856
857         sd_notify(false,
858                   "READY=1\n"
859                   "STATUS=Processing messages...");
860 #
861         for (;;) {
862                 struct epoll_event event;
863
864                 r = epoll_wait(server.epoll_fd, &event, 1, -1);
865                 if (r < 0) {
866
867                         if (errno == EINTR)
868                                 continue;
869
870                         log_error("epoll_wait() failed: %m");
871                         r = -errno;
872                         goto finish;
873                 } else if (r == 0)
874                         break;
875
876                 r = process_event(&server, &event);
877                 if (r < 0)
878                         goto finish;
879                 else if (r == 0)
880                         break;
881         }
882
883 finish:
884         sd_notify(false,
885                   "STATUS=Shutting down...");
886
887         server_done(&server);
888
889         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
890 }