]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/show-status.c
pkgconfig: define variables relative to ${prefix}/${rootprefix}/${sysconfdir}
[thirdparty/systemd.git] / src / core / show-status.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "alloc-util.h"
4 #include "fd-util.h"
5 #include "io-util.h"
6 #include "parse-util.h"
7 #include "show-status.h"
8 #include "string-table.h"
9 #include "string-util.h"
10 #include "terminal-util.h"
11 #include "util.h"
12
13 static const char* const show_status_table[_SHOW_STATUS_MAX] = {
14 [SHOW_STATUS_NO] = "no",
15 [SHOW_STATUS_AUTO] = "auto",
16 [SHOW_STATUS_TEMPORARY] = "temporary",
17 [SHOW_STATUS_YES] = "yes",
18 };
19
20 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(show_status, ShowStatus, SHOW_STATUS_YES);
21
22 int parse_show_status(const char *v, ShowStatus *ret) {
23 ShowStatus s;
24
25 assert(ret);
26
27 s = show_status_from_string(v);
28 if (s < 0 || s == SHOW_STATUS_TEMPORARY)
29 return -EINVAL;
30
31 *ret = s;
32 return 0;
33 }
34
35 int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
36 static const char status_indent[] = " "; /* "[" STATUS "] " */
37 _cleanup_free_ char *s = NULL;
38 _cleanup_close_ int fd = -1;
39 struct iovec iovec[7] = {};
40 int n = 0;
41 static bool prev_ephemeral;
42
43 assert(format);
44
45 /* This is independent of logging, as status messages are
46 * optional and go exclusively to the console. */
47
48 if (vasprintf(&s, format, ap) < 0)
49 return log_oom();
50
51 /* Before you ask: yes, on purpose we open/close the console for each status line we write individually. This
52 * is a good strategy to avoid PID 1 getting killed by the kernel's SAK concept (it doesn't fix this entirely,
53 * but minimizes the time window the kernel might end up killing PID 1 due to SAK). It also makes things easier
54 * for us so that we don't have to recover from hangups and suchlike triggered on the console. */
55
56 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
57 if (fd < 0)
58 return fd;
59
60 if (ellipse) {
61 char *e;
62 size_t emax, sl;
63 int c;
64
65 c = fd_columns(fd);
66 if (c <= 0)
67 c = 80;
68
69 sl = status ? sizeof(status_indent)-1 : 0;
70
71 emax = c - sl - 1;
72 if (emax < 3)
73 emax = 3;
74
75 e = ellipsize(s, emax, 50);
76 if (e) {
77 free(s);
78 s = e;
79 }
80 }
81
82 if (prev_ephemeral)
83 iovec[n++] = IOVEC_MAKE_STRING(ANSI_REVERSE_LINEFEED "\r" ANSI_ERASE_TO_END_OF_LINE);
84
85 if (status) {
86 if (!isempty(status)) {
87 iovec[n++] = IOVEC_MAKE_STRING("[");
88 iovec[n++] = IOVEC_MAKE_STRING(status);
89 iovec[n++] = IOVEC_MAKE_STRING("] ");
90 } else
91 iovec[n++] = IOVEC_MAKE_STRING(status_indent);
92 }
93
94 iovec[n++] = IOVEC_MAKE_STRING(s);
95 iovec[n++] = IOVEC_MAKE_STRING("\n");
96
97 if (prev_ephemeral && !ephemeral)
98 iovec[n++] = IOVEC_MAKE_STRING(ANSI_ERASE_TO_END_OF_LINE);
99 prev_ephemeral = ephemeral;
100
101 if (writev(fd, iovec, n) < 0)
102 return -errno;
103
104 return 0;
105 }
106
107 int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
108 va_list ap;
109 int r;
110
111 assert(format);
112
113 va_start(ap, format);
114 r = status_vprintf(status, ellipse, ephemeral, format, ap);
115 va_end(ap);
116
117 return r;
118 }