diff options
Diffstat (limited to 'sway/main.c')
-rw-r--r-- | sway/main.c | 83 |
1 files changed, 53 insertions, 30 deletions
diff --git a/sway/main.c b/sway/main.c index a325dc3a..a20f1dac 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #define _XOPEN_SOURCE 700 | 1 | #define _XOPEN_SOURCE 700 |
2 | #define _POSIX_C_SOURCE 200112L | 2 | #define _POSIX_C_SOURCE 200112L |
3 | #include <getopt.h> | 3 | #include <getopt.h> |
4 | #include <pango/pangocairo.h> | ||
4 | #include <signal.h> | 5 | #include <signal.h> |
5 | #include <stdbool.h> | 6 | #include <stdbool.h> |
6 | #include <stdlib.h> | 7 | #include <stdlib.h> |
@@ -19,6 +20,7 @@ | |||
19 | #include "sway/commands.h" | 20 | #include "sway/commands.h" |
20 | #include "sway/config.h" | 21 | #include "sway/config.h" |
21 | #include "sway/debug.h" | 22 | #include "sway/debug.h" |
23 | #include "sway/desktop/transaction.h" | ||
22 | #include "sway/server.h" | 24 | #include "sway/server.h" |
23 | #include "sway/tree/layout.h" | 25 | #include "sway/tree/layout.h" |
24 | #include "sway/ipc-server.h" | 26 | #include "sway/ipc-server.h" |
@@ -128,7 +130,7 @@ static void log_env() { | |||
128 | "SWAYSOCK" | 130 | "SWAYSOCK" |
129 | }; | 131 | }; |
130 | for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { | 132 | for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { |
131 | wlr_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); | 133 | wlr_log(WLR_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); |
132 | } | 134 | } |
133 | } | 135 | } |
134 | 136 | ||
@@ -143,14 +145,14 @@ static void log_distro() { | |||
143 | for (size_t i = 0; i < sizeof(paths) / sizeof(char *); ++i) { | 145 | for (size_t i = 0; i < sizeof(paths) / sizeof(char *); ++i) { |
144 | FILE *f = fopen(paths[i], "r"); | 146 | FILE *f = fopen(paths[i], "r"); |
145 | if (f) { | 147 | if (f) { |
146 | wlr_log(L_INFO, "Contents of %s:", paths[i]); | 148 | wlr_log(WLR_INFO, "Contents of %s:", paths[i]); |
147 | while (!feof(f)) { | 149 | while (!feof(f)) { |
148 | char *line; | 150 | char *line; |
149 | if (!(line = read_line(f))) { | 151 | if (!(line = read_line(f))) { |
150 | break; | 152 | break; |
151 | } | 153 | } |
152 | if (*line) { | 154 | if (*line) { |
153 | wlr_log(L_INFO, "%s", line); | 155 | wlr_log(WLR_INFO, "%s", line); |
154 | } | 156 | } |
155 | free(line); | 157 | free(line); |
156 | } | 158 | } |
@@ -162,7 +164,7 @@ static void log_distro() { | |||
162 | static void log_kernel() { | 164 | static void log_kernel() { |
163 | FILE *f = popen("uname -a", "r"); | 165 | FILE *f = popen("uname -a", "r"); |
164 | if (!f) { | 166 | if (!f) { |
165 | wlr_log(L_INFO, "Unable to determine kernel version"); | 167 | wlr_log(WLR_INFO, "Unable to determine kernel version"); |
166 | return; | 168 | return; |
167 | } | 169 | } |
168 | while (!feof(f)) { | 170 | while (!feof(f)) { |
@@ -171,25 +173,25 @@ static void log_kernel() { | |||
171 | break; | 173 | break; |
172 | } | 174 | } |
173 | if (*line) { | 175 | if (*line) { |
174 | wlr_log(L_INFO, "%s", line); | 176 | wlr_log(WLR_INFO, "%s", line); |
175 | } | 177 | } |
176 | free(line); | 178 | free(line); |
177 | } | 179 | } |
178 | fclose(f); | 180 | pclose(f); |
179 | } | 181 | } |
180 | 182 | ||
181 | static void security_sanity_check() { | 183 | static void security_sanity_check() { |
182 | // TODO: Notify users visually if this has issues | 184 | // TODO: Notify users visually if this has issues |
183 | struct stat s; | 185 | struct stat s; |
184 | if (stat("/proc", &s)) { | 186 | if (stat("/proc", &s)) { |
185 | wlr_log(L_ERROR, | 187 | wlr_log(WLR_ERROR, |
186 | "!! DANGER !! /proc is not available - sway CANNOT enforce security rules!"); | 188 | "!! DANGER !! /proc is not available - sway CANNOT enforce security rules!"); |
187 | } | 189 | } |
188 | #ifdef __linux__ | 190 | #ifdef __linux__ |
189 | cap_flag_value_t v; | 191 | cap_flag_value_t v; |
190 | cap_t cap = cap_get_proc(); | 192 | cap_t cap = cap_get_proc(); |
191 | if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) { | 193 | if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) { |
192 | wlr_log(L_ERROR, | 194 | wlr_log(WLR_ERROR, |
193 | "!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users."); | 195 | "!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users."); |
194 | } | 196 | } |
195 | if (cap) { | 197 | if (cap) { |
@@ -205,13 +207,13 @@ static void executable_sanity_check() { | |||
205 | stat(exe, &sb); | 207 | stat(exe, &sb); |
206 | // We assume that cap_get_file returning NULL implies ENODATA | 208 | // We assume that cap_get_file returning NULL implies ENODATA |
207 | if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { | 209 | if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { |
208 | wlr_log(L_ERROR, | 210 | wlr_log(WLR_ERROR, |
209 | "sway executable has both the s(g)uid bit AND file caps set."); | 211 | "sway executable has both the s(g)uid bit AND file caps set."); |
210 | wlr_log(L_ERROR, | 212 | wlr_log(WLR_ERROR, |
211 | "This is strongly discouraged (and completely broken)."); | 213 | "This is strongly discouraged (and completely broken)."); |
212 | wlr_log(L_ERROR, | 214 | wlr_log(WLR_ERROR, |
213 | "Please clear one of them (either the suid bit, or the file caps)."); | 215 | "Please clear one of them (either the suid bit, or the file caps)."); |
214 | wlr_log(L_ERROR, | 216 | wlr_log(WLR_ERROR, |
215 | "If unsure, strip the file caps."); | 217 | "If unsure, strip the file caps."); |
216 | exit(EXIT_FAILURE); | 218 | exit(EXIT_FAILURE); |
217 | } | 219 | } |
@@ -222,16 +224,16 @@ static void executable_sanity_check() { | |||
222 | static void drop_permissions(bool keep_caps) { | 224 | static void drop_permissions(bool keep_caps) { |
223 | if (getuid() != geteuid() || getgid() != getegid()) { | 225 | if (getuid() != geteuid() || getgid() != getegid()) { |
224 | if (setgid(getgid()) != 0) { | 226 | if (setgid(getgid()) != 0) { |
225 | wlr_log(L_ERROR, "Unable to drop root"); | 227 | wlr_log(WLR_ERROR, "Unable to drop root"); |
226 | exit(EXIT_FAILURE); | 228 | exit(EXIT_FAILURE); |
227 | } | 229 | } |
228 | if (setuid(getuid()) != 0) { | 230 | if (setuid(getuid()) != 0) { |
229 | wlr_log(L_ERROR, "Unable to drop root"); | 231 | wlr_log(WLR_ERROR, "Unable to drop root"); |
230 | exit(EXIT_FAILURE); | 232 | exit(EXIT_FAILURE); |
231 | } | 233 | } |
232 | } | 234 | } |
233 | if (setuid(0) != -1) { | 235 | if (setuid(0) != -1) { |
234 | wlr_log(L_ERROR, "Root privileges can be restored."); | 236 | wlr_log(WLR_ERROR, "Root privileges can be restored."); |
235 | exit(EXIT_FAILURE); | 237 | exit(EXIT_FAILURE); |
236 | } | 238 | } |
237 | #ifdef __linux__ | 239 | #ifdef __linux__ |
@@ -239,17 +241,29 @@ static void drop_permissions(bool keep_caps) { | |||
239 | // Drop every cap except CAP_SYS_PTRACE | 241 | // Drop every cap except CAP_SYS_PTRACE |
240 | cap_t caps = cap_init(); | 242 | cap_t caps = cap_init(); |
241 | cap_value_t keep = CAP_SYS_PTRACE; | 243 | cap_value_t keep = CAP_SYS_PTRACE; |
242 | wlr_log(L_INFO, "Dropping extra capabilities"); | 244 | wlr_log(WLR_INFO, "Dropping extra capabilities"); |
243 | if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || | 245 | if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || |
244 | cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || | 246 | cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || |
245 | cap_set_proc(caps)) { | 247 | cap_set_proc(caps)) { |
246 | wlr_log(L_ERROR, "Failed to drop extra capabilities"); | 248 | wlr_log(WLR_ERROR, "Failed to drop extra capabilities"); |
247 | exit(EXIT_FAILURE); | 249 | exit(EXIT_FAILURE); |
248 | } | 250 | } |
249 | } | 251 | } |
250 | #endif | 252 | #endif |
251 | } | 253 | } |
252 | 254 | ||
255 | void enable_debug_flag(const char *flag) { | ||
256 | if (strcmp(flag, "render-tree") == 0) { | ||
257 | enable_debug_tree = true; | ||
258 | } else if (strncmp(flag, "damage=", 7) == 0) { | ||
259 | damage_debug = &flag[7]; | ||
260 | } else if (strcmp(flag, "txn-debug") == 0) { | ||
261 | txn_debug = true; | ||
262 | } else if (strncmp(flag, "txn-timeout=", 12) == 0) { | ||
263 | txn_timeout_ms = atoi(&flag[12]); | ||
264 | } | ||
265 | } | ||
266 | |||
253 | int main(int argc, char **argv) { | 267 | int main(int argc, char **argv) { |
254 | static int verbose = 0, debug = 0, validate = 0; | 268 | static int verbose = 0, debug = 0, validate = 0; |
255 | 269 | ||
@@ -289,7 +303,7 @@ int main(int argc, char **argv) { | |||
289 | int c; | 303 | int c; |
290 | while (1) { | 304 | while (1) { |
291 | int option_index = 0; | 305 | int option_index = 0; |
292 | c = getopt_long(argc, argv, "hCdDvVc:", long_options, &option_index); | 306 | c = getopt_long(argc, argv, "hCdD:vVc:", long_options, &option_index); |
293 | if (c == -1) { | 307 | if (c == -1) { |
294 | break; | 308 | break; |
295 | } | 309 | } |
@@ -308,7 +322,7 @@ int main(int argc, char **argv) { | |||
308 | debug = 1; | 322 | debug = 1; |
309 | break; | 323 | break; |
310 | case 'D': // extended debug options | 324 | case 'D': // extended debug options |
311 | enable_debug_tree = true; | 325 | enable_debug_flag(optarg); |
312 | break; | 326 | break; |
313 | case 'v': // version | 327 | case 'v': // version |
314 | fprintf(stdout, "sway version " SWAY_VERSION "\n"); | 328 | fprintf(stdout, "sway version " SWAY_VERSION "\n"); |
@@ -334,22 +348,22 @@ int main(int argc, char **argv) { | |||
334 | 348 | ||
335 | // TODO: switch logging over to wlroots? | 349 | // TODO: switch logging over to wlroots? |
336 | if (debug) { | 350 | if (debug) { |
337 | wlr_log_init(L_DEBUG, NULL); | 351 | wlr_log_init(WLR_DEBUG, NULL); |
338 | } else if (verbose || validate) { | 352 | } else if (verbose || validate) { |
339 | wlr_log_init(L_INFO, NULL); | 353 | wlr_log_init(WLR_INFO, NULL); |
340 | } else { | 354 | } else { |
341 | wlr_log_init(L_ERROR, NULL); | 355 | wlr_log_init(WLR_ERROR, NULL); |
342 | } | 356 | } |
343 | 357 | ||
344 | if (optind < argc) { // Behave as IPC client | 358 | if (optind < argc) { // Behave as IPC client |
345 | if(optind != 1) { | 359 | if(optind != 1) { |
346 | wlr_log(L_ERROR, "Don't use options with the IPC client"); | 360 | wlr_log(WLR_ERROR, "Don't use options with the IPC client"); |
347 | exit(EXIT_FAILURE); | 361 | exit(EXIT_FAILURE); |
348 | } | 362 | } |
349 | drop_permissions(false); | 363 | drop_permissions(false); |
350 | char *socket_path = getenv("SWAYSOCK"); | 364 | char *socket_path = getenv("SWAYSOCK"); |
351 | if (!socket_path) { | 365 | if (!socket_path) { |
352 | wlr_log(L_ERROR, "Unable to retrieve socket path"); | 366 | wlr_log(WLR_ERROR, "Unable to retrieve socket path"); |
353 | exit(EXIT_FAILURE); | 367 | exit(EXIT_FAILURE); |
354 | } | 368 | } |
355 | char *command = join_args(argv + optind, argc - optind); | 369 | char *command = join_args(argv + optind, argc - optind); |
@@ -368,7 +382,7 @@ int main(int argc, char **argv) { | |||
368 | if (getuid() != geteuid() || getgid() != getegid()) { | 382 | if (getuid() != geteuid() || getgid() != getegid()) { |
369 | // Retain capabilities after setuid() | 383 | // Retain capabilities after setuid() |
370 | if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { | 384 | if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { |
371 | wlr_log(L_ERROR, "Cannot keep caps after setuid()"); | 385 | wlr_log(WLR_ERROR, "Cannot keep caps after setuid()"); |
372 | exit(EXIT_FAILURE); | 386 | exit(EXIT_FAILURE); |
373 | } | 387 | } |
374 | suid = true; | 388 | suid = true; |
@@ -389,7 +403,7 @@ int main(int argc, char **argv) { | |||
389 | // prevent ipc from crashing sway | 403 | // prevent ipc from crashing sway |
390 | signal(SIGPIPE, SIG_IGN); | 404 | signal(SIGPIPE, SIG_IGN); |
391 | 405 | ||
392 | wlr_log(L_INFO, "Starting sway version " SWAY_VERSION); | 406 | wlr_log(WLR_INFO, "Starting sway version " SWAY_VERSION); |
393 | 407 | ||
394 | layout_init(); | 408 | layout_init(); |
395 | 409 | ||
@@ -415,32 +429,41 @@ int main(int argc, char **argv) { | |||
415 | 429 | ||
416 | security_sanity_check(); | 430 | security_sanity_check(); |
417 | 431 | ||
432 | setenv("WAYLAND_DISPLAY", server.socket, true); | ||
433 | if (!terminate_request) { | ||
434 | if (!server_start_backend(&server)) { | ||
435 | sway_terminate(EXIT_FAILURE); | ||
436 | } | ||
437 | } | ||
438 | |||
418 | config->active = true; | 439 | config->active = true; |
419 | // Execute commands until there are none left | 440 | // Execute commands until there are none left |
441 | wlr_log(WLR_DEBUG, "Running deferred commands"); | ||
420 | while (config->cmd_queue->length) { | 442 | while (config->cmd_queue->length) { |
421 | char *line = config->cmd_queue->items[0]; | 443 | char *line = config->cmd_queue->items[0]; |
422 | struct cmd_results *res = execute_command(line, NULL); | 444 | struct cmd_results *res = execute_command(line, NULL); |
423 | if (res->status != CMD_SUCCESS) { | 445 | if (res->status != CMD_SUCCESS) { |
424 | wlr_log(L_ERROR, "Error on line '%s': %s", line, res->error); | 446 | wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error); |
425 | } | 447 | } |
426 | free_cmd_results(res); | 448 | free_cmd_results(res); |
427 | free(line); | 449 | free(line); |
428 | list_del(config->cmd_queue, 0); | 450 | list_del(config->cmd_queue, 0); |
429 | } | 451 | } |
452 | transaction_commit_dirty(); | ||
430 | 453 | ||
431 | if (!terminate_request) { | 454 | if (!terminate_request) { |
432 | server_run(&server); | 455 | server_run(&server); |
433 | } | 456 | } |
434 | 457 | ||
435 | wlr_log(L_INFO, "Shutting down sway"); | 458 | wlr_log(WLR_INFO, "Shutting down sway"); |
436 | 459 | ||
437 | server_fini(&server); | 460 | server_fini(&server); |
438 | 461 | ||
439 | ipc_terminate(); | ||
440 | |||
441 | if (config) { | 462 | if (config) { |
442 | free_config(config); | 463 | free_config(config); |
443 | } | 464 | } |
444 | 465 | ||
466 | pango_cairo_font_map_set_default(NULL); | ||
467 | |||
445 | return exit_value; | 468 | return exit_value; |
446 | } | 469 | } |