<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">dump</arg>
</cmdsynopsis>
+ <cmdsynopsis>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">cat-config</arg>
+ <arg choice="plain" rep="repeat"><replaceable>NAME</replaceable></arg>
+ </cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
state. Its format is subject to change without notice and should
not be parsed by applications.</para>
+ <para><command>systemd-analyze cat-config</command> is similar
+ to <command>systemctl cat</command>, 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.</para>
+
+ <example>
+ <title>Showing logind configuration</title>
+ <programlisting>$ 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
+ </programlisting>
+ </example>
+
<para><command>systemd-analyze unit-paths</command> outputs a list of all
directories from which unit files, <filename>.d</filename> overrides, and
<filename>.wants</filename>, <filename>.requires</filename> symlinks may be
#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
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;
" 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"
{ "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 },
#include <string.h>
#include "conf-files.h"
+#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
#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) {
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);
+}
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);
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);
}
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);
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);
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;
}
}
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[]) {