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