~ubuntu-branches/debian/jessie/systemd/jessie

« back to all changes in this revision

Viewing changes to src/log.c

  • Committer: Package Import Robot
  • Author(s): Tollef Fog Heen, Tollef Fog Heen, Michael Biebl
  • Date: 2012-04-03 19:59:17 UTC
  • mfrom: (1.1.10) (6.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20120403195917-l532urrbg4pkreas
Tags: 44-1
[ Tollef Fog Heen ]
* New upstream version.
  - Backport 3492207: journal: PAGE_SIZE is not known on ppc and other
    archs
  - Backport 5a2a2a1: journal: react with immediate rotation to a couple
    of more errors
  - Backport 693ce21: util: never follow symlinks in rm_rf_children()
    Fixes CVE-2012-1174, closes: #664364
* Drop output message from init-functions hook, it's pointless.
* Only rmdir /lib/init/rw if it exists.
* Explicitly order debian-fixup before sysinit.target to prevent a
  possible race condition with the creation of sockets.  Thanks to
  Michael Biebl for debugging this.
* Always restart the initctl socket on upgrades, to mask sysvinit
  removing it.

[ Michael Biebl ]
* Remove workaround for non-interactive sessions from pam config again.
* Create compat /dev/initctl symlink in case we are upgrading from a system
  running a newer version of sysvinit (using /run/initctl) and sysvinit is
  replaced with systemd-sysv during the upgrade. Closes: #663219
* Install new man pages.
* Build-Depend on valac (>= 0.12) instead of valac-0.12. Closes: #663323

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <fcntl.h>
27
27
#include <sys/socket.h>
28
28
#include <sys/un.h>
 
29
#include <stddef.h>
29
30
 
30
31
#include "log.h"
31
32
#include "util.h"
32
33
#include "macro.h"
 
34
#include "socket-util.h"
33
35
 
34
 
#define SYSLOG_TIMEOUT_USEC (5*USEC_PER_SEC)
 
36
#define SNDBUF_SIZE (8*1024*1024)
35
37
 
36
38
static LogTarget log_target = LOG_TARGET_CONSOLE;
37
39
static int log_max_level = LOG_INFO;
39
41
static int console_fd = STDERR_FILENO;
40
42
static int syslog_fd = -1;
41
43
static int kmsg_fd = -1;
 
44
static int journal_fd = -1;
42
45
 
43
46
static bool syslog_is_stream = false;
44
47
 
69
72
 
70
73
        if (getpid() == 1) {
71
74
 
72
 
                if ((console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) {
 
75
                console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
 
76
                if (console_fd < 0) {
73
77
                        log_error("Failed to open /dev/console for logging: %s", strerror(-console_fd));
74
78
                        return console_fd;
75
79
                }
95
99
        if (kmsg_fd >= 0)
96
100
                return 0;
97
101
 
98
 
        if ((kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) {
 
102
        kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
 
103
        if (kmsg_fd < 0) {
99
104
                log_error("Failed to open /dev/kmsg for logging: %s", strerror(errno));
100
105
                return -errno;
101
106
        }
115
120
}
116
121
 
117
122
static int create_log_socket(int type) {
118
 
        struct timeval tv;
119
123
        int fd;
120
124
 
121
 
        if ((fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0)) < 0)
122
 
                return -errno;
123
 
 
124
 
        /* Make sure we don't block for more than 5s when talking to
125
 
         * syslog */
126
 
        timeval_store(&tv, SYSLOG_TIMEOUT_USEC);
127
 
        if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
128
 
                close_nointr_nofail(fd);
129
 
                return -errno;
130
 
        }
 
125
        /* All output to the syslog/journal fds we do asynchronously,
 
126
         * and if the buffers are full we just drop the messages */
 
127
 
 
128
        fd = socket(AF_UNIX, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
 
129
        if (fd < 0)
 
130
                return -errno;
 
131
 
 
132
        fd_inc_sndbuf(fd, SNDBUF_SIZE);
131
133
 
132
134
        return fd;
133
135
}
134
136
 
135
137
static int log_open_syslog(void) {
136
 
        union {
137
 
                struct sockaddr sa;
138
 
                struct sockaddr_un un;
139
 
        } sa;
 
138
        union sockaddr_union sa;
140
139
        int r;
141
140
 
142
141
        if (syslog_fd >= 0)
146
145
        sa.un.sun_family = AF_UNIX;
147
146
        strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path));
148
147
 
149
 
        if ((syslog_fd = create_log_socket(SOCK_DGRAM)) < 0) {
150
 
                r = -errno;
 
148
        syslog_fd = create_log_socket(SOCK_DGRAM);
 
149
        if (syslog_fd < 0) {
 
150
                r = syslog_fd;
151
151
                goto fail;
152
152
        }
153
153
 
157
157
                /* Some legacy syslog systems still use stream
158
158
                 * sockets. They really shouldn't. But what can we
159
159
                 * do... */
160
 
                if ((syslog_fd = create_log_socket(SOCK_STREAM)) < 0) {
161
 
                        r = -errno;
 
160
                syslog_fd = create_log_socket(SOCK_STREAM);
 
161
                if (syslog_fd < 0) {
 
162
                        r = syslog_fd;
162
163
                        goto fail;
163
164
                }
164
165
 
181
182
        return r;
182
183
}
183
184
 
 
185
void log_close_journal(void) {
 
186
 
 
187
        if (journal_fd < 0)
 
188
                return;
 
189
 
 
190
        close_nointr_nofail(journal_fd);
 
191
        journal_fd = -1;
 
192
}
 
193
 
 
194
static int log_open_journal(void) {
 
195
        union sockaddr_union sa;
 
196
        int r;
 
197
 
 
198
        if (journal_fd >= 0)
 
199
                return 0;
 
200
 
 
201
        journal_fd = create_log_socket(SOCK_DGRAM);
 
202
        if (journal_fd < 0) {
 
203
                r = journal_fd;
 
204
                goto fail;
 
205
        }
 
206
 
 
207
        zero(sa);
 
208
        sa.un.sun_family = AF_UNIX;
 
209
        strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
 
210
 
 
211
        if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
 
212
                r = -errno;
 
213
                goto fail;
 
214
        }
 
215
 
 
216
        log_debug("Successfully opened journal for logging.");
 
217
 
 
218
        return 0;
 
219
 
 
220
fail:
 
221
        log_close_journal();
 
222
        log_debug("Failed to open journal for logging: %s", strerror(-r));
 
223
        return r;
 
224
}
 
225
 
184
226
int log_open(void) {
185
227
        int r;
186
228
 
191
233
         * because there is no reason to close it. */
192
234
 
193
235
        if (log_target == LOG_TARGET_NULL) {
 
236
                log_close_journal();
194
237
                log_close_syslog();
195
238
                log_close_console();
196
239
                return 0;
201
244
            isatty(STDERR_FILENO) <= 0) {
202
245
 
203
246
                if (log_target == LOG_TARGET_AUTO ||
204
 
                    log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
205
 
                    log_target == LOG_TARGET_SYSLOG)
206
 
                        if ((r = log_open_syslog()) >= 0) {
207
 
                                log_close_console();
208
 
                                return r;
209
 
                        }
 
247
                    log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
 
248
                    log_target == LOG_TARGET_JOURNAL) {
 
249
                        r = log_open_journal();
 
250
                        if (r >= 0) {
 
251
                                log_close_syslog();
 
252
                                log_close_console();
 
253
                                return r;
 
254
                        }
 
255
                }
 
256
 
 
257
                if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
 
258
                    log_target == LOG_TARGET_SYSLOG) {
 
259
                        r = log_open_syslog();
 
260
                        if (r >= 0) {
 
261
                                log_close_journal();
 
262
                                log_close_console();
 
263
                                return r;
 
264
                        }
 
265
                }
 
266
 
210
267
                if (log_target == LOG_TARGET_AUTO ||
 
268
                    log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
211
269
                    log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
212
 
                    log_target == LOG_TARGET_KMSG)
213
 
                        if ((r = log_open_kmsg()) >= 0) {
 
270
                    log_target == LOG_TARGET_KMSG) {
 
271
                        r = log_open_kmsg();
 
272
                        if (r >= 0) {
 
273
                                log_close_journal();
214
274
                                log_close_syslog();
215
275
                                log_close_console();
216
276
                                return r;
217
277
                        }
 
278
                }
218
279
        }
219
280
 
 
281
        log_close_journal();
220
282
        log_close_syslog();
221
283
 
222
284
        /* Get the real /dev/console if we are PID=1, hence reopen */
232
294
}
233
295
 
234
296
void log_close(void) {
235
 
        log_close_console();
 
297
        log_close_journal();
 
298
        log_close_syslog();
236
299
        log_close_kmsg();
237
 
        log_close_syslog();
 
300
        log_close_console();
 
301
}
 
302
 
 
303
void log_forget_fds(void) {
 
304
        console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
238
305
}
239
306
 
240
307
void log_set_max_level(int level) {
258
325
        if (console_fd < 0)
259
326
                return 0;
260
327
 
261
 
        snprintf(location, sizeof(location), "(%s:%u) ", file, line);
262
 
        char_array_0(location);
263
 
 
264
328
        highlight = LOG_PRI(level) <= LOG_ERR && show_color;
265
329
 
266
330
        zero(iovec);
267
 
        if (show_location)
 
331
 
 
332
        if (show_location) {
 
333
                snprintf(location, sizeof(location), "(%s:%u) ", file, line);
 
334
                char_array_0(location);
268
335
                IOVEC_SET_STRING(iovec[n++], location);
 
336
        }
 
337
 
269
338
        if (highlight)
270
 
                IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_ON);
 
339
                IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
271
340
        IOVEC_SET_STRING(iovec[n++], buffer);
272
341
        if (highlight)
273
342
                IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
326
395
        for (;;) {
327
396
                ssize_t n;
328
397
 
329
 
                if ((n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL)) < 0)
 
398
                n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
 
399
                if (n < 0)
330
400
                        return -errno;
331
401
 
332
402
                if (!syslog_is_stream ||
371
441
        return 1;
372
442
}
373
443
 
 
444
static int write_to_journal(
 
445
        int level,
 
446
        const char*file,
 
447
        int line,
 
448
        const char *func,
 
449
        const char *buffer) {
 
450
 
 
451
        char header[LINE_MAX];
 
452
        struct iovec iovec[3];
 
453
        struct msghdr mh;
 
454
 
 
455
        if (journal_fd < 0)
 
456
                return 0;
 
457
 
 
458
        snprintf(header, sizeof(header),
 
459
                 "PRIORITY=%i\n"
 
460
                 "CODE_FILE=%s\n"
 
461
                 "CODE_LINE=%i\n"
 
462
                 "CODE_FUNCTION=%s\n"
 
463
                 "MESSAGE=",
 
464
                 LOG_PRI(level),
 
465
                 file,
 
466
                 line,
 
467
                 func);
 
468
 
 
469
        char_array_0(header);
 
470
 
 
471
        zero(iovec);
 
472
        IOVEC_SET_STRING(iovec[0], header);
 
473
        IOVEC_SET_STRING(iovec[1], buffer);
 
474
        IOVEC_SET_STRING(iovec[2], "\n");
 
475
 
 
476
        zero(mh);
 
477
        mh.msg_iov = iovec;
 
478
        mh.msg_iovlen = ELEMENTSOF(iovec);
 
479
 
 
480
        if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
 
481
                return -errno;
 
482
 
 
483
        return 1;
 
484
}
 
485
 
374
486
static int log_dispatch(
375
487
        int level,
376
488
        const char*file,
400
512
                        *(e++) = 0;
401
513
 
402
514
                if (log_target == LOG_TARGET_AUTO ||
403
 
                    log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
 
515
                    log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
 
516
                    log_target == LOG_TARGET_JOURNAL) {
 
517
 
 
518
                        k = write_to_journal(level, file, line, func, buffer);
 
519
                        if (k < 0) {
 
520
                                if (k != -EAGAIN)
 
521
                                        log_close_journal();
 
522
                                log_open_kmsg();
 
523
                        } else if (k > 0)
 
524
                                r++;
 
525
                }
 
526
 
 
527
                if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
404
528
                    log_target == LOG_TARGET_SYSLOG) {
405
529
 
406
 
                        if ((k = write_to_syslog(level, file, line, func, buffer)) < 0) {
407
 
                                log_close_syslog();
 
530
                        k = write_to_syslog(level, file, line, func, buffer);
 
531
                        if (k < 0) {
 
532
                                if (k != -EAGAIN)
 
533
                                        log_close_syslog();
408
534
                                log_open_kmsg();
409
535
                        } else if (k > 0)
410
536
                                r++;
415
541
                     log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
416
542
                     log_target == LOG_TARGET_KMSG)) {
417
543
 
418
 
                        if ((k = write_to_kmsg(level, file, line, func, buffer)) < 0) {
 
544
                        k = write_to_kmsg(level, file, line, func, buffer);
 
545
                        if (k < 0) {
419
546
                                log_close_kmsg();
420
547
                                log_open_console();
421
548
                        } else if (k > 0)
422
549
                                r++;
423
550
                }
424
551
 
425
 
                if (k <= 0 &&
426
 
                    (k = write_to_console(level, file, line, func, buffer)) < 0)
427
 
                        return k;
 
552
                if (k <= 0) {
 
553
                        k = write_to_console(level, file, line, func, buffer);
 
554
                        if (k < 0)
 
555
                                return k;
 
556
                }
428
557
 
429
558
                buffer = e;
430
559
        } while (buffer);
453
582
        return r;
454
583
}
455
584
 
 
585
int log_metav(
 
586
        int level,
 
587
        const char*file,
 
588
        int line,
 
589
        const char *func,
 
590
        const char *format,
 
591
        va_list ap) {
 
592
 
 
593
        char buffer[LINE_MAX];
 
594
        int saved_errno, r;
 
595
 
 
596
        if (_likely_(LOG_PRI(level) > log_max_level))
 
597
                return 0;
 
598
 
 
599
        saved_errno = errno;
 
600
        vsnprintf(buffer, sizeof(buffer), format, ap);
 
601
        char_array_0(buffer);
 
602
 
 
603
        r = log_dispatch(level, file, line, func, buffer);
 
604
        errno = saved_errno;
 
605
 
 
606
        return r;
 
607
}
 
608
 
456
609
int log_meta(
457
610
        int level,
458
611
        const char*file,
460
613
        const char *func,
461
614
        const char *format, ...) {
462
615
 
463
 
        char buffer[LINE_MAX];
464
 
        int saved_errno, r;
 
616
        int r;
465
617
        va_list ap;
466
618
 
467
 
        if (_likely_(LOG_PRI(level) > log_max_level))
468
 
                return 0;
469
 
 
470
 
        saved_errno = errno;
471
 
 
472
619
        va_start(ap, format);
473
 
        vsnprintf(buffer, sizeof(buffer), format, ap);
 
620
        r = log_metav(level, file, line, func, format, ap);
474
621
        va_end(ap);
475
622
 
476
 
        char_array_0(buffer);
477
 
 
478
 
        r = log_dispatch(level, file, line, func, buffer);
479
 
        errno = saved_errno;
480
 
 
481
623
        return r;
482
624
}
483
625
 
484
 
void log_assert(
485
 
        const char*file,
486
 
        int line,
487
 
        const char *func,
488
 
        const char *format, ...) {
489
 
 
 
626
#pragma GCC diagnostic push
 
627
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
 
628
_noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) {
490
629
        static char buffer[LINE_MAX];
491
 
        int saved_errno = errno;
492
 
        va_list ap;
493
630
 
494
 
        va_start(ap, format);
495
 
        vsnprintf(buffer, sizeof(buffer), format, ap);
496
 
        va_end(ap);
 
631
        snprintf(buffer, sizeof(buffer), format, text, file, line, func);
497
632
 
498
633
        char_array_0(buffer);
499
634
        log_abort_msg = buffer;
500
635
 
501
636
        log_dispatch(LOG_CRIT, file, line, func, buffer);
502
637
        abort();
503
 
 
504
 
        /* If the user chose to ignore this SIGABRT, we are happy to go on, as if nothing happened. */
505
 
        errno = saved_errno;
 
638
}
 
639
#pragma GCC diagnostic pop
 
640
 
 
641
_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) {
 
642
        log_assert(text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
 
643
}
 
644
 
 
645
_noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
 
646
        log_assert(text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
506
647
}
507
648
 
508
649
int log_set_target_from_string(const char *e) {
509
650
        LogTarget t;
510
651
 
511
 
        if ((t = log_target_from_string(e)) < 0)
 
652
        t = log_target_from_string(e);
 
653
        if (t < 0)
512
654
                return -EINVAL;
513
655
 
514
656
        log_set_target(t);
518
660
int log_set_max_level_from_string(const char *e) {
519
661
        int t;
520
662
 
521
 
        if ((t = log_level_from_string(e)) < 0)
522
 
                return -EINVAL;
 
663
        t = log_level_from_string(e);
 
664
        if (t < 0)
 
665
                return t;
523
666
 
524
667
        log_set_max_level(t);
525
668
        return 0;
564
707
int log_show_color_from_string(const char *e) {
565
708
        int t;
566
709
 
567
 
        if ((t = parse_boolean(e)) < 0)
568
 
                return -EINVAL;
 
710
        t = parse_boolean(e);
 
711
        if (t < 0)
 
712
                return t;
569
713
 
570
714
        log_show_color(t);
571
715
        return 0;
574
718
int log_show_location_from_string(const char *e) {
575
719
        int t;
576
720
 
577
 
        if ((t = parse_boolean(e)) < 0)
578
 
                return -EINVAL;
 
721
        t = parse_boolean(e);
 
722
        if (t < 0)
 
723
                return t;
579
724
 
580
725
        log_show_location(t);
581
726
        return 0;
583
728
 
584
729
static const char *const log_target_table[] = {
585
730
        [LOG_TARGET_CONSOLE] = "console",
 
731
        [LOG_TARGET_KMSG] = "kmsg",
 
732
        [LOG_TARGET_JOURNAL] = "journal",
 
733
        [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
586
734
        [LOG_TARGET_SYSLOG] = "syslog",
587
 
        [LOG_TARGET_KMSG] = "kmsg",
588
735
        [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
589
 
        [LOG_TARGET_NULL] = "null",
590
 
        [LOG_TARGET_AUTO] = "auto"
 
736
        [LOG_TARGET_AUTO] = "auto",
 
737
        [LOG_TARGET_NULL] = "null"
591
738
};
592
739
 
593
740
DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);