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