1 #include "configator.h"
2 #include "dragonfail.h"
3 
4 #include "inputs.h"
5 #include "config.h"
6 #include "utils.h"
7 
8 #include <dirent.h>
9 #include <limits.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/ioctl.h>
14 #include <unistd.h>
15 
16 #if defined(__DragonFly__) || defined(__FreeBSD__)
17 	#include <sys/consio.h>
18 #else // linux
19 	#include <linux/vt.h>
20 #endif
21 
desktop_crawl(struct desktop * target,char * sessions,enum display_server server)22 void desktop_crawl(
23 	struct desktop* target,
24 	char* sessions,
25 	enum display_server server)
26 {
27 	DIR* dir;
28 	struct dirent* dir_info;
29 	int ok;
30 
31 	ok = access(sessions, F_OK);
32 
33 	if (ok == -1)
34 	{
35 		dgn_throw(DGN_XSESSIONS_DIR);
36 		return;
37 	}
38 
39 	dir = opendir(sessions);
40 
41 	if (dir == NULL)
42 	{
43 		dgn_throw(DGN_XSESSIONS_OPEN);
44 		return;
45 	}
46 
47 	char* name = NULL;
48 	char* exec = NULL;
49 
50 	struct configator_param map_desktop[] =
51 	{
52 		{"Exec", &exec, config_handle_str},
53 		{"Name", &name, config_handle_str},
54 	};
55 
56 	struct configator_param* map[] =
57 	{
58 		NULL,
59 		map_desktop,
60 	};
61 
62 	struct configator_param sections[] =
63 	{
64 		{"Desktop Entry", NULL, NULL},
65 	};
66 
67 	uint16_t map_len[] = {0, 2};
68 	uint16_t sections_len = 1;
69 
70 	struct configator desktop_config;
71 	desktop_config.map = map;
72 	desktop_config.map_len = map_len;
73 	desktop_config.sections = sections;
74 	desktop_config.sections_len = sections_len;
75 
76 #if defined(NAME_MAX)
77 	char path[NAME_MAX];
78 #elif defined(_POSIX_PATH_MAX)
79 	char path[_POSIX_PATH_MAX];
80 #else
81 	char path[1024];
82 #endif
83 
84 	dir_info = readdir(dir);
85 
86 	while (dir_info != NULL)
87 	{
88 		if ((dir_info->d_name)[0] == '.')
89 		{
90 			dir_info = readdir(dir);
91 			continue;
92 		}
93 
94 		snprintf(path, (sizeof (path)) - 1, "%s/", sessions);
95 		strncat(path, dir_info->d_name, (sizeof (path)) - 1);
96 		configator(&desktop_config, path);
97 
98 		// if these are wayland sessions, add " (Wayland)" to their names,
99 		// as long as their names don't already contain that string
100 		if (server == DS_WAYLAND && config.wayland_specifier)
101 		{
102 			const char wayland_specifier[] = " (Wayland)";
103 			if (strstr(name, wayland_specifier) == NULL)
104 			{
105 				name = realloc(name, (strlen(name) + sizeof(wayland_specifier) + 1));
106 				// using strcat is safe because the string is constant
107 				strcat(name, wayland_specifier);
108 			}
109 		}
110 
111 		if ((name != NULL) && (exec != NULL))
112 		{
113 			input_desktop_add(target, name, exec, server);
114 		}
115 
116 		name = NULL;
117 		exec = NULL;
118 		dir_info = readdir(dir);
119 	}
120 
121 	closedir(dir);
122 }
123 
desktop_load(struct desktop * target)124 void desktop_load(struct desktop* target)
125 {
126 	// we don't care about desktop environments presence
127 	// because the fallback shell is always available
128 	// so we just dismiss any "throw" for now
129 	int err = 0;
130 
131 	desktop_crawl(target, config.waylandsessions, DS_WAYLAND);
132 
133 	if (dgn_catch())
134 	{
135 		++err;
136 		dgn_reset();
137 	}
138 
139 	desktop_crawl(target, config.xsessions, DS_XORG);
140 
141 	if (dgn_catch())
142 	{
143 		++err;
144 		dgn_reset();
145 	}
146 }
147 
148 static char* hostname_backup = NULL;
149 
hostname(char ** out)150 void hostname(char** out)
151 {
152 	if (hostname_backup != NULL)
153 	{
154 		*out = hostname_backup;
155 		return;
156 	}
157 
158 	int maxlen = sysconf(_SC_HOST_NAME_MAX);
159 
160 	if (maxlen < 0)
161 	{
162 		maxlen = _POSIX_HOST_NAME_MAX;
163 	}
164 
165 	hostname_backup = malloc(maxlen + 1);
166 
167 	if (hostname_backup == NULL)
168 	{
169 		dgn_throw(DGN_ALLOC);
170 		return;
171 	}
172 
173 	if (gethostname(hostname_backup, maxlen) < 0)
174 	{
175 		dgn_throw(DGN_HOSTNAME);
176 		return;
177 	}
178 
179 	hostname_backup[maxlen] = '\0';
180 	*out = hostname_backup;
181 }
182 
free_hostname()183 void free_hostname()
184 {
185 	free(hostname_backup);
186 }
187 
switch_tty(struct term_buf * buf)188 void switch_tty(struct term_buf* buf)
189 {
190 	FILE* console = fopen(config.console_dev, "w");
191 
192 	if (console == NULL)
193 	{
194 		buf->info_line = lang.err_console_dev;
195 		return;
196 	}
197 
198 	int fd = fileno(console);
199 
200 	ioctl(fd, VT_ACTIVATE, config.tty);
201 	ioctl(fd, VT_WAITACTIVE, config.tty);
202 
203 	fclose(console);
204 }
205 
save(struct desktop * desktop,struct text * login)206 void save(struct desktop* desktop, struct text* login)
207 {
208 	if (config.save)
209 	{
210 		FILE* fp = fopen(config.save_file, "wb+");
211 
212 		if (fp != NULL)
213 		{
214 			fprintf(fp, "%s\n%d", login->text, desktop->cur);
215 			fclose(fp);
216 		}
217 	}
218 }
219 
load(struct desktop * desktop,struct text * login)220 void load(struct desktop* desktop, struct text* login)
221 {
222 	if (!config.load)
223 	{
224 		return;
225 	}
226 
227 	FILE* fp = fopen(config.save_file, "rb");
228 
229 	if (fp == NULL)
230 	{
231 		return;
232 	}
233 
234 	char* line = malloc(config.max_login_len + 1);
235 
236 	if (line == NULL)
237 	{
238 		fclose(fp);
239 		return;
240 	}
241 
242 	if (fgets(line, config.max_login_len + 1, fp))
243 	{
244 		int len = strlen(line);
245 		strncpy(login->text, line, login->len);
246 
247 		if (len == 0)
248 		{
249 			login->end = login->text;
250 		}
251 		else
252 		{
253 			login->end = login->text + len - 1;
254 			login->text[len - 1] = '\0';
255 		}
256 	}
257 	else
258 	{
259 		fclose(fp);
260 		free(line);
261 		return;
262 	}
263 
264 	if (fgets(line, config.max_login_len + 1, fp))
265 	{
266 		int saved_cur = abs(atoi(line));
267 
268 		if (saved_cur < desktop->len)
269 		{
270 			desktop->cur = saved_cur;
271 		}
272 	}
273 
274 	fclose(fp);
275 	free(line);
276 }
277