From 81f5e5136859523782e0ca0260eee60dc175c777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 26 Apr 2018 13:03:39 +0200 Subject: [PATCH 01/11] Move function to cat file & dropins into basic/ This fixes a buglet where the second and later drop-in would not be seperated properly by a newline. --- src/basic/terminal-util.c | 37 +++++++++++++++++++++++++++++++++++ src/basic/terminal-util.h | 2 ++ src/systemctl/systemctl.c | 32 +++--------------------------- src/test/test-terminal-util.c | 9 +++++++++ 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 2bf0f4f86d..5624c03bce 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -28,6 +28,7 @@ #include #include "alloc-util.h" +#include "copy.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" @@ -1362,3 +1363,39 @@ int terminal_urlify_path(const char *path, const char *text, char **ret) { return terminal_urlify(url, text, ret); } + +static int cat_file(const char *filename, bool newline) { + _cleanup_close_ int fd; + + fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return -errno; + + printf("%s%s# %s%s\n", + newline ? "\n" : "", + ansi_highlight_blue(), + filename, + ansi_normal()); + fflush(stdout); + + return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0); +} + +int cat_files(const char *file, char **dropins) { + char **path; + int r; + + if (file) { + r = cat_file(file, false); + 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); + if (r < 0) + return log_warning_errno(r, "Failed to cat %s: %m", *path); + } + + return 0; +} diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index ad6ee338ed..d2d3ad5127 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -159,3 +159,5 @@ int vt_reset_keyboard(int fd); int terminal_urlify(const char *url, const char *text, char **ret); int terminal_urlify_path(const char *path, const char *text, char **ret); + +int cat_files(const char *file, char **files); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 69a6d940ef..23ce6acd6a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5320,23 +5320,6 @@ static int show(int argc, char *argv[], void *userdata) { return ret; } -static int cat_file(const char *filename, bool newline) { - _cleanup_close_ int fd; - - fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0) - return -errno; - - printf("%s%s# %s%s\n", - newline ? "\n" : "", - ansi_highlight_blue(), - filename, - ansi_normal()); - fflush(stdout); - - return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0); -} - static int cat(int argc, char *argv[], void *userdata) { _cleanup_(lookup_paths_free) LookupPaths lp = {}; _cleanup_strv_free_ char **names = NULL; @@ -5367,7 +5350,6 @@ static int cat(int argc, char *argv[], void *userdata) { STRV_FOREACH(name, names) { _cleanup_free_ char *fragment_path = NULL; _cleanup_strv_free_ char **dropin_paths = NULL; - char **path; r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths); if (r < 0) @@ -5394,17 +5376,9 @@ static int cat(int argc, char *argv[], void *userdata) { arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", ansi_normal()); - if (fragment_path) { - r = cat_file(fragment_path, false); - if (r < 0) - return log_warning_errno(r, "Failed to cat %s: %m", fragment_path); - } - - STRV_FOREACH(path, dropin_paths) { - r = cat_file(*path, path == dropin_paths); - if (r < 0) - return log_warning_errno(r, "Failed to cat %s: %m", *path); - } + r = cat_files(fragment_path, dropin_paths); + if (r < 0) + return r; } return 0; diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c index c83dfa9dcd..92add77531 100644 --- a/src/test/test-terminal-util.c +++ b/src/test/test-terminal-util.c @@ -14,6 +14,7 @@ #include "fileio.h" #include "log.h" #include "macro.h" +#include "strv.h" #include "terminal-util.h" #include "util.h" @@ -76,6 +77,13 @@ static void test_terminal_urlify(void) { printf("Or click on %s to have a look at it!\n", formatted); } +static void test_cat_files(void) { + assert_se(cat_files("/no/such/file", NULL) == -ENOENT); + + if (access("/etc/fstab", R_OK) >= 0) + assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab")) == 0); +} + int main(int argc, char *argv[]) { log_parse_environment(); log_open(); @@ -83,6 +91,7 @@ int main(int argc, char *argv[]) { test_default_term_for_tty(); test_read_one_char(); test_terminal_urlify(); + test_cat_files(); return 0; } From 854a42fb2e9db1b9eaa381559d7671f2e9b3a0f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 26 Apr 2018 13:49:50 +0200 Subject: [PATCH 02/11] analyze: add 'cat-config' verb This is used as 'systemd-analyze show-config systemd/logind.conf', which will dump /etc/systemd/system/user@.service /etc/systemd/system/user@.service.d/*.conf /run/systemd/system/user@.service.d/*.conf /usr/local/lib/systemd/system/user@.service.d/*.conf /usr/lib/systemd/system/user@.service.d/*.conf The idea is to make it easy to dump the configuration using the same locations and order that systemd programs use themselves (including masking, in the right order, etc.). This is the generic variant that works with any configuration scheme that follows the same general rules: $ systemd-analyze cat-config systemd/system.conf $ systemd-analyze cat-config systemd/user.conf $ systemd-analyze cat-config systemd/logind.conf $ systemd-analyze cat-config systemd/sleep.conf $ systemd-analyze cat-config systemd/journald.conf $ systemd-analyze cat-config systemd/journal-remote.conf $ systemd-analyze cat-config systemd/journal-upload.conf $ systemd-analyze cat-config systemd/coredump.conf $ systemd-analyze cat-config systemd/resolved.conf $ systemd-analyze cat-config systemd/timesyncd.conf $ systemd-analyze cat-config udev/udev.conf --- man/systemd-analyze.xml | 30 ++++++++++++++++++++++++++++++ src/analyze/analyze.c | 27 +++++++++++++++++++++++++++ src/basic/conf-files.c | 32 ++++++++++++++++++++++++++++++++ src/basic/conf-files.h | 1 + src/basic/terminal-util.c | 9 +++++++-- src/basic/terminal-util.h | 7 ++++++- src/systemctl/systemctl.c | 2 +- src/test/test-terminal-util.c | 5 +++-- 8 files changed, 107 insertions(+), 6 deletions(-) diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index de14a7e3ce..70f87f4786 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -78,6 +78,12 @@ OPTIONS dump + + systemd-analyze + OPTIONS + cat-config + NAME + systemd-analyze OPTIONS @@ -180,6 +186,30 @@ state. Its format is subject to change without notice and should not be parsed by applications. + systemd-analyze cat-config is similar + to systemctl cat, but operates on config files. + It will copy the contents of a config file and any drop-ins to standard + output, using the usual systemd set of directories and rules for + precedence. + + + Showing logind configuration + $ systemd-analyze cat-config systemd/logind.conf +# /etc/systemd/logind.conf +# This file is part of systemd. +... +[Login] +NAutoVTs=8 +... + +# /usr/lib/systemd/logind.conf.d/20-test.conf +... some override from another package + +# /etc/systemd/logind.conf.d/50-override.conf +... some adminstrator override + + + systemd-analyze unit-paths outputs a list of all directories from which unit files, .d overrides, and .wants, .requires symlinks may be diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 06add1171d..0b0925d18c 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -19,12 +19,14 @@ #include "bus-unit-util.h" #include "bus-util.h" #include "calendarspec.h" +#include "conf-files.h" #include "glob-util.h" #include "hashmap.h" #include "locale-util.h" #include "log.h" #include "pager.h" #include "parse-util.h" +#include "path-util.h" #if HAVE_SECCOMP #include "seccomp-util.h" #endif @@ -1312,6 +1314,29 @@ static int dump(int argc, char *argv[], void *userdata) { return 0; } +static int cat_config(int argc, char *argv[], void *userdata) { + char **arg; + int r; + + (void) pager_open(arg_no_pager, false); + + STRV_FOREACH(arg, argv + 1) { + if (arg != argv + 1) + puts(""); + + if (path_is_absolute(*arg)) { + log_error("Arguments must be config file names (relative to /etc/"); + return -EINVAL; + } + + r = conf_files_cat(*arg); + if (r < 0) + return r; + } + + return 0; +} + static int set_log_level(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; @@ -1643,6 +1668,7 @@ static int help(int argc, char *argv[], void *userdata) { " log-level [LEVEL] Get/set logging threshold for manager\n" " log-target [TARGET] Get/set logging target for manager\n" " dump Output state serialization of service manager\n" + " cat-config Show configuration file and drop-ins\n" " unit-paths List load directories for units\n" " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" " verify FILE... Check unit files for correctness\n" @@ -1819,6 +1845,7 @@ int main(int argc, char *argv[]) { { "set-log-target", 2, 2, 0, set_log_target }, { "get-log-target", VERB_ANY, 1, 0, get_log_target }, { "dump", VERB_ANY, 1, 0, dump }, + { "cat-config", 2, VERB_ANY, 0, cat_config }, { "unit-paths", 1, 1, 0, dump_unit_paths }, { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, { "verify", 2, VERB_ANY, 0, do_verify }, diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index 8e0fb06ad9..4c5ecb5cbb 100644 --- a/src/basic/conf-files.c +++ b/src/basic/conf-files.c @@ -13,6 +13,7 @@ #include #include "conf-files.h" +#include "def.h" #include "dirent-util.h" #include "fd-util.h" #include "hashmap.h" @@ -23,6 +24,7 @@ #include "stat-util.h" #include "string-util.h" #include "strv.h" +#include "terminal-util.h" #include "util.h" static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned flags, const char *path) { @@ -256,3 +258,33 @@ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, u return conf_files_list_strv_internal(strv, suffix, root, flags, d); } + +int conf_files_cat(const char *name) { + _cleanup_strv_free_ char **dirs = NULL, **files = NULL; + const char *dir; + char **t; + int r; + + NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) { + assert(endswith(dir, "/")); + r = strv_extendf(&dirs, "%s%s.d", dir, name); + if (r < 0) + return log_error("Failed to build directory list: %m"); + } + + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dirs); + if (r < 0) + return log_error_errno(r, "Failed to query file list: %m"); + + name = strjoina("/etc/", name); + + if (DEBUG_LOGGING) { + log_debug("Looking for configuration in:"); + log_debug(" %s", name); + STRV_FOREACH(t, dirs) + log_debug(" %s/*.conf", *t); + } + + /* show */ + return cat_files(name, files, CAT_FLAGS_MAIN_FILE_OPTIONAL); +} diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h index b902c3a3b3..3d1feadf03 100644 --- a/src/basic/conf-files.h +++ b/src/basic/conf-files.h @@ -17,3 +17,4 @@ int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsi int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs); int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path); int conf_files_insert_nulstr(char ***strv, const char *root, const char *dirs, const char *path); +int conf_files_cat(const char *name); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 5624c03bce..c2b7cd799e 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1381,13 +1381,18 @@ static int cat_file(const char *filename, bool newline) { return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0); } -int cat_files(const char *file, char **dropins) { +int cat_files(const char *file, char **dropins, CatFlags flags) { char **path; int r; if (file) { r = cat_file(file, false); - if (r < 0) + if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL)) + printf("%s# config file %s not found%s\n", + ansi_highlight_magenta(), + file, + ansi_normal()); + else if (r < 0) return log_warning_errno(r, "Failed to cat %s: %m", file); } diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index d2d3ad5127..ea7eb2d63b 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -133,6 +133,7 @@ DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED); DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN); DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW); DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE); +DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA); DEFINE_ANSI_FUNC(normal, NORMAL); DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL); @@ -160,4 +161,8 @@ int vt_reset_keyboard(int fd); int terminal_urlify(const char *url, const char *text, char **ret); int terminal_urlify_path(const char *path, const char *text, char **ret); -int cat_files(const char *file, char **files); +typedef enum CatFlags { + CAT_FLAGS_MAIN_FILE_OPTIONAL = 1 << 1, +} CatFlags; + +int cat_files(const char *file, char **dropins, CatFlags flags); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 23ce6acd6a..a1938bc91b 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5376,7 +5376,7 @@ static int cat(int argc, char *argv[], void *userdata) { arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", ansi_normal()); - r = cat_files(fragment_path, dropin_paths); + r = cat_files(fragment_path, dropin_paths, 0); if (r < 0) return r; } diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c index 92add77531..61a3ea5e56 100644 --- a/src/test/test-terminal-util.c +++ b/src/test/test-terminal-util.c @@ -78,10 +78,11 @@ static void test_terminal_urlify(void) { } static void test_cat_files(void) { - assert_se(cat_files("/no/such/file", NULL) == -ENOENT); + assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT); + assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0); if (access("/etc/fstab", R_OK) >= 0) - assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab")) == 0); + assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0); } int main(int argc, char *argv[]) { From ceaaeb9bab2efee578971615c584c4c91b9d3858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 26 Apr 2018 19:07:54 +0200 Subject: [PATCH 03/11] tmpfiles: add --cat-config This implements similar logic as conf_files_cat(), but with slightly different file gathering logic. I also want to add support for replacement files later on, so it seems better to keep those two file-gathering functions separate. --- man/standard-options.xml | 9 +++++ man/systemd-tmpfiles.xml | 1 + src/basic/conf-files.c | 35 +++++++++++++++++++ src/basic/conf-files.h | 6 ++++ src/tmpfiles/tmpfiles.c | 72 +++++++++++++++++++++++++--------------- 5 files changed, 96 insertions(+), 27 deletions(-) diff --git a/man/standard-options.xml b/man/standard-options.xml index 40edb4b4e1..4ffe124905 100644 --- a/man/standard-options.xml +++ b/man/standard-options.xml @@ -50,4 +50,13 @@ footer with hints. + + + + + + Copy the contents of config files to standard output. + Before each file, the filename is printed as a comment. + + diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml index c40f8a920a..f8a289eba3 100644 --- a/man/systemd-tmpfiles.xml +++ b/man/systemd-tmpfiles.xml @@ -183,6 +183,7 @@ + diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index 4c5ecb5cbb..29a85c018a 100644 --- a/src/basic/conf-files.c +++ b/src/basic/conf-files.c @@ -259,6 +259,41 @@ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, u return conf_files_list_strv_internal(strv, suffix, root, flags, d); } +int conf_files_list_with_replacement( + const char *root, + char **config_dirs, + const char *replacement, + char ***files, + char **replace_file) { + + _cleanup_strv_free_ char **f = NULL; + _cleanup_free_ char *p = NULL; + int r; + + assert(config_dirs); + assert(files); + assert(replace_file || !replacement); + + r = conf_files_list_strv(&f, ".conf", root, 0, (const char* const*) config_dirs); + if (r < 0) + return log_error_errno(r, "Failed to enumerate config files: %m"); + + if (replacement) { + r = conf_files_insert(&f, root, config_dirs, replacement); + if (r < 0) + return log_error_errno(r, "Failed to extend config file list: %m"); + + p = path_join(root, replacement, NULL); + if (!p) + return log_oom(); + } + + *files = TAKE_PTR(f); + if (replace_file) + *replace_file = TAKE_PTR(p); + return 0; +} + int conf_files_cat(const char *name) { _cleanup_strv_free_ char **dirs = NULL, **files = NULL; const char *dir; diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h index 3d1feadf03..7eb8739ee1 100644 --- a/src/basic/conf-files.h +++ b/src/basic/conf-files.h @@ -17,4 +17,10 @@ int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsi int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs); int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path); int conf_files_insert_nulstr(char ***strv, const char *root, const char *dirs, const char *path); +int conf_files_list_with_replacement( + const char *root, + char **config_dirs, + const char *replacement, + char ***files, + char **replace_file); int conf_files_cat(const char *name); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index bc66299142..b4a9b87728 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -60,6 +60,7 @@ #include "string-table.h" #include "string-util.h" #include "strv.h" +#include "terminal-util.h" #include "umask-util.h" #include "user-util.h" #include "util.h" @@ -149,6 +150,7 @@ typedef enum DirectoryType { _DIRECTORY_TYPE_MAX, } DirectoryType; +static bool arg_cat_config = false; static bool arg_user = false; static bool arg_create = false; static bool arg_clean = false; @@ -2441,12 +2443,24 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool return 0; } +static int cat_config(char **config_dirs, char **args) { + _cleanup_strv_free_ char **files = NULL; + int r; + + r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, NULL); + if (r < 0) + return r; + + return cat_files(NULL, files, 0); +} + static void help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Creates, deletes and cleans up volatile and temporary files and directories.\n\n" " -h --help Show this help\n" " --user Execute user configuration\n" " --version Show package version\n" + " --cat-config Show configuration files\n" " --create Create marked files/directories\n" " --clean Clean up marked directories\n" " --remove Remove marked files/directories\n" @@ -2462,6 +2476,7 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, + ARG_CAT_CONFIG, ARG_USER, ARG_CREATE, ARG_CLEAN, @@ -2477,6 +2492,7 @@ static int parse_argv(int argc, char *argv[]) { { "help", no_argument, NULL, 'h' }, { "user", no_argument, NULL, ARG_USER }, { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, { "create", no_argument, NULL, ARG_CREATE }, { "clean", no_argument, NULL, ARG_CLEAN }, { "remove", no_argument, NULL, ARG_REMOVE }, @@ -2504,6 +2520,10 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERSION: return version(); + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + case ARG_USER: arg_user = true; break; @@ -2557,11 +2577,16 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (!arg_clean && !arg_create && !arg_remove) { + if (!arg_clean && !arg_create && !arg_remove && !arg_cat_config) { log_error("You need to specify at least one of --clean, --create or --remove."); return -EINVAL; } + if (arg_replace && arg_cat_config) { + log_error("Option --replace= is not supported with --cat-config"); + return -EINVAL; + } + if (arg_replace && optind >= argc) { log_error("When --replace= is given, some configuration items must be specified"); return -EINVAL; @@ -2677,19 +2702,9 @@ static int read_config_files(char **config_dirs, char **args, bool *invalid_conf char **f; int r; - r = conf_files_list_strv(&files, ".conf", arg_root, 0, (const char* const*) config_dirs); + r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, &p); if (r < 0) - return log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m"); - - if (arg_replace) { - r = conf_files_insert(&files, arg_root, config_dirs, arg_replace); - if (r < 0) - return log_error_errno(r, "Failed to extend tmpfiles.d file list: %m"); - - p = path_join(arg_root, arg_replace, NULL); - if (!p) - return log_oom(); - } + return r; STRV_FOREACH(f, files) if (p && path_equal(*f, p)) { @@ -2721,20 +2736,6 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); - umask(0022); - - mac_selinux_init(); - - items = ordered_hashmap_new(&string_hash_ops); - globs = ordered_hashmap_new(&string_hash_ops); - - if (!items || !globs) { - r = log_oom(); - goto finish; - } - - r = 0; - if (arg_user) { r = user_config_paths(&config_dirs); if (r < 0) { @@ -2757,6 +2758,23 @@ int main(int argc, char *argv[]) { log_debug("Looking for configuration files in (higher priority first):\n\t%s", t); } + if (arg_cat_config) { + r = cat_config(config_dirs, argv + optind); + goto finish; + } + + umask(0022); + + mac_selinux_init(); + + items = ordered_hashmap_new(&string_hash_ops); + globs = ordered_hashmap_new(&string_hash_ops); + + if (!items || !globs) { + r = log_oom(); + goto finish; + } + /* If command line arguments are specified along with --replace, read all * configuration files and insert the positional arguments at the specified * place. Otherwise, if command line arguments are specified, execute just From ec0327d69c260d9a3770e9d722dbdcde996651cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 26 Apr 2018 20:38:39 +0200 Subject: [PATCH 04/11] sysusers: add --cat-config --- man/systemd-sysusers.xml | 1 + src/basic/def.h | 14 +++++++-- src/sysusers/sysusers.c | 64 ++++++++++++++++++++++++++-------------- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/man/systemd-sysusers.xml b/man/systemd-sysusers.xml index 0f4a47bc7e..ea119fe375 100644 --- a/man/systemd-sysusers.xml +++ b/man/systemd-sysusers.xml @@ -124,6 +124,7 @@ line instead of a file name. + diff --git a/src/basic/def.h b/src/basic/def.h index 0ffd81fe39..559721754a 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -54,8 +54,10 @@ #define NOTIFY_BUFFER_MAX PIPE_BUF #if HAVE_SPLIT_USR -# define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0" +# define _CONF_PATHS_SPLIT_USR_NULSTR(n) "/lib/" n "\0" +# define _CONF_PATHS_SPLIT_USR(n) , "/lib/" n #else +# define _CONF_PATHS_SPLIT_USR_NULSTR(n) # define _CONF_PATHS_SPLIT_USR(n) #endif @@ -68,6 +70,14 @@ "/run/" n "\0" \ "/usr/local/lib/" n "\0" \ "/usr/lib/" n "\0" \ - _CONF_PATHS_SPLIT_USR(n) + _CONF_PATHS_SPLIT_USR_NULSTR(n) + +#define CONF_PATHS_STRV(n) \ + STRV_MAKE( \ + "/etc/" n, \ + "/run/" n, \ + "/usr/local/lib/" n, \ + "/usr/lib/" n \ + _CONF_PATHS_SPLIT_USR(n)) #define LONG_LINE_MAX (1U*1024U*1024U) diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 7c5fafcf8a..c9744728d4 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -23,6 +23,7 @@ #include "specifier.h" #include "string-util.h" #include "strv.h" +#include "terminal-util.h" #include "uid-range.h" #include "user-util.h" #include "utf8.h" @@ -61,10 +62,11 @@ typedef struct Item { } Item; static char *arg_root = NULL; +static bool arg_cat_config = false; static const char *arg_replace = NULL; static bool arg_inline = false; -static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d"); +static char **config_dirs = CONF_PATHS_STRV("sysusers.d"); static OrderedHashmap *users = NULL, *groups = NULL; static OrderedHashmap *todo_uids = NULL, *todo_gids = NULL; @@ -1688,7 +1690,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) { if (streq(fn, "-")) f = stdin; else { - r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &rf); + r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &rf); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; @@ -1744,11 +1746,24 @@ static void free_database(Hashmap *by_name, Hashmap *by_id) { hashmap_free(by_id); } +static int cat_config(void) { + _cleanup_strv_free_ char **files = NULL; + _cleanup_free_ char *replace_file = NULL; + int r; + + r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, NULL); + if (r < 0) + return r; + + return cat_files(NULL, files, 0); +} + static void help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Creates system user accounts.\n\n" " -h --help Show this help\n" " --version Show package version\n" + " --cat-config Show configuration files\n" " --root=PATH Operate on an alternate filesystem root\n" " --replace=PATH Treat arguments as replacement for PATH\n" " --inline Treat arguments as configuration lines\n" @@ -1759,17 +1774,19 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, + ARG_CAT_CONFIG, ARG_ROOT, ARG_REPLACE, ARG_INLINE, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "root", required_argument, NULL, ARG_ROOT }, - { "replace", required_argument, NULL, ARG_REPLACE }, - { "inline", no_argument, NULL, ARG_INLINE }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "root", required_argument, NULL, ARG_ROOT }, + { "replace", required_argument, NULL, ARG_REPLACE }, + { "inline", no_argument, NULL, ARG_INLINE }, {} }; @@ -1789,6 +1806,10 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERSION: return version(); + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + case ARG_ROOT: r = parse_path_argument_and_warn(optarg, true, &arg_root); if (r < 0) @@ -1816,6 +1837,11 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } + if (arg_replace && arg_cat_config) { + log_error("Option --replace= is not supported with --cat-config"); + return -EINVAL; + } + if (arg_replace && optind >= argc) { log_error("When --replace= is given, some configuration items must be specified"); return -EINVAL; @@ -1844,25 +1870,15 @@ static int parse_arguments(char **args) { return 0; } -static int read_config_files(const char* dirs, char **args) { +static int read_config_files(char **args) { _cleanup_strv_free_ char **files = NULL; _cleanup_free_ char *p = NULL; char **f; int r; - r = conf_files_list_nulstr(&files, ".conf", arg_root, 0, dirs); + r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, &p); if (r < 0) - return log_error_errno(r, "Failed to enumerate sysusers.d files: %m"); - - if (arg_replace) { - r = conf_files_insert_nulstr(&files, arg_root, dirs, arg_replace); - if (r < 0) - return log_error_errno(r, "Failed to extend sysusers.d file list: %m"); - - p = path_join(arg_root, arg_replace, NULL); - if (!p) - return log_oom(); - } + return r; STRV_FOREACH(f, files) if (p && path_equal(*f, p)) { @@ -1882,7 +1898,6 @@ static int read_config_files(const char* dirs, char **args) { } int main(int argc, char *argv[]) { - _cleanup_close_ int lock = -1; Iterator iterator; int r; @@ -1897,6 +1912,11 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); + if (arg_cat_config) { + r = cat_config(); + goto finish; + } + umask(0022); r = mac_selinux_init(); @@ -1912,7 +1932,7 @@ int main(int argc, char *argv[]) { * read configuration and execute it. */ if (arg_replace || optind >= argc) - r = read_config_files(conf_file_dirs, argv + optind); + r = read_config_files(argv + optind); else r = parse_arguments(argv + optind); if (r < 0) From 3c51c626160b4798f547ca0b2d42901909edd90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 26 Apr 2018 21:08:53 +0200 Subject: [PATCH 05/11] sysctl: add --cat-config --- man/systemd-sysctl.service.xml | 1 + src/sysctl/sysctl.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/man/systemd-sysctl.service.xml b/man/systemd-sysctl.service.xml index b4fdc708ad..5df310cff5 100644 --- a/man/systemd-sysctl.service.xml +++ b/man/systemd-sysctl.service.xml @@ -79,6 +79,7 @@ + diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 75a3680db0..55aedffc6e 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -23,11 +23,13 @@ #include "string-util.h" #include "strv.h" #include "sysctl-util.h" +#include "terminal-util.h" #include "util.h" static char **arg_prefixes = NULL; +static bool arg_cat_config = false; -static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d"); +static char **config_dirs = CONF_PATHS_STRV("sysctl.d"); static int apply_all(OrderedHashmap *sysctl_options) { char *property, *value; @@ -83,7 +85,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign assert(path); - r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f); + r = search_and_fopen(path, "re", NULL, (const char**) config_dirs, &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; @@ -168,6 +170,7 @@ static void help(void) { "Applies kernel sysctl settings.\n\n" " -h --help Show this help\n" " --version Show package version\n" + " --cat-config Show configuration files\n" " --prefix=PATH Only apply rules with the specified prefix\n" , program_invocation_short_name); } @@ -176,13 +179,15 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, - ARG_PREFIX + ARG_CAT_CONFIG, + ARG_PREFIX, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "prefix", required_argument, NULL, ARG_PREFIX }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "prefix", required_argument, NULL, ARG_PREFIX }, {} }; @@ -202,6 +207,10 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERSION: return version(); + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + case ARG_PREFIX: { char *p; @@ -231,6 +240,11 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } + if (arg_cat_config && argc > optind) { + log_error("Positional arguments are not allowed with --cat-config"); + return -EINVAL; + } + return 1; } @@ -268,12 +282,17 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) config_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate sysctl.d files: %m"); goto finish; } + if (arg_cat_config) { + r = cat_files(NULL, files, 0); + goto finish; + } + STRV_FOREACH(f, files) { k = parse_file(sysctl_options, *f, true); if (k < 0 && r == 0) From 46d8646a9fd637b8911ac032cb2a760407221f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 27 Apr 2018 08:55:16 +0200 Subject: [PATCH 06/11] analyze: add --root option for cat-config --- man/systemd-analyze.xml | 7 +++++++ src/analyze/analyze.c | 14 +++++++++++++- src/basic/conf-files.c | 13 ++++++++----- src/basic/conf-files.h | 2 +- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index 70f87f4786..1c43531871 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -367,6 +367,13 @@ NAutoVTs=8 generators enabled will generally result in some warnings. + + + + With cat-files, show config files underneath + the specified root path PATH. + + diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 0b0925d18c..19e6e83c6f 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -72,6 +72,7 @@ static const char *arg_host = NULL; static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; static bool arg_man = true; static bool arg_generators = false; +static const char *arg_root = NULL; struct boot_times { usec_t firmware_time; @@ -1329,7 +1330,7 @@ static int cat_config(int argc, char *argv[], void *userdata) { return -EINVAL; } - r = conf_files_cat(*arg); + r = conf_files_cat(arg_root, *arg); if (r < 0) return r; } @@ -1688,6 +1689,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_ORDER, ARG_REQUIRE, + ARG_ROOT, ARG_SYSTEM, ARG_USER, ARG_GLOBAL, @@ -1704,6 +1706,7 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "order", no_argument, NULL, ARG_ORDER }, { "require", no_argument, NULL, ARG_REQUIRE }, + { "root", required_argument, NULL, ARG_ROOT }, { "system", no_argument, NULL, ARG_SYSTEM }, { "user", no_argument, NULL, ARG_USER }, { "global", no_argument, NULL, ARG_GLOBAL }, @@ -1732,6 +1735,10 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERSION: return version(); + case ARG_ROOT: + arg_root = optarg; + break; + case ARG_SYSTEM: arg_scope = UNIT_FILE_SYSTEM; break; @@ -1825,6 +1832,11 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } + if (arg_root && !streq_ptr(argv[optind], "cat-config")) { + log_error("Option --root is only supported for cat-config right now."); + return -EINVAL; + } + return 1; /* work to do */ } diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index 29a85c018a..00e4629668 100644 --- a/src/basic/conf-files.c +++ b/src/basic/conf-files.c @@ -294,8 +294,9 @@ int conf_files_list_with_replacement( return 0; } -int conf_files_cat(const char *name) { +int conf_files_cat(const char *root, const char *name) { _cleanup_strv_free_ char **dirs = NULL, **files = NULL; + _cleanup_free_ char *path = NULL; const char *dir; char **t; int r; @@ -307,19 +308,21 @@ int conf_files_cat(const char *name) { return log_error("Failed to build directory list: %m"); } - r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dirs); + r = conf_files_list_strv(&files, ".conf", root, 0, (const char* const*) dirs); if (r < 0) return log_error_errno(r, "Failed to query file list: %m"); - name = strjoina("/etc/", name); + path = path_join(root, "/etc", name); + if (!path) + return log_oom(); if (DEBUG_LOGGING) { log_debug("Looking for configuration in:"); - log_debug(" %s", name); + log_debug(" %s", path); STRV_FOREACH(t, dirs) log_debug(" %s/*.conf", *t); } /* show */ - return cat_files(name, files, CAT_FLAGS_MAIN_FILE_OPTIONAL); + return cat_files(path, files, CAT_FLAGS_MAIN_FILE_OPTIONAL); } diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h index 7eb8739ee1..2dd1b272ca 100644 --- a/src/basic/conf-files.h +++ b/src/basic/conf-files.h @@ -23,4 +23,4 @@ int conf_files_list_with_replacement( const char *replacement, char ***files, char **replace_file); -int conf_files_cat(const char *name); +int conf_files_cat(const char *root, const char *name); From 6aaab70f0c7af9a529a2433ad39fe9169883a391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 27 Apr 2018 09:11:59 +0200 Subject: [PATCH 07/11] binfmt: add --cat-config Document --help and --version while at it. --- man/systemd-binfmt.service.xml | 11 ++++++++++- src/binfmt/binfmt.c | 29 ++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/man/systemd-binfmt.service.xml b/man/systemd-binfmt.service.xml index f02e8f0cb0..37ac163f07 100644 --- a/man/systemd-binfmt.service.xml +++ b/man/systemd-binfmt.service.xml @@ -8,7 +8,8 @@ Copyright 2012 Lennart Poettering --> - + systemd-binfmt.service @@ -52,6 +53,14 @@ for information about the configuration of this service. + Options + + + + + + + See Also diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 03c4937dac..22296ca164 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -21,9 +21,11 @@ #include "log.h" #include "string-util.h" #include "strv.h" +#include "terminal-util.h" #include "util.h" -static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d"); +static char **config_dirs = CONF_PATHS_STRV("binfmt.d"); +static bool arg_cat_config = false; static int delete_rule(const char *rule) { _cleanup_free_ char *x = NULL, *fn = NULL; @@ -63,7 +65,7 @@ static int apply_file(const char *path, bool ignore_enoent) { assert(path); - r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f); + r = search_and_fopen(path, "re", NULL, (const char**) config_dirs, &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; @@ -102,6 +104,7 @@ static void help(void) { "Registers binary formats.\n\n" " -h --help Show this help\n" " --version Show package version\n" + " --cat-config Show configuration files\n" , program_invocation_short_name); } @@ -109,11 +112,13 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, + ARG_CAT_CONFIG, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, {} }; @@ -133,6 +138,10 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERSION: return version(); + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + case '?': return -EINVAL; @@ -140,6 +149,11 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } + if (arg_cat_config && argc > optind) { + log_error("Positional arguments are not allowed with --cat-config"); + return -EINVAL; + } + return 1; } @@ -170,12 +184,17 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) config_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate binfmt.d files: %m"); goto finish; } + if (arg_cat_config) { + r = cat_files(NULL, files, 0); + goto finish; + } + /* Flush out all rules */ write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0); From f8360f335c3ff78da41e6316049e1562b0711f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 27 Apr 2018 09:39:53 +0200 Subject: [PATCH 08/11] basic/terminal-util: fix output of files without a final newline If the main config file or one of the drop-ins did not have the final newline, there would be no seperating empty line (or if this was the last file displayed, our own output would end without the final newline, possibly running into the subsequent prompt or such). copy_bytes() does not know anything about lines, so let's just use a normal loop with read_line() and puts(). --- src/basic/terminal-util.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index c2b7cd799e..7f18d3d35c 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -29,6 +29,7 @@ #include "alloc-util.h" #include "copy.h" +#include "def.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" @@ -1365,10 +1366,11 @@ int terminal_urlify_path(const char *path, const char *text, char **ret) { } static int cat_file(const char *filename, bool newline) { - _cleanup_close_ int fd; + _cleanup_fclose_ FILE *f = NULL; + int r; - fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0) + f = fopen(filename, "re"); + if (!f) return -errno; printf("%s%s# %s%s\n", @@ -1378,7 +1380,19 @@ static int cat_file(const char *filename, bool newline) { ansi_normal()); fflush(stdout); - return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0); + for (;;) { + _cleanup_free_ char *line = NULL; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read \"%s\": %m", filename); + if (r == 0) + break; + + puts(line); + } + + return 0; } int cat_files(const char *file, char **dropins, CatFlags flags) { From 2e1ec10a62e57551e3ee17606df488816e945b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 27 Apr 2018 09:55:32 +0200 Subject: [PATCH 09/11] analyze: seperate config file groups by underline When multiple configuration file groups are shown together (e.g. systemd-analyze cat-config systemd/system.conf systemd/user.conf), it's nice to separate them visually. I tried first to write a line of spaces and underline that. This does not look too good, because the line is too low. Then I tried a block of blue-background spaces. In this version, there are two lines, one is full of spaces and underlined, so visually we get an empty line in the middle. I then tried underlining the last line of the previous file. This does not look right, unless the line is full width, i.e. unless spaces are written out until the end of the line. But when those spaces are added, it's not clear if they were part of the original file or not. Here, the spaces are between groups, so it seems less likely that somebody will mistake those spaces for part of the configuration file. --- src/analyze/analyze.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 19e6e83c6f..b6036acf1c 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -1323,7 +1323,10 @@ static int cat_config(int argc, char *argv[], void *userdata) { STRV_FOREACH(arg, argv + 1) { if (arg != argv + 1) - puts(""); + printf("%s%*s%s\n\n", + ansi_underline(), + columns(), "", + ansi_normal()); if (path_is_absolute(*arg)) { log_error("Arguments must be config file names (relative to /etc/"); From 971f6ea5511a204165a7bc2f8da92f5a465dad57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 27 Apr 2018 12:50:07 +0200 Subject: [PATCH 10/11] analyze: allow full paths for cat-config $ systemd-analyze cat-config systemd/logind.conf $ systemd-analyze cat-config /etc/systemd/logind.conf $ systemd-analyze cat-config /usr/lib/systemd/logind.conf are all equvalent, $ systemd-analyze cat-config /var/systemd/logind.conf is an error. --- man/systemd-analyze.xml | 8 ++++++-- src/analyze/analyze.c | 22 ++++++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index 1c43531871..0d2ccd7bfe 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -82,7 +82,7 @@ systemd-analyze OPTIONS cat-config - NAME + NAME|PATH systemd-analyze @@ -190,7 +190,11 @@ to systemctl cat, but operates on config files. It will copy the contents of a config file and any drop-ins to standard output, using the usual systemd set of directories and rules for - precedence. + precedence. Each argument must be either an absolute path including + the prefix (such as /etc/systemd/logind.conf or + /usr/lib/systemd/logind.conf), or a name + relative to the prefix (such as systemd/logind.conf). + Showing logind configuration diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index b6036acf1c..ea51453d40 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -19,6 +19,7 @@ #include "bus-unit-util.h" #include "bus-util.h" #include "calendarspec.h" +#include "def.h" #include "conf-files.h" #include "glob-util.h" #include "hashmap.h" @@ -1322,6 +1323,8 @@ static int cat_config(int argc, char *argv[], void *userdata) { (void) pager_open(arg_no_pager, false); STRV_FOREACH(arg, argv + 1) { + const char *t = NULL; + if (arg != argv + 1) printf("%s%*s%s\n\n", ansi_underline(), @@ -1329,11 +1332,22 @@ static int cat_config(int argc, char *argv[], void *userdata) { ansi_normal()); if (path_is_absolute(*arg)) { - log_error("Arguments must be config file names (relative to /etc/"); - return -EINVAL; - } + const char *dir; - r = conf_files_cat(arg_root, *arg); + NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) { + t = path_startswith(*arg, dir); + if (t) + break; + } + + if (!t) { + log_error("Path %s does not start with any known prefix.", *arg); + return -EINVAL; + } + } else + t = *arg; + + r = conf_files_cat(arg_root, t); if (r < 0) return r; } From a826d4f7d01b144df191cf7a6de729b678cdb1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 27 Apr 2018 18:20:17 +0200 Subject: [PATCH 11/11] Eliminate config_dirs vars which hold a static strv --- src/binfmt/binfmt.c | 5 ++--- src/sysctl/sysctl.c | 6 ++---- src/sysusers/sysusers.c | 8 +++----- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 22296ca164..0eb9e46014 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -24,7 +24,6 @@ #include "terminal-util.h" #include "util.h" -static char **config_dirs = CONF_PATHS_STRV("binfmt.d"); static bool arg_cat_config = false; static int delete_rule(const char *rule) { @@ -65,7 +64,7 @@ static int apply_file(const char *path, bool ignore_enoent) { assert(path); - r = search_and_fopen(path, "re", NULL, (const char**) config_dirs, &f); + r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; @@ -184,7 +183,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) config_dirs); + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d")); if (r < 0) { log_error_errno(r, "Failed to enumerate binfmt.d files: %m"); goto finish; diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 55aedffc6e..5489cb96b7 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -29,8 +29,6 @@ static char **arg_prefixes = NULL; static bool arg_cat_config = false; -static char **config_dirs = CONF_PATHS_STRV("sysctl.d"); - static int apply_all(OrderedHashmap *sysctl_options) { char *property, *value; Iterator i; @@ -85,7 +83,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign assert(path); - r = search_and_fopen(path, "re", NULL, (const char**) config_dirs, &f); + r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; @@ -282,7 +280,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) config_dirs); + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("sysctl.d")); if (r < 0) { log_error_errno(r, "Failed to enumerate sysctl.d files: %m"); goto finish; diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index c9744728d4..92e5851519 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -66,8 +66,6 @@ static bool arg_cat_config = false; static const char *arg_replace = NULL; static bool arg_inline = false; -static char **config_dirs = CONF_PATHS_STRV("sysusers.d"); - static OrderedHashmap *users = NULL, *groups = NULL; static OrderedHashmap *todo_uids = NULL, *todo_gids = NULL; static OrderedHashmap *members = NULL; @@ -1690,7 +1688,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) { if (streq(fn, "-")) f = stdin; else { - r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &rf); + r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; @@ -1751,7 +1749,7 @@ static int cat_config(void) { _cleanup_free_ char *replace_file = NULL; int r; - r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, NULL); + r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, NULL); if (r < 0) return r; @@ -1876,7 +1874,7 @@ static int read_config_files(char **args) { char **f; int r; - r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, &p); + r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, &p); if (r < 0) return r;