1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/* Copyright (c) 2008-2018 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));
i_close_fd(&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 != NULL; p++) {
if (str_begins(*p, "DISTRIB_DESCRIPTION="))
break;
}
if (*p == NULL)
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);
}
|