Line data Source code
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 Lesser General Public License as published by
10 : the Free Software Foundation; either version 2.1 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 : Lesser General Public License for more details.
17 :
18 : You should have received a copy of the GNU Lesser General Public License
19 : along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 : ***/
21 :
22 : #include <time.h>
23 : #include <fcntl.h>
24 : #include <sys/socket.h>
25 :
26 : #include "fileio.h"
27 : #include "journald-server.h"
28 : #include "journald-console.h"
29 : #include "formats-util.h"
30 : #include "process-util.h"
31 : #include "terminal-util.h"
32 :
33 0 : static bool prefix_timestamp(void) {
34 :
35 : static int cached_printk_time = -1;
36 :
37 0 : if (_unlikely_(cached_printk_time < 0)) {
38 0 : _cleanup_free_ char *p = NULL;
39 :
40 0 : cached_printk_time =
41 0 : read_one_line_file("/sys/module/printk/parameters/time", &p) >= 0
42 0 : && parse_boolean(p) > 0;
43 : }
44 :
45 0 : return cached_printk_time;
46 : }
47 :
48 0 : void server_forward_console(
49 : Server *s,
50 : int priority,
51 : const char *identifier,
52 : const char *message,
53 : const struct ucred *ucred) {
54 :
55 : struct iovec iovec[5];
56 : struct timespec ts;
57 : char tbuf[sizeof("[] ")-1 + DECIMAL_STR_MAX(ts.tv_sec) + DECIMAL_STR_MAX(ts.tv_nsec)-3 + 1];
58 : char header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t)];
59 0 : int n = 0, fd;
60 0 : _cleanup_free_ char *ident_buf = NULL;
61 : const char *tty;
62 :
63 0 : assert(s);
64 0 : assert(message);
65 :
66 0 : if (LOG_PRI(priority) > s->max_level_console)
67 0 : return;
68 :
69 : /* First: timestamp */
70 0 : if (prefix_timestamp()) {
71 0 : assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
72 0 : xsprintf(tbuf, "[%5"PRI_TIME".%06ld] ",
73 : ts.tv_sec,
74 : ts.tv_nsec / 1000);
75 0 : IOVEC_SET_STRING(iovec[n++], tbuf);
76 : }
77 :
78 : /* Second: identifier and PID */
79 0 : if (ucred) {
80 0 : if (!identifier) {
81 0 : get_process_comm(ucred->pid, &ident_buf);
82 0 : identifier = ident_buf;
83 : }
84 :
85 0 : xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid);
86 :
87 0 : if (identifier)
88 0 : IOVEC_SET_STRING(iovec[n++], identifier);
89 :
90 0 : IOVEC_SET_STRING(iovec[n++], header_pid);
91 0 : } else if (identifier) {
92 0 : IOVEC_SET_STRING(iovec[n++], identifier);
93 0 : IOVEC_SET_STRING(iovec[n++], ": ");
94 : }
95 :
96 : /* Fourth: message */
97 0 : IOVEC_SET_STRING(iovec[n++], message);
98 0 : IOVEC_SET_STRING(iovec[n++], "\n");
99 :
100 0 : tty = s->tty_path ? s->tty_path : "/dev/console";
101 :
102 0 : fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC);
103 0 : if (fd < 0) {
104 0 : log_debug_errno(errno, "Failed to open %s for logging: %m", tty);
105 0 : return;
106 : }
107 :
108 0 : if (writev(fd, iovec, n) < 0)
109 0 : log_debug_errno(errno, "Failed to write to %s for logging: %m", tty);
110 :
111 0 : safe_close(fd);
112 : }
|