]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/show-status.c
core: rework how we track service and scope PIDs
[thirdparty/systemd.git] / src / core / show-status.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
15bd9a28
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2014 Lennart Poettering
15bd9a28
LP
6***/
7
b5efdb8a 8#include "alloc-util.h"
8b43440b 9#include "fd-util.h"
afc5dbf3 10#include "io-util.h"
6bedfcbb
LP
11#include "parse-util.h"
12#include "show-status.h"
07630cea 13#include "string-util.h"
8b43440b 14#include "terminal-util.h"
15bd9a28
LP
15#include "util.h"
16
17int 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}
b8faf2ec
LP
35
36int 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
8ae2c630
LP
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
b8faf2ec
LP
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)
e6a7ec4b 84 iovec[n++] = IOVEC_MAKE_STRING("\r" ANSI_ERASE_TO_END_OF_LINE);
b8faf2ec
LP
85 prev_ephemeral = ephemeral;
86
87 if (status) {
88 if (!isempty(status)) {
e6a7ec4b
LP
89 iovec[n++] = IOVEC_MAKE_STRING("[");
90 iovec[n++] = IOVEC_MAKE_STRING(status);
91 iovec[n++] = IOVEC_MAKE_STRING("] ");
b8faf2ec 92 } else
e6a7ec4b 93 iovec[n++] = IOVEC_MAKE_STRING(status_indent);
b8faf2ec
LP
94 }
95
e6a7ec4b 96 iovec[n++] = IOVEC_MAKE_STRING(s);
b8faf2ec 97 if (!ephemeral)
e6a7ec4b 98 iovec[n++] = IOVEC_MAKE_STRING("\n");
b8faf2ec
LP
99
100 if (writev(fd, iovec, n) < 0)
101 return -errno;
102
103 return 0;
104}
105
106int 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}