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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
#include "lm.h"
#include "common/properties.h"
#include "common/dbus.h"
#include "common/processing.h"
#include "detection/displayserver/displayserver.h"
#include <unistd.h>
#define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/"
#define FF_SYSTEMD_USERS_PATH "/run/systemd/users/"
static const char* getGdmVersion(FFstrbuf* version) {
const char* error = ffProcessAppendStdOut(version, (char* const[]) { "gdm", "--version", NULL });
if (error || version->length == 0) {
error = ffProcessAppendStdOut(version, (char* const[]) { "gdm3", "--version", NULL });
if (error || version->length == 0) {
return "Failed to get GDM version";
}
}
// GDM 44.1
ffStrbufSubstrAfterFirstC(version, ' ');
return NULL;
}
static const char* getSshdVersion(FFstrbuf* version) {
const char* error = ffProcessAppendStdErr(version, (char* const[]) { "sshd", "-V", NULL });
if (error) {
return error;
}
// OpenSSH_9.0p1, OpenSSL 3.0.9 30 May 2023...
ffStrbufSubstrBeforeFirstC(version, ',');
ffStrbufSubstrAfterFirstC(version, '_');
return NULL;
}
#ifdef FF_HAVE_ZLIB
#include "common/library.h"
#include <stdlib.h>
#include <zlib.h>
static const char* getSddmVersion(FFstrbuf* version) {
FF_LIBRARY_LOAD_MESSAGE(zlib, "libz" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzopen)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzread)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzerror)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gztell)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose)
gzFile file = ffgzopen(FASTFETCH_TARGET_DIR_USR "/share/man/man1/sddm.1.gz", "rb");
if (file == Z_NULL) {
return "ffgzopen(\"/usr/share/man/man1/sddm.1.gz\", \"rb\") failed";
}
ffStrbufEnsureFree(version, 2047);
memset(version->chars, 0, version->allocated);
int size = ffgzread(file, version->chars, version->allocated - 1);
ffgzclose(file);
if (size <= 0) {
return "ffgzread(file, version->chars, version->length) failed";
}
version->length = (uint32_t) size;
uint32_t index = ffStrbufFirstIndexS(version, ".TH ");
if (index == version->length) {
ffStrbufClear(version);
return ".TH is not found";
}
ffStrbufSubstrBefore(version, ffStrbufNextIndexC(version, index, '\n'));
ffStrbufSubstrAfter(version, index + (uint32_t) strlen(".TH "));
// "SDDM" 1 "May 2014" "sddm 0.20.0" "sddm"
ffStrbufSubstrBeforeLastC(version, ' ');
ffStrbufTrimRight(version, '"');
ffStrbufSubstrAfterLastC(version, ' ');
return NULL;
}
#else
static const char* getSddmVersion(FF_A_UNUSED FFstrbuf* version) {
return "Fastfetch is built without libz support";
}
#endif
static const char* getXfwmVersion(FFstrbuf* version) {
const char* error = ffProcessAppendStdOut(version, (char* const[]) { "xfwm4", "--version", NULL });
if (error) {
return error;
}
// This is xfwm4 version 4.18.0 (revision 7e7473c5b) for Xfce 4.18...
ffStrbufSubstrAfterFirstS(version, "version ");
ffStrbufSubstrBeforeFirstC(version, ' ');
return NULL;
}
static const char* getLightdmVersion(FFstrbuf* version) {
const char* error = ffProcessAppendStdErr(version, (char* const[]) { "lightdm", "--version", NULL });
if (error) {
return error;
}
// lightdm 1.30.0
ffStrbufSubstrAfterFirstC(version, ' ');
ffStrbufTrimRight(version, '\n');
return NULL;
}
const char* ffDetectLM(FFLMResult* result) {
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY sessionId = ffStrbufCreateS(getenv("XDG_SESSION_ID"));
if (sessionId.length == 0) {
// On some incorrectly configured systems, $XDG_SESSION_ID is not set. Try finding it ourself
// WARNING: This is private data. Do not parse
ffStrbufSetF(&path, FF_SYSTEMD_USERS_PATH "%d", instance.state.platform.uid);
// This is actually buggy, and assumes current user is using DE
// `sd_pid_get_session` can be a better option, but we need to find a pid to use
if (!ffParsePropFileValues(path.chars, 1, (FFpropquery[]) {
{ "DISPLAY=", &sessionId },
})) {
return "Failed to get $XDG_SESSION_ID";
}
}
ffStrbufSetS(&path, FF_SYSTEMD_SESSIONS_PATH);
ffStrbufAppend(&path, &sessionId);
// WARNING: This is private data. Do not parse
if (!ffParsePropFileValues(path.chars, 2, (FFpropquery[]) {
{ "SERVICE=", &result->service },
{ "TYPE=", &result->type },
})) {
return "Failed to parse " FF_SYSTEMD_SESSIONS_PATH "$XDG_SESSION_ID";
}
if (instance.config.general.detectVersion) {
if (ffStrbufStartsWithS(&result->service, "gdm")) {
getGdmVersion(&result->version);
} else if (ffStrbufStartsWithS(&result->service, "sddm")) {
getSddmVersion(&result->version);
} else if (ffStrbufStartsWithS(&result->service, "xfwm")) {
getXfwmVersion(&result->version);
} else if (ffStrbufStartsWithS(&result->service, "lightdm")) {
getLightdmVersion(&result->version);
} else if (ffStrbufStartsWithS(&result->service, "sshd")) {
getSshdVersion(&result->version);
}
}
// Correct char cases
if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_WAYLAND)) {
ffStrbufSetS(&result->type, FF_WM_PROTOCOL_WAYLAND);
} else if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_X11)) {
ffStrbufSetS(&result->type, FF_WM_PROTOCOL_X11);
} else if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_TTY)) {
ffStrbufSetS(&result->type, FF_WM_PROTOCOL_TTY);
}
return NULL;
}
|