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