pretty-print: fix handling of line continuation in cat_file() (#35886)
Fixes #35878.
This commit is contained in:
+60
-54
@@ -183,34 +183,20 @@ int terminal_urlify_man(const char *page, const char *section, char **ret) {
|
||||
return terminal_urlify(url, text, ret);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
LINE_SECTION,
|
||||
LINE_COMMENT,
|
||||
LINE_NORMAL,
|
||||
} LineType;
|
||||
|
||||
static LineType classify_line_type(const char *line, CatFlags flags) {
|
||||
const char *t = skip_leading_chars(line, WHITESPACE);
|
||||
|
||||
if ((flags & CAT_FORMAT_HAS_SECTIONS) && *t == '[')
|
||||
return LINE_SECTION;
|
||||
if (IN_SET(*t, '#', ';', '\0'))
|
||||
return LINE_COMMENT;
|
||||
return LINE_NORMAL;
|
||||
}
|
||||
|
||||
static int cat_file(const char *filename, bool newline, CatFlags flags) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *urlified = NULL, *section = NULL, *old_section = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
|
||||
f = fopen(filename, "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
return log_error_errno(errno, "Failed to open \"%s\": %m", filename);
|
||||
|
||||
r = terminal_urlify_path(filename, NULL, &urlified);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_error_errno(r, "Failed to urlify path \"%s\": %m", filename);
|
||||
|
||||
printf("%s%s# %s%s\n",
|
||||
newline ? "\n" : "",
|
||||
@@ -219,7 +205,7 @@ static int cat_file(const char *filename, bool newline, CatFlags flags) {
|
||||
ansi_normal());
|
||||
fflush(stdout);
|
||||
|
||||
for (;;) {
|
||||
for (bool continued = false;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
@@ -228,58 +214,78 @@ static int cat_file(const char *filename, bool newline, CatFlags flags) {
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
LineType line_type = classify_line_type(line, flags);
|
||||
if (FLAGS_SET(flags, CAT_TLDR)) {
|
||||
if (line_type == LINE_SECTION) {
|
||||
/* The start of a section, let's not print it yet. */
|
||||
const char *l = skip_leading_chars(line, WHITESPACE);
|
||||
|
||||
/* comment */
|
||||
if (*l != '\0' && strchr(COMMENTS, *l)) {
|
||||
if (!FLAGS_SET(flags, CAT_TLDR))
|
||||
printf("%s%s%s\n", ansi_highlight_grey(), line, ansi_normal());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* empty line */
|
||||
if (FLAGS_SET(flags, CAT_TLDR) && (isempty(l) || streq(l, "\\")))
|
||||
continue;
|
||||
|
||||
/* section */
|
||||
if (FLAGS_SET(flags, CAT_FORMAT_HAS_SECTIONS) && *l == '[' && !continued) {
|
||||
if (FLAGS_SET(flags, CAT_TLDR))
|
||||
/* On TLDR, let's not print it yet. */
|
||||
free_and_replace(section, line);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
printf("%s%s%s\n", ansi_highlight_cyan(), line, ansi_normal());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line_type == LINE_COMMENT)
|
||||
continue;
|
||||
/* normal line */
|
||||
|
||||
/* Before we print the actual line, print the last section header */
|
||||
if (section) {
|
||||
/* Do not print redundant section headers */
|
||||
if (!streq_ptr(section, old_section))
|
||||
printf("%s%s%s\n",
|
||||
ansi_highlight_cyan(),
|
||||
section,
|
||||
ansi_normal());
|
||||
/* Before we print the line, print the last section header. */
|
||||
if (FLAGS_SET(flags, CAT_TLDR) && section) {
|
||||
/* Do not print redundant section headers */
|
||||
if (!streq_ptr(section, old_section))
|
||||
printf("%s%s%s\n", ansi_highlight_cyan(), section, ansi_normal());
|
||||
|
||||
free_and_replace(old_section, section);
|
||||
}
|
||||
free_and_replace(old_section, section);
|
||||
}
|
||||
|
||||
/* Check if the line ends with a backslash. */
|
||||
bool escaped = false;
|
||||
char *e;
|
||||
for (e = line; *e != '\0'; e++) {
|
||||
if (escaped)
|
||||
escaped = false;
|
||||
else if (*e == '\\')
|
||||
escaped = true;
|
||||
}
|
||||
|
||||
/* Highlight the trailing backslash. */
|
||||
if (escaped) {
|
||||
assert(e > line);
|
||||
*(e-1) = '\0';
|
||||
|
||||
if (!strextend(&line, ansi_highlight_red(), "\\", ansi_normal()))
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
/* Highlight the left side (directive) of a Foo=bar assignment */
|
||||
if (FLAGS_SET(flags, CAT_FORMAT_HAS_SECTIONS) && line_type == LINE_NORMAL) {
|
||||
if (FLAGS_SET(flags, CAT_FORMAT_HAS_SECTIONS) && !continued) {
|
||||
const char *p = strchr(line, '=');
|
||||
if (p) {
|
||||
_cleanup_free_ char *highlighted = NULL, *directive = NULL;
|
||||
_cleanup_free_ char *directive = NULL;
|
||||
|
||||
directive = strndup(line, p - line);
|
||||
if (!directive)
|
||||
return log_oom();
|
||||
|
||||
highlighted = strjoin(ansi_highlight_green(),
|
||||
directive,
|
||||
"=",
|
||||
ansi_normal(),
|
||||
p + 1);
|
||||
if (!highlighted)
|
||||
return log_oom();
|
||||
|
||||
free_and_replace(line, highlighted);
|
||||
printf("%s%s=%s%s\n", ansi_highlight_green(), directive, ansi_normal(), p + 1);
|
||||
continued = escaped;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s%s%s\n",
|
||||
line_type == LINE_SECTION ? ansi_highlight_cyan() :
|
||||
line_type == LINE_COMMENT ? ansi_highlight_grey() :
|
||||
"",
|
||||
line,
|
||||
line_type != LINE_NORMAL ? ansi_normal() : "");
|
||||
/* Otherwise, print the line as is. */
|
||||
printf("%s\n", line);
|
||||
continued = escaped;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -202,6 +202,105 @@ systemd-analyze cat-config --tldr /etc/systemd/system.conf >/dev/null
|
||||
systemd-analyze cat-config --tldr systemd/system.conf systemd/journald.conf >/dev/null
|
||||
systemd-analyze cat-config --tldr systemd/system.conf foo/bar systemd/journald.conf >/dev/null
|
||||
systemd-analyze cat-config --tldr foo/bar
|
||||
mkdir -p /run/test-analyze-cat-config/main.conf.d
|
||||
cat >/run/test-analyze-cat-config/main.conf <<EOF
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free
|
||||
# Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Entries in this file show the compile time defaults. Local configuration
|
||||
# should be created by either modifying this file (or a copy of it placed in
|
||||
# /etc/ if the original file is shipped in /usr/), or by creating "drop-ins" in
|
||||
# the /etc/systemd/networkd.conf.d/ directory. The latter is generally
|
||||
# recommended. Defaults can be restored by simply deleting the main
|
||||
# configuration file and all drop-ins located in /etc/.
|
||||
#
|
||||
# Use 'systemd-analyze cat-config systemd/networkd.conf' to display the full config.
|
||||
#
|
||||
# See networkd.conf(5) for details.
|
||||
|
||||
[Network]
|
||||
#SpeedMeter=no
|
||||
#SpeedMeterIntervalSec=10sec
|
||||
#ManageForeignRoutingPolicyRules=yes
|
||||
#ManageForeignRoutes=yes
|
||||
#ManageForeignNextHops=yes
|
||||
#RouteTable=
|
||||
#IPv4Forwarding=
|
||||
#IPv6Forwarding=
|
||||
#IPv6PrivacyExtensions=no
|
||||
#UseDomains=no
|
||||
|
||||
#[IPv6AddressLabel]
|
||||
#Prefix=
|
||||
#Label=
|
||||
|
||||
[IPv6AcceptRA]
|
||||
#UseDomains=
|
||||
|
||||
[DHCPv4]
|
||||
ClientIdentifier=duid
|
||||
#DUIDType=vendor
|
||||
#DUIDRawData=
|
||||
#UseDomains=
|
||||
|
||||
[DHCPv6]
|
||||
#DUIDType=vendor
|
||||
#DUIDRawData=
|
||||
#UseDomains=
|
||||
|
||||
[DHCPServer]
|
||||
PersistLeases=yes
|
||||
EOF
|
||||
cat >/run/test-analyze-cat-config/main.conf.d/override.conf <<EOF
|
||||
[DHCPServer]
|
||||
PersistLeases=no
|
||||
|
||||
[Network]
|
||||
[Network]
|
||||
[Network]
|
||||
SpeedMeter=yes
|
||||
|
||||
Continuation=foo \\
|
||||
bar \\
|
||||
# comment
|
||||
hogehoge \\
|
||||
\\
|
||||
aaa \\
|
||||
|
||||
|
||||
bbb
|
||||
AAAA=bbbb
|
||||
EOF
|
||||
diff -u <(echo '# /run/test-analyze-cat-config/main.conf'
|
||||
cat /run/test-analyze-cat-config/main.conf
|
||||
echo
|
||||
echo '# /run/test-analyze-cat-config/main.conf.d/override.conf'
|
||||
cat /run/test-analyze-cat-config/main.conf.d/override.conf) \
|
||||
<(systemd-analyze cat-config test-analyze-cat-config/main.conf)
|
||||
diff -u - <<EOF <(systemd-analyze --tldr cat-config test-analyze-cat-config/main.conf)
|
||||
# /run/test-analyze-cat-config/main.conf
|
||||
[DHCPv4]
|
||||
ClientIdentifier=duid
|
||||
[DHCPServer]
|
||||
PersistLeases=yes
|
||||
|
||||
# /run/test-analyze-cat-config/main.conf.d/override.conf
|
||||
[DHCPServer]
|
||||
PersistLeases=no
|
||||
[Network]
|
||||
SpeedMeter=yes
|
||||
Continuation=foo \\
|
||||
bar \\
|
||||
hogehoge \\
|
||||
aaa \\
|
||||
bbb
|
||||
AAAA=bbbb
|
||||
EOF
|
||||
rm -rf /run/test-analyze-cat-config
|
||||
(! systemd-analyze cat-config --global systemd/system.conf)
|
||||
# security
|
||||
systemd-analyze security
|
||||
|
||||
Reference in New Issue
Block a user