]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveconf -n, -a: Show version number, config file path and system info.
authorTimo Sirainen <tss@iki.fi>
Wed, 6 May 2009 18:33:06 +0000 (14:33 -0400)
committerTimo Sirainen <tss@iki.fi>
Wed, 6 May 2009 18:33:06 +0000 (14:33 -0400)
--HG--
branch : HEAD

src/config/Makefile.am
src/config/doveconf.c
src/config/sysinfo-get.c [new file with mode: 0644]
src/config/sysinfo-get.h [new file with mode: 0644]

index aab3f6cd7850f5db72ee021482b830b12dcf8a79..c15854e74f5a170fa1b0925015a5f87e0222c7af 100644 (file)
@@ -29,7 +29,8 @@ common = \
        all-settings.c \
        config-connection.c \
        config-parser.c \
-       config-request.c
+       config-request.c \
+       sysinfo-get.c
 
 config_SOURCES = \
        main.c \
@@ -42,7 +43,8 @@ doveconf_SOURCES = \
 noinst_HEADERS = \
        all-settings.h \
        config-connection.h \
-       config-parser.h
+       config-parser.h \
+       sysinfo-get.h
 
 all-settings.c: $(SETTING_FILES) $(top_srcdir)/src/config/settings-get.pl
        $(top_srcdir)/src/config/settings-get.pl $(SETTING_FILES) > all-settings.c || rm -f all-settings.c
index 0037456cd34e6b6e97b700260e69234de523870e..202a9cb241e6b2df779a109dc10a912ab0009f09 100644 (file)
@@ -3,12 +3,16 @@
 #include "lib.h"
 #include "array.h"
 #include "env-util.h"
-#include "master-service.h"
 #include "ostream.h"
+#include "settings-parser.h"
+#include "master-service.h"
+#include "all-settings.h"
+#include "sysinfo-get.h"
 #include "config-connection.h"
 #include "config-parser.h"
 #include "config-request.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
@@ -173,16 +177,38 @@ static void config_request_putenv(const char *key, const char *value,
        } T_END;
 }
 
+static const char *get_mail_location(void)
+{
+       struct config_setting_parser_list *l;
+       const struct setting_define *def;
+       const char *const *value;
+       const void *set;
+
+       for (l = config_setting_parsers; l->module_name != NULL; l++) {
+               if (strcmp(l->module_name, "mail") != 0)
+                       continue;
+
+               set = settings_parser_get(l->parser);
+               for (def = l->root->defines; def->key != NULL; def++) {
+                       if (strcmp(def->key, "mail_location") == 0) {
+                               value = CONST_PTR_OFFSET(set, def->offset);
+                               return *value;
+                       }
+               }
+       }
+       return "";
+}
+
 int main(int argc, char *argv[])
 {
        enum config_dump_flags flags = CONFIG_DUMP_FLAG_DEFAULTS;
-       const char *getopt_str, *service_name = "";
+       const char *getopt_str, *config_path, *service_name = "";
        char **exec_args = NULL;
        int c;
 
        service = master_service_init("config", MASTER_SERVICE_FLAG_STANDALONE,
                                      argc, argv);
-
+       i_set_failure_prefix("doveconf: ");
        getopt_str = t_strconcat("anp:e", master_service_getopt_string(), NULL);
        while ((c = getopt(argc, argv, getopt_str)) > 0) {
                if (c == 'e')
@@ -201,15 +227,29 @@ int main(int argc, char *argv[])
                                exit(FATAL_DEFAULT);
                }
        }
+       config_path = master_service_get_config_path(service);
+
        if (argv[optind] != NULL)
                exec_args = &argv[optind];
+       else {
+               /* print the config file path before parsing it, so in case
+                  of errors it's still shown */
+               printf("# "VERSION": %s\n", config_path);
+               fflush(stdout);
+       }
        master_service_init_finish(service);
 
-       config_parse_file(master_service_get_config_path(service));
+       config_parse_file(config_path);
 
-       if (exec_args == NULL)
+       if (exec_args == NULL) {
+               const char *info;
+
+               info = sysinfo_get(get_mail_location());
+               if (*info != '\0')
+                       printf("# %s\n", info);
+               fflush(stdout);
                config_dump_human(service_name, flags);
-       else {
+       else {
                env_put("DOVECONF_ENV=1");
                config_request_handle(service_name, 0,
                                      config_request_putenv, NULL);
diff --git a/src/config/sysinfo-get.c b/src/config/sysinfo-get.c
new file mode 100644 (file)
index 0000000..49091e2
--- /dev/null
@@ -0,0 +1,127 @@
+/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "mountpoint.h"
+#include "strescape.h"
+#include "sysinfo-get.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_UTSNAME_H
+#  include <sys/utsname.h>
+#endif
+
+static bool readfile(const char *path, const char **data_r)
+{
+       char buf[1024];
+       int fd, ret;
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return FALSE;
+       ret = read(fd, buf, sizeof(buf));
+       (void)close(fd);
+       if (ret <= 0)
+               return FALSE;
+
+       *data_r = t_strndup(buf, ret);
+       return TRUE;
+}
+
+static bool lsb_distro_get(const char *path, const char **name_r)
+{
+       const char *data, *const *p, *str, *end;
+
+       if (!readfile(path, &data))
+               return FALSE;
+
+       for (p = t_strsplit(data, "\n"); *p != '\0'; p++) {
+               if (strncmp(*p, "DISTRIB_DESCRIPTION=", 20) == 0)
+                       break;
+       }
+       if (*p == '\0')
+               return FALSE;
+
+       str = t_strcut(*p + 20, '\n');
+       if (*str != '"')
+               *name_r = str;
+       else {
+               end = strrchr(++str, '"');
+               *name_r = str_unescape(p_strdup_until(unsafe_data_stack_pool,
+                                                     str, end));
+       }
+       return TRUE;
+}
+
+static const char *distro_get(void)
+{
+       static const char *files[] = {
+               "", "/etc/redhat-release",
+               "", "/etc/SuSE-release",
+               "", "/etc/mandriva-release",
+               "", "/etc/fedora-release",
+               "", "/etc/sourcemage-release",
+               "", "/etc/slackware-version",
+               "", "/etc/gentoo-release",
+               "Debian ", "/etc/debian_version",
+               NULL
+       };
+       const char *name;
+       unsigned int i;
+
+       if (lsb_distro_get("/etc/lsb-release", &name))
+               return name;
+       for (i = 0; files[i] != NULL; i += 2) {
+               if (readfile(files[i+1], &name)) {
+                       return t_strconcat(files[i], t_strcut(name, '\n'),
+                                          NULL);
+               }
+       }
+       return "";
+}
+
+static const char *filesystem_get(const char *mail_location)
+{
+       struct mountpoint mp;
+       const char *path;
+
+       path = strchr(mail_location, ':');
+       if (path == NULL)
+               path = mail_location;
+       else
+               path = t_strcut(path + 1, ':');
+       if (*path == '~') {
+               /* we don't know where users' home dirs are */
+               return "";
+       }
+       path = t_strcut(path, '%');
+       if (strlen(path) <= 1)
+               return "";
+
+       /* all in all it seems we can support only /<path>/%u style location */
+       if (mountpoint_get(path, pool_datastack_create(), &mp) < 0)
+               return "";
+       return mp.type == NULL ? "" : mp.type;
+}
+
+const char *sysinfo_get(const char *mail_location)
+{
+       const char *distro = "", *fs, *uname_info = "";
+#ifdef HAVE_SYS_UTSNAME_H
+       struct utsname u;
+
+       if (uname(&u) < 0)
+               i_error("uname() failed: %m");
+       else {
+               uname_info = t_strdup_printf("%s %s %s",
+                                            u.sysname, u.release, u.machine);
+       }
+       if (strcmp(u.sysname, "Linux") == 0)
+               distro = distro_get();
+#endif
+       fs = filesystem_get(mail_location);
+       if (*uname_info == '\0' && *distro == '\0' && *fs == '\0')
+               return "";
+       return t_strdup_printf("OS: %s %s %s %s %s", u.sysname, u.release, u.machine, distro, fs);
+}
diff --git a/src/config/sysinfo-get.h b/src/config/sysinfo-get.h
new file mode 100644 (file)
index 0000000..0f319cb
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef SYSINFO_GET_H
+#define SYSINFO_GET_H
+
+const char *sysinfo_get(const char *mail_location);
+
+#endif