From 80788a0bd49d9992820b37096d59a69f82e80166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 14 Oct 2023 17:36:01 +0200 Subject: [PATCH 1/8] shared/pretty-print: drop unused flag 0895e87348e5fc02f50498cad5922eb3eb172323 removed the last (only?) use of CAT_MAIN_FILE_OPTIONAL, except for tests. All callers first check if the main file exists on their own, so this code was effectively dead. I want to repopulate the enum in later commits, so a dummy flag is added to allow the code to compile. --- src/shared/pretty-print.c | 7 +------ src/shared/pretty-print.h | 2 +- src/test/test-pretty-print.c | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index a354ae4983..55a2570ddf 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -171,12 +171,7 @@ int cat_files(const char *file, char **dropins, CatFlags flags) { if (file) { r = cat_file(file, false); - if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL)) - printf("%s# Configuration file %s not found%s\n", - ansi_highlight_magenta(), - file, - ansi_normal()); - else if (r < 0) + if (r < 0) return log_warning_errno(r, "Failed to cat %s: %m", file); } diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h index 45644da67d..0012dc8835 100644 --- a/src/shared/pretty-print.h +++ b/src/shared/pretty-print.h @@ -15,7 +15,7 @@ int terminal_urlify_path(const char *path, const char *text, char **ret); int terminal_urlify_man(const char *page, const char *section, char **ret); typedef enum CatFlags { - CAT_FLAGS_MAIN_FILE_OPTIONAL = 1 << 0, + CAT_DUMMY_FLAG, // This flag only exists a as a placeholder because empty enums are not allowed } CatFlags; int cat_files(const char *file, char **dropins, CatFlags flags); diff --git a/src/test/test-pretty-print.c b/src/test/test-pretty-print.c index 7c6c6c7ad1..ece1a161e4 100644 --- a/src/test/test-pretty-print.c +++ b/src/test/test-pretty-print.c @@ -25,7 +25,7 @@ TEST(terminal_urlify) { TEST(cat_files) { assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT); - assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0); + assert_se(cat_files(NULL, NULL, 0) == 0); if (access("/etc/fstab", R_OK) >= 0) assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0); From 063c8382068b4cb8661aa5a77b6c7d117d0bd117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 12 Oct 2023 16:33:01 +0200 Subject: [PATCH 2/8] analyze/cat-config: add switch to print only "interesting" parts of config files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When looking at configuration, often a user wants to suppress the comments and just look at the parts that actually configure something, roughly equivalent to systemd-analyze cat-config … | rg -v '^(#|;|$) This switch implements this natively, skipping lines that start with a comment character or only contain whitespace. For formats that have section headers, section headers are skipped, if only followed by stuff that would be skipped. (The last section header is printed when we're about to print some actual output.) Note that the caller doesn't know if the format has headers or not. We do format type detection in pretty-print.c. So the caller only specifies tldr=true|false, and conf_files_cat() figures out if the format has headers and whether those should be handled specially. The comments that show the file name are always printed, even if all of the file is suppressed. This is a partial answer to the discussions in https://github.com/systemd/systemd/pull/28919, https://github.com/systemd/systemd/pull/29248. If the default config is shown in config files, the user can conveniently use '--tldr' to show the relevant parts. --- man/systemd-analyze.xml | 10 ++++++++ src/analyze/analyze-cat-config.c | 2 +- src/analyze/analyze.c | 8 +++++++ src/analyze/analyze.h | 2 ++ src/binfmt/binfmt.c | 2 +- src/machine/machinectl.c | 4 ++-- src/network/networkctl.c | 2 +- src/shared/pretty-print.c | 39 ++++++++++++++++++++++++++------ src/shared/pretty-print.h | 5 ++-- src/sysctl/sysctl.c | 2 +- src/systemctl/systemctl-edit.c | 2 +- src/sysusers/sysusers.c | 2 +- test/units/testsuite-65.sh | 5 ++++ 13 files changed, 68 insertions(+), 17 deletions(-) diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index d3a1de9a91..5b7f22c87c 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -1470,6 +1470,16 @@ NR NAME SHA256 + + + + With cat-config, only print the "interesting" parts of the + configuration files, skipping comments and empty lines and section headers followed only by + comments and empty lines. + + + + diff --git a/src/analyze/analyze-cat-config.c b/src/analyze/analyze-cat-config.c index 08184cedfe..66bbbc1102 100644 --- a/src/analyze/analyze-cat-config.c +++ b/src/analyze/analyze-cat-config.c @@ -35,7 +35,7 @@ int verb_cat_config(int argc, char *argv[], void *userdata) { } else t = *arg; - r = conf_files_cat(arg_root, t); + r = conf_files_cat(arg_root, t, arg_cat_flags); if (r < 0) return r; } diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index b7c852a08c..1b96e8b69a 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -91,6 +91,7 @@ DotMode arg_dot = DEP_ALL; char **arg_dot_from_patterns = NULL, **arg_dot_to_patterns = NULL; usec_t arg_fuzz = 0; PagerFlags arg_pager_flags = 0; +CatFlags arg_cat_flags = 0; BusTransport arg_transport = BUS_TRANSPORT_LOCAL; const char *arg_host = NULL; RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; @@ -270,6 +271,7 @@ static int help(int argc, char *argv[], void *userdata) { " -h --help Show this help\n" " --version Show package version\n" " -q --quiet Do not emit hints\n" + " --tldr Skip comments and empty lines\n" " --root=PATH Operate on an alternate filesystem root\n" " --image=PATH Operate on disk image as filesystem root\n" " --image-policy=POLICY Specify disk image dissection policy\n" @@ -313,6 +315,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_PROFILE, ARG_TABLE, ARG_NO_LEGEND, + ARG_TLDR, }; static const struct option options[] = { @@ -346,6 +349,7 @@ static int parse_argv(int argc, char *argv[]) { { "profile", required_argument, NULL, ARG_PROFILE }, { "table", optional_argument, NULL, ARG_TABLE }, { "no-legend", optional_argument, NULL, ARG_NO_LEGEND }, + { "tldr", no_argument, NULL, ARG_TLDR }, {} }; @@ -535,6 +539,10 @@ static int parse_argv(int argc, char *argv[]) { arg_legend = false; break; + case ARG_TLDR: + arg_cat_flags = CAT_TLDR; + break; + case '?': return -EINVAL; diff --git a/src/analyze/analyze.h b/src/analyze/analyze.h index 84575cd9a9..8a9528c0d3 100644 --- a/src/analyze/analyze.h +++ b/src/analyze/analyze.h @@ -7,6 +7,7 @@ #include "bus-util.h" #include "json.h" #include "pager.h" +#include "pretty-print.h" #include "time-util.h" #include "unit-file.h" @@ -20,6 +21,7 @@ extern DotMode arg_dot; extern char **arg_dot_from_patterns, **arg_dot_to_patterns; extern usec_t arg_fuzz; extern PagerFlags arg_pager_flags; +extern CatFlags arg_cat_flags; extern BusTransport arg_transport; extern const char *arg_host; extern RuntimeScope arg_runtime_scope; diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 675ae185e2..fa3d6b0e26 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -232,7 +232,7 @@ static int run(int argc, char *argv[]) { if (arg_cat_config) { pager_open(arg_pager_flags); - return cat_files(NULL, files, 0); + return cat_files(NULL, files, /* flags= */ 0); } r = binfmt_mounted_warn(); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 9b6a6cebda..e8e0c3299a 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1537,7 +1537,7 @@ static int cat_settings(int argc, char *argv[], void *userdata) { "Invalid settings file path '%s'.", *name); - q = cat_files(*name, /* dropins = */ NULL, /* flags = */ 0); + q = cat_files(*name, /* dropins = */ NULL, /* flags = */ CAT_FORMAT_HAS_SECTIONS); if (q < 0) return r < 0 ? r : q; continue; @@ -1558,7 +1558,7 @@ static int cat_settings(int argc, char *argv[], void *userdata) { return r < 0 ? r : q; } - q = cat_files(path, /* dropins = */ NULL, /* flags = */ 0); + q = cat_files(path, /* dropins = */ NULL, /* flags = */ CAT_FORMAT_HAS_SECTIONS); if (q < 0) return r < 0 ? r : q; } diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 5d961b6c83..48b0f2eca0 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -3298,7 +3298,7 @@ static int verb_cat(int argc, char *argv[], void *userdata) { } } - r = cat_files(path, dropins, /* flags = */ 0); + r = cat_files(path, dropins, /* flags = */ CAT_FORMAT_HAS_SECTIONS); if (r < 0) return ret < 0 ? ret : r; } diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index 55a2570ddf..ae5b9d8604 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -131,9 +131,9 @@ int terminal_urlify_man(const char *page, const char *section, char **ret) { return terminal_urlify(url, text, ret); } -static int cat_file(const char *filename, bool newline) { +static int cat_file(const char *filename, bool newline, CatFlags flags) { _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *urlified = NULL; + _cleanup_free_ char *urlified = NULL, *section = NULL; int r; f = fopen(filename, "re"); @@ -160,6 +160,25 @@ static int cat_file(const char *filename, bool newline) { if (r == 0) break; + if (flags & CAT_TLDR) { + const char *t = skip_leading_chars(line, WHITESPACE); + + if ((flags & CAT_FORMAT_HAS_SECTIONS) && *t == '[') { + /* The start of a section, let's not print it yet. */ + free_and_replace(section, line); + continue; + } + + if (IN_SET(*t, '#', ';', '\0')) + continue; + + /* Before we print the actual line, print the last section header */ + if (section) { + puts(section); + section = mfree(section); + } + } + puts(line); } @@ -170,13 +189,13 @@ int cat_files(const char *file, char **dropins, CatFlags flags) { int r; if (file) { - r = cat_file(file, false); + r = cat_file(file, /* newline= */ false, flags); if (r < 0) return log_warning_errno(r, "Failed to cat %s: %m", file); } STRV_FOREACH(path, dropins) { - r = cat_file(*path, file || path != dropins); + r = cat_file(*path, /* newline= */ file || path != dropins, flags); if (r < 0) return log_warning_errno(r, "Failed to cat %s: %m", *path); } @@ -208,7 +227,10 @@ void print_separator(void) { static int guess_type(const char **name, char ***prefixes, bool *is_collection, const char **extension) { /* Try to figure out if name is like tmpfiles.d/ or systemd/system-presets/, - * i.e. a collection of directories without a main config file. */ + * i.e. a collection of directories without a main config file. + * Incidentally, all those formats don't use sections. So we return a single + * is_collection boolean, which also means that the format doesn't use sections. + */ _cleanup_free_ char *n = NULL; bool usr = false, run = false, coll = false; @@ -274,7 +296,7 @@ static int guess_type(const char **name, char ***prefixes, bool *is_collection, return 0; } -int conf_files_cat(const char *root, const char *name) { +int conf_files_cat(const char *root, const char *name, CatFlags flags) { _cleanup_strv_free_ char **dirs = NULL, **files = NULL; _cleanup_free_ char *path = NULL; char **prefixes = NULL; /* explicit initialization to appease gcc */ @@ -330,5 +352,8 @@ int conf_files_cat(const char *root, const char *name) { return log_error_errno(r, "Failed to query file list: %m"); /* Show */ - return cat_files(path, files, 0); + if (is_collection) + flags |= CAT_FORMAT_HAS_SECTIONS; + + return cat_files(path, files, flags); } diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h index 0012dc8835..aef74cac2f 100644 --- a/src/shared/pretty-print.h +++ b/src/shared/pretty-print.h @@ -15,11 +15,12 @@ int terminal_urlify_path(const char *path, const char *text, char **ret); int terminal_urlify_man(const char *page, const char *section, char **ret); typedef enum CatFlags { - CAT_DUMMY_FLAG, // This flag only exists a as a placeholder because empty enums are not allowed + CAT_FORMAT_HAS_SECTIONS = 1 << 0, /* Sections are meaningful for this file format */ + CAT_TLDR = 1 << 1, /* Only print comments and relevant section headers */ } CatFlags; int cat_files(const char *file, char **dropins, CatFlags flags); -int conf_files_cat(const char *root, const char *name); +int conf_files_cat(const char *root, const char *name, CatFlags flags); #define RED_CROSS_MARK_MAX (STRLEN(ANSI_HIGHLIGHT_RED) + STRLEN("✗") + STRLEN(ANSI_NORMAL) + 1) #define GREEN_CHECK_MARK_MAX (STRLEN(ANSI_HIGHLIGHT_GREEN) + STRLEN("✓") + STRLEN(ANSI_NORMAL) + 1) diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index ca41f02fdd..bf078ac6e1 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -464,7 +464,7 @@ static int run(int argc, char *argv[]) { if (arg_cat_config) { pager_open(arg_pager_flags); - return cat_files(NULL, files, 0); + return cat_files(NULL, files, /* flags= */ 0); } STRV_FOREACH(f, files) diff --git a/src/systemctl/systemctl-edit.c b/src/systemctl/systemctl-edit.c index ac0bbb4542..367afa20f7 100644 --- a/src/systemctl/systemctl-edit.c +++ b/src/systemctl/systemctl-edit.c @@ -93,7 +93,7 @@ int verb_cat(int argc, char *argv[], void *userdata) { arg_runtime_scope == RUNTIME_SCOPE_SYSTEM ? "" : " --user", ansi_normal()); - r = cat_files(fragment_path, dropin_paths, 0); + r = cat_files(fragment_path, dropin_paths, /* flags= */ CAT_FORMAT_HAS_SECTIONS); if (r < 0) return r; } diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 0fcbf261c1..d996583cbd 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -2044,7 +2044,7 @@ static int cat_config(void) { pager_open(arg_pager_flags); - return cat_files(NULL, files, 0); + return cat_files(NULL, files, /* flags= */ 0); } static int help(void) { diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh index 66db42d759..9bd2c0b3bd 100755 --- a/test/units/testsuite-65.sh +++ b/test/units/testsuite-65.sh @@ -165,6 +165,11 @@ systemd-analyze cat-config /etc/systemd/system.conf >/dev/null systemd-analyze cat-config systemd/system.conf systemd/journald.conf >/dev/null systemd-analyze cat-config systemd/system.conf foo/bar systemd/journald.conf >/dev/null systemd-analyze cat-config foo/bar +systemd-analyze cat-config --tldr systemd/system.conf >/dev/null +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 # security systemd-analyze security systemd-analyze security --json=off From a9e680358219377645fe5fd203432f63b98e0887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 14 Oct 2023 18:49:35 +0200 Subject: [PATCH 3/8] shared/pretty-print: add highlighting --- src/shared/pretty-print.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index ae5b9d8604..1544b422da 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -131,6 +131,22 @@ 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; @@ -160,26 +176,33 @@ 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 & CAT_TLDR) { - const char *t = skip_leading_chars(line, WHITESPACE); - - if ((flags & CAT_FORMAT_HAS_SECTIONS) && *t == '[') { + if (line_type == LINE_SECTION) { /* The start of a section, let's not print it yet. */ free_and_replace(section, line); continue; } - if (IN_SET(*t, '#', ';', '\0')) + if (line_type == LINE_COMMENT) continue; /* Before we print the actual line, print the last section header */ if (section) { - puts(section); + printf("%s%s%s\n", + ansi_highlight_cyan(), + section, + ansi_normal()); section = mfree(section); } } - puts(line); + 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() : ""); } return 0; From 1be6a5db21bfc785e201f32d56765d408428644e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 15 Oct 2023 18:33:10 +0200 Subject: [PATCH 4/8] tmpfiles: add --tldr This is like --cat-config, but omits the comments and empty lines. The name is incoungrous with --cat-config, but I don't see a nice way to call it that wouldn't be annoyingly long. pager_open() is moved to cat_config() to remove some lines from run(). --- man/standard-options.xml | 10 ++++++++++ man/systemd-tmpfiles.xml | 1 + src/shared/pretty-print.h | 6 ++++-- src/tmpfiles/tmpfiles.c | 30 ++++++++++++++++++------------ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/man/standard-options.xml b/man/standard-options.xml index 75e91862f4..eb27f5cb65 100644 --- a/man/standard-options.xml +++ b/man/standard-options.xml @@ -74,6 +74,16 @@ + + + + + Copy the contents of config files to standard output. Only the "interesting" parts of the + configuration files are printed, comments and empty lines are skipped. Before each file, the filename + is printed as a comment. + + + MODE diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml index c048927882..95e1e2951c 100644 --- a/man/systemd-tmpfiles.xml +++ b/man/systemd-tmpfiles.xml @@ -250,6 +250,7 @@ + diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h index aef74cac2f..b25684aaa6 100644 --- a/src/shared/pretty-print.h +++ b/src/shared/pretty-print.h @@ -15,8 +15,10 @@ int terminal_urlify_path(const char *path, const char *text, char **ret); int terminal_urlify_man(const char *page, const char *section, char **ret); typedef enum CatFlags { - CAT_FORMAT_HAS_SECTIONS = 1 << 0, /* Sections are meaningful for this file format */ - CAT_TLDR = 1 << 1, /* Only print comments and relevant section headers */ + CAT_CONFIG_OFF = 0, + CAT_CONFIG_ON = 1 << 0, + CAT_FORMAT_HAS_SECTIONS = 1 << 1, /* Sections are meaningful for this file format */ + CAT_TLDR = 1 << 2, /* Only print comments and relevant section headers */ } CatFlags; int cat_files(const char *file, char **dropins, CatFlags flags); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index aab65f49d1..818d3517e0 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -196,7 +196,7 @@ typedef enum { _CREATION_MODE_INVALID = -EINVAL, } CreationMode; -static bool arg_cat_config = false; +static CatFlags arg_cat_flags = CAT_CONFIG_OFF; static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; static OperationMask arg_operation = 0; static bool arg_boot = false; @@ -3936,7 +3936,9 @@ static int cat_config(char **config_dirs, char **args) { if (r < 0) return r; - return cat_files(NULL, files, 0); + pager_open(arg_pager_flags); + + return cat_files(NULL, files, arg_cat_flags); } static int exclude_default_prefixes(void) { @@ -3974,6 +3976,7 @@ static int help(void) { " --user Execute user configuration\n" " --version Show package version\n" " --cat-config Show configuration files\n" + " --tldr Show non-comment parts of configuration\n" " --create Create marked files/directories\n" " --clean Clean up marked directories\n" " --remove Remove marked files/directories\n" @@ -4001,6 +4004,7 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_CAT_CONFIG, + ARG_TLDR, ARG_USER, ARG_CREATE, ARG_CLEAN, @@ -4021,6 +4025,7 @@ static int parse_argv(int argc, char *argv[]) { { "user", no_argument, NULL, ARG_USER }, { "version", no_argument, NULL, ARG_VERSION }, { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "tldr", no_argument, NULL, ARG_TLDR }, { "create", no_argument, NULL, ARG_CREATE }, { "clean", no_argument, NULL, ARG_CLEAN }, { "remove", no_argument, NULL, ARG_REMOVE }, @@ -4052,7 +4057,11 @@ static int parse_argv(int argc, char *argv[]) { return version(); case ARG_CAT_CONFIG: - arg_cat_config = true; + arg_cat_flags = CAT_CONFIG_ON; + break; + + case ARG_TLDR: + arg_cat_flags = CAT_TLDR; break; case ARG_USER: @@ -4140,17 +4149,17 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached(); } - if (arg_operation == 0 && !arg_cat_config) + if (arg_operation == 0 && arg_cat_flags == CAT_CONFIG_OFF) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "You need to specify at least one of --clean, --create or --remove."); + "You need to specify at least one of --clean, --create, or --remove."); - if (arg_replace && arg_cat_config) + if (arg_replace && arg_cat_flags != CAT_CONFIG_OFF) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Option --replace= is not supported with --cat-config"); + "Option --replace= is not supported with --cat-config/--tldr."); if (arg_replace && optind >= argc) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "When --replace= is given, some configuration items must be specified"); + "When --replace= is given, some configuration items must be specified."); if (arg_root && arg_runtime_scope == RUNTIME_SCOPE_USER) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -4455,11 +4464,8 @@ static int run(int argc, char *argv[]) { log_debug("Looking for configuration files in (higher priority first):%s", t); } - if (arg_cat_config) { - pager_open(arg_pager_flags); - + if (arg_cat_flags != CAT_CONFIG_OFF) return cat_config(config_dirs, argv + optind); - } umask(0022); From 918560d70fb3ee8d1f4e236ac89e5eaf62aa3a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 15 Oct 2023 18:34:05 +0200 Subject: [PATCH 5/8] sysusers: add --tldr --- man/systemd-sysusers.xml | 1 + src/sysusers/sysusers.c | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/man/systemd-sysusers.xml b/man/systemd-sysusers.xml index b8b811bb5e..3dfe8c006a 100644 --- a/man/systemd-sysusers.xml +++ b/man/systemd-sysusers.xml @@ -139,6 +139,7 @@ + diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index d996583cbd..a8fa5557c5 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -94,7 +94,7 @@ typedef struct Item { static char *arg_root = NULL; static char *arg_image = NULL; -static bool arg_cat_config = false; +static CatFlags arg_cat_flags = CAT_CONFIG_OFF; static const char *arg_replace = NULL; static bool arg_dry_run = false; static bool arg_inline = false; @@ -2044,7 +2044,7 @@ static int cat_config(void) { pager_open(arg_pager_flags); - return cat_files(NULL, files, /* flags= */ 0); + return cat_files(NULL, files, arg_cat_flags); } static int help(void) { @@ -2060,6 +2060,7 @@ static int help(void) { " -h --help Show this help\n" " --version Show package version\n" " --cat-config Show configuration files\n" + " --tldr Show non-comment parts of configuration\n" " --root=PATH Operate on an alternate filesystem root\n" " --image=PATH Operate on disk image as filesystem root\n" " --image-policy=POLICY Specify disk image dissection policy\n" @@ -2079,6 +2080,7 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_CAT_CONFIG, + ARG_TLDR, ARG_ROOT, ARG_IMAGE, ARG_IMAGE_POLICY, @@ -2092,6 +2094,7 @@ static int parse_argv(int argc, char *argv[]) { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "tldr", no_argument, NULL, ARG_TLDR }, { "root", required_argument, NULL, ARG_ROOT }, { "image", required_argument, NULL, ARG_IMAGE }, { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY }, @@ -2118,7 +2121,11 @@ static int parse_argv(int argc, char *argv[]) { return version(); case ARG_CAT_CONFIG: - arg_cat_config = true; + arg_cat_flags = CAT_CONFIG_ON; + break; + + case ARG_TLDR: + arg_cat_flags = CAT_TLDR; break; case ARG_ROOT: @@ -2172,16 +2179,17 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached(); } - if (arg_replace && arg_cat_config) + if (arg_replace && arg_cat_flags != CAT_CONFIG_OFF) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Option --replace= is not supported with --cat-config"); + "Option --replace= is not supported with --cat-config/--tldr."); if (arg_replace && optind >= argc) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "When --replace= is given, some configuration items must be specified"); + "When --replace= is given, some configuration items must be specified."); if (arg_image && arg_root) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported."); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Use either --root= or --image=, the combination of both is not supported."); return 1; } @@ -2275,7 +2283,7 @@ static int run(int argc, char *argv[]) { log_setup(); - if (arg_cat_config) + if (arg_cat_flags != CAT_CONFIG_OFF) return cat_config(); umask(0022); From f80f5dd6ccfb5abf8193a59dd2f8f64866e45f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 15 Oct 2023 18:34:38 +0200 Subject: [PATCH 6/8] sysctl: add --tldr --- man/systemd-sysctl.service.xml | 1 + src/sysctl/sysctl.c | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/man/systemd-sysctl.service.xml b/man/systemd-sysctl.service.xml index 7a66e59e6e..4c63ed1723 100644 --- a/man/systemd-sysctl.service.xml +++ b/man/systemd-sysctl.service.xml @@ -78,6 +78,7 @@ + diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index bf078ac6e1..53df5389b9 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -28,7 +28,7 @@ #include "sysctl-util.h" static char **arg_prefixes = NULL; -static bool arg_cat_config = false; +static CatFlags arg_cat_flags = CAT_CONFIG_OFF; static bool arg_strict = false; static PagerFlags arg_pager_flags = 0; @@ -332,6 +332,12 @@ static int read_credential_lines(OrderedHashmap **sysctl_options) { return 0; } +static int cat_config(char **files) { + pager_open(arg_pager_flags); + + return cat_files(NULL, files, arg_cat_flags); +} + static int help(void) { _cleanup_free_ char *link = NULL; int r; @@ -345,6 +351,7 @@ static int help(void) { " -h --help Show this help\n" " --version Show package version\n" " --cat-config Show configuration files\n" + " --tldr Show non-comment parts of configuration\n" " --prefix=PATH Only apply rules with the specified prefix\n" " --no-pager Do not pipe output into a pager\n" "\nSee the %s for details.\n", @@ -359,6 +366,7 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_CAT_CONFIG, + ARG_TLDR, ARG_PREFIX, ARG_NO_PAGER, ARG_STRICT, @@ -368,6 +376,7 @@ static int parse_argv(int argc, char *argv[]) { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "tldr", no_argument, NULL, ARG_TLDR }, { "prefix", required_argument, NULL, ARG_PREFIX }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "strict", no_argument, NULL, ARG_STRICT }, @@ -390,7 +399,11 @@ static int parse_argv(int argc, char *argv[]) { return version(); case ARG_CAT_CONFIG: - arg_cat_config = true; + arg_cat_flags = CAT_CONFIG_ON; + break; + + case ARG_TLDR: + arg_cat_flags = CAT_TLDR; break; case ARG_PREFIX: { @@ -429,9 +442,9 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached(); } - if (arg_cat_config && argc > optind) + if (arg_cat_flags != CAT_CONFIG_OFF && argc > optind) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Positional arguments are not allowed with --cat-config"); + "Positional arguments are not allowed with --cat-config/--tldr."); return 1; } @@ -461,11 +474,8 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to enumerate sysctl.d files: %m"); - if (arg_cat_config) { - pager_open(arg_pager_flags); - - return cat_files(NULL, files, /* flags= */ 0); - } + if (arg_cat_flags != CAT_CONFIG_OFF) + return cat_config(files); STRV_FOREACH(f, files) RET_GATHER(r, parse_file(&sysctl_options, *f, true)); From 5737c890d61a8ca5b847fa2e1975e35faacce05f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 15 Oct 2023 18:34:54 +0200 Subject: [PATCH 7/8] binfmt: add --tldr --- man/systemd-binfmt.service.xml | 1 + src/binfmt/binfmt.c | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/man/systemd-binfmt.service.xml b/man/systemd-binfmt.service.xml index b52b58494e..15453fae29 100644 --- a/man/systemd-binfmt.service.xml +++ b/man/systemd-binfmt.service.xml @@ -52,6 +52,7 @@ + diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index fa3d6b0e26..1b34638ff9 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -24,7 +24,7 @@ #include "string-util.h" #include "strv.h" -static bool arg_cat_config = false; +static CatFlags arg_cat_flags = CAT_CONFIG_OFF; static PagerFlags arg_pager_flags = 0; static bool arg_unregister = false; @@ -106,6 +106,12 @@ static int apply_file(const char *filename, bool ignore_enoent) { return r; } +static int cat_config(char **files) { + pager_open(arg_pager_flags); + + return cat_files(NULL, files, arg_cat_flags); +} + static int help(void) { _cleanup_free_ char *link = NULL; int r; @@ -119,6 +125,7 @@ static int help(void) { " -h --help Show this help\n" " --version Show package version\n" " --cat-config Show configuration files\n" + " --tldr Show non-comment parts of configuration\n" " --no-pager Do not pipe output into a pager\n" " --unregister Unregister all existing entries\n" "\nSee the %s for details.\n", @@ -132,6 +139,7 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_CAT_CONFIG, + ARG_TLDR, ARG_NO_PAGER, ARG_UNREGISTER, }; @@ -140,6 +148,7 @@ static int parse_argv(int argc, char *argv[]) { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "tldr", no_argument, NULL, ARG_TLDR }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "unregister", no_argument, NULL, ARG_UNREGISTER }, {} @@ -161,7 +170,11 @@ static int parse_argv(int argc, char *argv[]) { return version(); case ARG_CAT_CONFIG: - arg_cat_config = true; + arg_cat_flags = CAT_CONFIG_ON; + break; + + case ARG_TLDR: + arg_cat_flags = CAT_TLDR; break; case ARG_NO_PAGER: @@ -179,9 +192,9 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached(); } - if ((arg_unregister || arg_cat_config) && argc > optind) + if ((arg_unregister || arg_cat_flags != CAT_CONFIG_OFF) && argc > optind) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Positional arguments are not allowed with --cat-config or --unregister"); + "Positional arguments are not allowed with --cat-config/--tldr or --unregister."); return 1; } @@ -229,11 +242,8 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to enumerate binfmt.d files: %m"); - if (arg_cat_config) { - pager_open(arg_pager_flags); - - return cat_files(NULL, files, /* flags= */ 0); - } + if (arg_cat_flags != CAT_CONFIG_OFF) + return cat_config(files); r = binfmt_mounted_warn(); if (r <= 0) From c04cec128f486c75e27171c10510867367fadf69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 17 Oct 2023 19:11:44 +0200 Subject: [PATCH 8/8] shared/pretty-print: skip redundant section headers with --tldr If the same section appears consecutively in a given file, subsequent occurenced are not printed. [Slice] Foo=bar [Slice] # this is not printed Bar=bar Requested in https://github.com/systemd/systemd/pull/29553#pullrequestreview-1677310352. --- src/shared/pretty-print.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index 1544b422da..e31edb88b0 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -149,7 +149,7 @@ static LineType classify_line_type(const char *line, CatFlags flags) { static int cat_file(const char *filename, bool newline, CatFlags flags) { _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *urlified = NULL, *section = NULL; + _cleanup_free_ char *urlified = NULL, *section = NULL, *old_section = NULL; int r; f = fopen(filename, "re"); @@ -189,11 +189,14 @@ static int cat_file(const char *filename, bool newline, CatFlags flags) { /* Before we print the actual line, print the last section header */ if (section) { - printf("%s%s%s\n", - ansi_highlight_cyan(), - section, - ansi_normal()); - section = mfree(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); } }