bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#include "lib.h"
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#include "mountpoint.h"
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#include "strescape.h"
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#include "sysinfo-get.h"
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#include <unistd.h>
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#include <fcntl.h>
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#include <sys/stat.h>
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#ifdef HAVE_SYS_UTSNAME_H
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen# include <sys/utsname.h>
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#endif
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainenstatic bool readfile(const char *path, const char **data_r)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen{
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen char buf[1024];
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen int fd, ret;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen fd = open(path, O_RDONLY);
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (fd == -1)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return FALSE;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen ret = read(fd, buf, sizeof(buf));
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&fd);
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (ret <= 0)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return FALSE;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen *data_r = t_strndup(buf, ret);
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return TRUE;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen}
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainenstatic bool lsb_distro_get(const char *path, const char **name_r)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen{
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen const char *data, *const *p, *str, *end;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (!readfile(path, &data))
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return FALSE;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
ba5c8b0ae7460752adaf911901bf263788f62c72Phil Carmody for (p = t_strsplit(data, "\n"); *p != NULL; p++) {
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (strncmp(*p, "DISTRIB_DESCRIPTION=", 20) == 0)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen break;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen }
ba5c8b0ae7460752adaf911901bf263788f62c72Phil Carmody if (*p == NULL)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return FALSE;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen str = t_strcut(*p + 20, '\n');
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (*str != '"')
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen *name_r = str;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen else {
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen end = strrchr(++str, '"');
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen *name_r = str_unescape(p_strdup_until(unsafe_data_stack_pool,
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen str, end));
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen }
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return TRUE;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen}
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainenstatic const char *distro_get(void)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen{
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen static const char *files[] = {
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "", "/etc/redhat-release",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "", "/etc/SuSE-release",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "", "/etc/mandriva-release",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "", "/etc/fedora-release",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "", "/etc/sourcemage-release",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "", "/etc/slackware-version",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "", "/etc/gentoo-release",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen "Debian ", "/etc/debian_version",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen NULL
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen };
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen const char *name;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen unsigned int i;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (lsb_distro_get("/etc/lsb-release", &name))
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return name;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen for (i = 0; files[i] != NULL; i += 2) {
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (readfile(files[i+1], &name)) {
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return t_strconcat(files[i], t_strcut(name, '\n'),
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen NULL);
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen }
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen }
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return "";
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen}
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainenstatic const char *filesystem_get(const char *mail_location)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen{
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen struct mountpoint mp;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen const char *path;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen path = strchr(mail_location, ':');
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (path == NULL)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen path = mail_location;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen else
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen path = t_strcut(path + 1, ':');
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (*path == '~') {
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen /* we don't know where users' home dirs are */
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return "";
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen }
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen path = t_strcut(path, '%');
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (strlen(path) <= 1)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return "";
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen /* all in all it seems we can support only /<path>/%u style location */
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (mountpoint_get(path, pool_datastack_create(), &mp) < 0)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return "";
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return mp.type == NULL ? "" : mp.type;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen}
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainenconst char *sysinfo_get(const char *mail_location)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen{
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen const char *distro = "", *fs, *uname_info = "";
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#ifdef HAVE_SYS_UTSNAME_H
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen struct utsname u;
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (uname(&u) < 0)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen i_error("uname() failed: %m");
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen else {
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen uname_info = t_strdup_printf("%s %s %s",
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen u.sysname, u.release, u.machine);
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen }
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (strcmp(u.sysname, "Linux") == 0)
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen distro = distro_get();
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen#endif
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen fs = filesystem_get(mail_location);
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen if (*uname_info == '\0' && *distro == '\0' && *fs == '\0')
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return "";
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen return t_strdup_printf("OS: %s %s %s %s %s", u.sysname, u.release, u.machine, distro, fs);
c1847a38dfbc8bad29547d96432ef9d707dbd345Timo Sirainen}