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