aboutsummaryrefslogtreecommitdiffstats
path: root/sway/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/main.c')
-rw-r--r--sway/main.c225
1 files changed, 84 insertions, 141 deletions
diff --git a/sway/main.c b/sway/main.c
index 0c219fb3..73254dc2 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -6,12 +6,14 @@
6#include <stdio.h> 6#include <stdio.h>
7#include <stdlib.h> 7#include <stdlib.h>
8#include <string.h> 8#include <string.h>
9#include <sys/resource.h>
9#include <sys/stat.h> 10#include <sys/stat.h>
10#include <sys/types.h> 11#include <sys/types.h>
11#include <sys/wait.h> 12#include <sys/wait.h>
12#include <sys/un.h> 13#include <sys/un.h>
13#include <unistd.h> 14#include <unistd.h>
14#include <wlr/util/log.h> 15#include <wlr/util/log.h>
16#include <wlr/version.h>
15#include "sway/commands.h" 17#include "sway/commands.h"
16#include "sway/config.h" 18#include "sway/config.h"
17#include "sway/server.h" 19#include "sway/server.h"
@@ -26,6 +28,7 @@
26 28
27static bool terminate_request = false; 29static bool terminate_request = false;
28static int exit_value = 0; 30static int exit_value = 0;
31static struct rlimit original_nofile_rlimit = {0};
29struct sway_server server = {0}; 32struct sway_server server = {0};
30struct sway_debug debug = {0}; 33struct sway_debug debug = {0};
31 34
@@ -46,81 +49,6 @@ void sig_handler(int signal) {
46 sway_terminate(EXIT_SUCCESS); 49 sway_terminate(EXIT_SUCCESS);
47} 50}
48 51
49void detect_raspi(void) {
50 bool raspi = false;
51 FILE *f = fopen("/sys/firmware/devicetree/base/model", "r");
52 if (!f) {
53 return;
54 }
55 char *line = NULL;
56 size_t line_size = 0;
57 while (getline(&line, &line_size, f) != -1) {
58 if (strstr(line, "Raspberry Pi")) {
59 raspi = true;
60 break;
61 }
62 }
63 fclose(f);
64 FILE *g = fopen("/proc/modules", "r");
65 if (!g) {
66 free(line);
67 return;
68 }
69 bool vc4 = false;
70 while (getline(&line, &line_size, g) != -1) {
71 if (strstr(line, "vc4")) {
72 vc4 = true;
73 break;
74 }
75 }
76 free(line);
77 fclose(g);
78 if (!vc4 && raspi) {
79 fprintf(stderr, "\x1B[1;31mWarning: You have a "
80 "Raspberry Pi, but the vc4 Module is "
81 "not loaded! Set 'dtoverlay=vc4-kms-v3d'"
82 "in /boot/config.txt and reboot.\x1B[0m\n");
83 }
84}
85
86void detect_proprietary(int allow_unsupported_gpu) {
87 FILE *f = fopen("/proc/modules", "r");
88 if (!f) {
89 return;
90 }
91 char *line = NULL;
92 size_t line_size = 0;
93 while (getline(&line, &line_size, f) != -1) {
94 if (strncmp(line, "nvidia ", 7) == 0) {
95 if (allow_unsupported_gpu) {
96 sway_log(SWAY_ERROR,
97 "!!! Proprietary Nvidia drivers are in use !!!");
98 } else {
99 sway_log(SWAY_ERROR,
100 "Proprietary Nvidia drivers are NOT supported. "
101 "Use Nouveau. To launch sway anyway, launch with "
102 "--my-next-gpu-wont-be-nvidia and DO NOT report issues.");
103 exit(EXIT_FAILURE);
104 }
105 break;
106 }
107 if (strstr(line, "fglrx")) {
108 if (allow_unsupported_gpu) {
109 sway_log(SWAY_ERROR,
110 "!!! Proprietary AMD drivers are in use !!!");
111 } else {
112 sway_log(SWAY_ERROR, "Proprietary AMD drivers do NOT support "
113 "Wayland. Use radeon. To try anyway, launch sway with "
114 "--unsupported-gpu and DO NOT report issues.");
115 exit(EXIT_FAILURE);
116 }
117 break;
118 }
119 }
120 free(line);
121 fclose(f);
122}
123
124void run_as_ipc_client(char *command, char *socket_path) { 52void run_as_ipc_client(char *command, char *socket_path) {
125 int socketfd = ipc_open_socket(socket_path); 53 int socketfd = ipc_open_socket(socket_path);
126 uint32_t len = strlen(command); 54 uint32_t len = strlen(command);
@@ -184,33 +112,49 @@ static void log_kernel(void) {
184 pclose(f); 112 pclose(f);
185} 113}
186 114
187 115static bool detect_suid(void) {
188static bool drop_permissions(void) { 116 if (geteuid() != 0 && getegid() != 0) {
189 if (getuid() != geteuid() || getgid() != getegid()) { 117 return false;
190 // Set the gid and uid in the correct order.
191 if (setgid(getgid()) != 0) {
192 sway_log(SWAY_ERROR, "Unable to drop root group, refusing to start");
193 return false;
194 }
195 if (setuid(getuid()) != 0) {
196 sway_log(SWAY_ERROR, "Unable to drop root user, refusing to start");
197 return false;
198 }
199 } 118 }
200 if (setgid(0) != -1 || setuid(0) != -1) { 119
201 sway_log(SWAY_ERROR, "Unable to drop root (we shouldn't be able to " 120 if (getuid() == geteuid() && getgid() == getegid()) {
202 "restore it after setuid), refusing to start");
203 return false; 121 return false;
204 } 122 }
123
124 sway_log(SWAY_ERROR, "SUID operation is no longer supported, refusing to start. "
125 "This check will be removed in a future release.");
205 return true; 126 return true;
206} 127}
207 128
129static void increase_nofile_limit(void) {
130 if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
131 sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
132 "getrlimit(NOFILE) failed");
133 return;
134 }
135
136 struct rlimit new_rlimit = original_nofile_rlimit;
137 new_rlimit.rlim_cur = new_rlimit.rlim_max;
138 if (setrlimit(RLIMIT_NOFILE, &new_rlimit) != 0) {
139 sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
140 "setrlimit(NOFILE) failed");
141 sway_log(SWAY_INFO, "Running with %d max open files",
142 (int)original_nofile_rlimit.rlim_cur);
143 }
144}
145
146void restore_nofile_limit(void) {
147 if (original_nofile_rlimit.rlim_cur == 0) {
148 return;
149 }
150 if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
151 sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
152 "setrlimit(NOFILE) failed");
153 }
154}
155
208void enable_debug_flag(const char *flag) { 156void enable_debug_flag(const char *flag) {
209 if (strcmp(flag, "damage=highlight") == 0) { 157 if (strcmp(flag, "noatomic") == 0) {
210 debug.damage = DAMAGE_HIGHLIGHT;
211 } else if (strcmp(flag, "damage=rerender") == 0) {
212 debug.damage = DAMAGE_RERENDER;
213 } else if (strcmp(flag, "noatomic") == 0) {
214 debug.noatomic = true; 158 debug.noatomic = true;
215 } else if (strcmp(flag, "txn-wait") == 0) { 159 } else if (strcmp(flag, "txn-wait") == 0) {
216 debug.txn_wait = true; 160 debug.txn_wait = true;
@@ -218,6 +162,8 @@ void enable_debug_flag(const char *flag) {
218 debug.txn_timings = true; 162 debug.txn_timings = true;
219 } else if (strncmp(flag, "txn-timeout=", 12) == 0) { 163 } else if (strncmp(flag, "txn-timeout=", 12) == 0) {
220 server.txn_timeout_ms = atoi(&flag[12]); 164 server.txn_timeout_ms = atoi(&flag[12]);
165 } else if (strcmp(flag, "legacy-wl-drm") == 0) {
166 debug.legacy_wl_drm = true;
221 } else { 167 } else {
222 sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag); 168 sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
223 } 169 }
@@ -242,36 +188,35 @@ static void handle_wlr_log(enum wlr_log_importance importance,
242 _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args); 188 _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args);
243} 189}
244 190
191static const struct option long_options[] = {
192 {"help", no_argument, NULL, 'h'},
193 {"config", required_argument, NULL, 'c'},
194 {"validate", no_argument, NULL, 'C'},
195 {"debug", no_argument, NULL, 'd'},
196 {"version", no_argument, NULL, 'v'},
197 {"verbose", no_argument, NULL, 'V'},
198 {"get-socketpath", no_argument, NULL, 'p'},
199 {"unsupported-gpu", no_argument, NULL, 'u'},
200 {0, 0, 0, 0}
201};
202
203static const char usage[] =
204 "Usage: sway [options] [command]\n"
205 "\n"
206 " -h, --help Show help message and quit.\n"
207 " -c, --config <config> Specify a config file.\n"
208 " -C, --validate Check the validity of the config file, then exit.\n"
209 " -d, --debug Enables full logging, including debug information.\n"
210 " -v, --version Show the version number and quit.\n"
211 " -V, --verbose Enables more verbose logging.\n"
212 " --get-socketpath Gets the IPC socket path and prints it, then exits.\n"
213 "\n";
214
245int main(int argc, char **argv) { 215int main(int argc, char **argv) {
246 static int verbose = 0, debug = 0, validate = 0, allow_unsupported_gpu = 0; 216 static bool verbose = false, debug = false, validate = false;
247
248 static struct option long_options[] = {
249 {"help", no_argument, NULL, 'h'},
250 {"config", required_argument, NULL, 'c'},
251 {"validate", no_argument, NULL, 'C'},
252 {"debug", no_argument, NULL, 'd'},
253 {"version", no_argument, NULL, 'v'},
254 {"verbose", no_argument, NULL, 'V'},
255 {"get-socketpath", no_argument, NULL, 'p'},
256 {"unsupported-gpu", no_argument, NULL, 'u'},
257 {"my-next-gpu-wont-be-nvidia", no_argument, NULL, 'u'},
258 {0, 0, 0, 0}
259 };
260 217
261 char *config_path = NULL; 218 char *config_path = NULL;
262 219
263 const char* usage =
264 "Usage: sway [options] [command]\n"
265 "\n"
266 " -h, --help Show help message and quit.\n"
267 " -c, --config <config> Specify a config file.\n"
268 " -C, --validate Check the validity of the config file, then exit.\n"
269 " -d, --debug Enables full logging, including debug information.\n"
270 " -v, --version Show the version number and quit.\n"
271 " -V, --verbose Enables more verbose logging.\n"
272 " --get-socketpath Gets the IPC socket path and prints it, then exits.\n"
273 "\n";
274
275 int c; 220 int c;
276 while (1) { 221 while (1) {
277 int option_index = 0; 222 int option_index = 0;
@@ -289,25 +234,25 @@ int main(int argc, char **argv) {
289 config_path = strdup(optarg); 234 config_path = strdup(optarg);
290 break; 235 break;
291 case 'C': // validate 236 case 'C': // validate
292 validate = 1; 237 validate = true;
293 break; 238 break;
294 case 'd': // debug 239 case 'd': // debug
295 debug = 1; 240 debug = true;
296 break; 241 break;
297 case 'D': // extended debug options 242 case 'D': // extended debug options
298 enable_debug_flag(optarg); 243 enable_debug_flag(optarg);
299 break; 244 break;
300 case 'u': 245 case 'u':
301 allow_unsupported_gpu = 1; 246 allow_unsupported_gpu = true;
302 break; 247 break;
303 case 'v': // version 248 case 'v': // version
304 printf("sway version " SWAY_VERSION "\n"); 249 printf("sway version " SWAY_VERSION "\n");
305 exit(EXIT_SUCCESS); 250 exit(EXIT_SUCCESS);
306 break; 251 break;
307 case 'V': // verbose 252 case 'V': // verbose
308 verbose = 1; 253 verbose = true;
309 break; 254 break;
310 case 'p': ; // --get-socketpath 255 case 'p': // --get-socketpath
311 if (getenv("SWAYSOCK")) { 256 if (getenv("SWAYSOCK")) {
312 printf("%s\n", getenv("SWAYSOCK")); 257 printf("%s\n", getenv("SWAYSOCK"));
313 exit(EXIT_SUCCESS); 258 exit(EXIT_SUCCESS);
@@ -322,6 +267,11 @@ int main(int argc, char **argv) {
322 } 267 }
323 } 268 }
324 269
270 // SUID operation is deprecated, so block it for now.
271 if (detect_suid()) {
272 exit(EXIT_FAILURE);
273 }
274
325 // Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the 275 // Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the
326 // clear error message (when not running as an IPC client). 276 // clear error message (when not running as an IPC client).
327 if (!getenv("XDG_RUNTIME_DIR") && optind == argc) { 277 if (!getenv("XDG_RUNTIME_DIR") && optind == argc) {
@@ -344,11 +294,10 @@ int main(int argc, char **argv) {
344 } 294 }
345 295
346 sway_log(SWAY_INFO, "Sway version " SWAY_VERSION); 296 sway_log(SWAY_INFO, "Sway version " SWAY_VERSION);
297 sway_log(SWAY_INFO, "wlroots version " WLR_VERSION_STR);
347 log_kernel(); 298 log_kernel();
348 log_distro(); 299 log_distro();
349 log_env(); 300 log_env();
350 detect_proprietary(allow_unsupported_gpu);
351 detect_raspi();
352 301
353 if (optind < argc) { // Behave as IPC client 302 if (optind < argc) { // Behave as IPC client
354 if (optind != 1) { 303 if (optind != 1) {
@@ -361,9 +310,6 @@ int main(int argc, char **argv) {
361 "`sway -d 2>sway.log`."); 310 "`sway -d 2>sway.log`.");
362 exit(EXIT_FAILURE); 311 exit(EXIT_FAILURE);
363 } 312 }
364 if (!drop_permissions()) {
365 exit(EXIT_FAILURE);
366 }
367 char *socket_path = getenv("SWAYSOCK"); 313 char *socket_path = getenv("SWAYSOCK");
368 if (!socket_path) { 314 if (!socket_path) {
369 sway_log(SWAY_ERROR, "Unable to retrieve socket path"); 315 sway_log(SWAY_ERROR, "Unable to retrieve socket path");
@@ -375,14 +321,7 @@ int main(int argc, char **argv) {
375 return 0; 321 return 0;
376 } 322 }
377 323
378 if (!server_privileged_prepare(&server)) { 324 increase_nofile_limit();
379 return 1;
380 }
381
382 if (!drop_permissions()) {
383 server_fini(&server);
384 exit(EXIT_FAILURE);
385 }
386 325
387 // handle SIGTERM signals 326 // handle SIGTERM signals
388 signal(SIGTERM, sig_handler); 327 signal(SIGTERM, sig_handler);
@@ -393,12 +332,14 @@ int main(int argc, char **argv) {
393 332
394 sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION); 333 sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
395 334
396 root = root_create();
397
398 if (!server_init(&server)) { 335 if (!server_init(&server)) {
399 return 1; 336 return 1;
400 } 337 }
401 338
339 if (server.linux_dmabuf_v1) {
340 wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
341 }
342
402 if (validate) { 343 if (validate) {
403 bool valid = load_main_config(config_path, false, true); 344 bool valid = load_main_config(config_path, false, true);
404 free(config_path); 345 free(config_path);
@@ -413,6 +354,8 @@ int main(int argc, char **argv) {
413 goto shutdown; 354 goto shutdown;
414 } 355 }
415 356
357 set_rr_scheduling();
358
416 if (!server_start(&server)) { 359 if (!server_start(&server)) {
417 sway_terminate(EXIT_FAILURE); 360 sway_terminate(EXIT_FAILURE);
418 goto shutdown; 361 goto shutdown;