aboutsummaryrefslogtreecommitdiffstats
path: root/sway/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/main.c')
-rw-r--r--sway/main.c186
1 files changed, 82 insertions, 104 deletions
diff --git a/sway/main.c b/sway/main.c
index 0611e80b..1c4939aa 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <getopt.h> 1#include <getopt.h>
3#include <pango/pangocairo.h> 2#include <pango/pangocairo.h>
4#include <signal.h> 3#include <signal.h>
@@ -6,6 +5,7 @@
6#include <stdio.h> 5#include <stdio.h>
7#include <stdlib.h> 6#include <stdlib.h>
8#include <string.h> 7#include <string.h>
8#include <sys/resource.h>
9#include <sys/stat.h> 9#include <sys/stat.h>
10#include <sys/types.h> 10#include <sys/types.h>
11#include <sys/wait.h> 11#include <sys/wait.h>
@@ -27,6 +27,7 @@
27 27
28static bool terminate_request = false; 28static bool terminate_request = false;
29static int exit_value = 0; 29static int exit_value = 0;
30static struct rlimit original_nofile_rlimit = {0};
30struct sway_server server = {0}; 31struct sway_server server = {0};
31struct sway_debug debug = {0}; 32struct sway_debug debug = {0};
32 33
@@ -47,44 +48,6 @@ void sig_handler(int signal) {
47 sway_terminate(EXIT_SUCCESS); 48 sway_terminate(EXIT_SUCCESS);
48} 49}
49 50
50void detect_proprietary(int allow_unsupported_gpu) {
51 FILE *f = fopen("/proc/modules", "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 (strncmp(line, "nvidia ", 7) == 0) {
59 if (allow_unsupported_gpu) {
60 sway_log(SWAY_ERROR,
61 "!!! Proprietary Nvidia drivers are in use !!!");
62 } else {
63 sway_log(SWAY_ERROR,
64 "Proprietary Nvidia drivers are NOT supported. "
65 "Use Nouveau. To launch sway anyway, launch with "
66 "--my-next-gpu-wont-be-nvidia and DO NOT report issues.");
67 exit(EXIT_FAILURE);
68 }
69 break;
70 }
71 if (strstr(line, "fglrx")) {
72 if (allow_unsupported_gpu) {
73 sway_log(SWAY_ERROR,
74 "!!! Proprietary AMD drivers are in use !!!");
75 } else {
76 sway_log(SWAY_ERROR, "Proprietary AMD drivers do NOT support "
77 "Wayland. Use radeon. To try anyway, launch sway with "
78 "--unsupported-gpu and DO NOT report issues.");
79 exit(EXIT_FAILURE);
80 }
81 break;
82 }
83 }
84 free(line);
85 fclose(f);
86}
87
88void run_as_ipc_client(char *command, char *socket_path) { 51void run_as_ipc_client(char *command, char *socket_path) {
89 int socketfd = ipc_open_socket(socket_path); 52 int socketfd = ipc_open_socket(socket_path);
90 uint32_t len = strlen(command); 53 uint32_t len = strlen(command);
@@ -148,33 +111,49 @@ static void log_kernel(void) {
148 pclose(f); 111 pclose(f);
149} 112}
150 113
151 114static bool detect_suid(void) {
152static bool drop_permissions(void) { 115 if (geteuid() != 0 && getegid() != 0) {
153 if (getuid() != geteuid() || getgid() != getegid()) { 116 return false;
154 // Set the gid and uid in the correct order.
155 if (setgid(getgid()) != 0) {
156 sway_log(SWAY_ERROR, "Unable to drop root group, refusing to start");
157 return false;
158 }
159 if (setuid(getuid()) != 0) {
160 sway_log(SWAY_ERROR, "Unable to drop root user, refusing to start");
161 return false;
162 }
163 } 117 }
164 if (setgid(0) != -1 || setuid(0) != -1) { 118
165 sway_log(SWAY_ERROR, "Unable to drop root (we shouldn't be able to " 119 if (getuid() == geteuid() && getgid() == getegid()) {
166 "restore it after setuid), refusing to start");
167 return false; 120 return false;
168 } 121 }
122
123 sway_log(SWAY_ERROR, "SUID operation is no longer supported, refusing to start. "
124 "This check will be removed in a future release.");
169 return true; 125 return true;
170} 126}
171 127
128static void increase_nofile_limit(void) {
129 if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
130 sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
131 "getrlimit(NOFILE) failed");
132 return;
133 }
134
135 struct rlimit new_rlimit = original_nofile_rlimit;
136 new_rlimit.rlim_cur = new_rlimit.rlim_max;
137 if (setrlimit(RLIMIT_NOFILE, &new_rlimit) != 0) {
138 sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
139 "setrlimit(NOFILE) failed");
140 sway_log(SWAY_INFO, "Running with %d max open files",
141 (int)original_nofile_rlimit.rlim_cur);
142 }
143}
144
145void restore_nofile_limit(void) {
146 if (original_nofile_rlimit.rlim_cur == 0) {
147 return;
148 }
149 if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
150 sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
151 "setrlimit(NOFILE) failed");
152 }
153}
154
172void enable_debug_flag(const char *flag) { 155void enable_debug_flag(const char *flag) {
173 if (strcmp(flag, "damage=highlight") == 0) { 156 if (strcmp(flag, "noatomic") == 0) {
174 debug.damage = DAMAGE_HIGHLIGHT;
175 } else if (strcmp(flag, "damage=rerender") == 0) {
176 debug.damage = DAMAGE_RERENDER;
177 } else if (strcmp(flag, "noatomic") == 0) {
178 debug.noatomic = true; 157 debug.noatomic = true;
179 } else if (strcmp(flag, "txn-wait") == 0) { 158 } else if (strcmp(flag, "txn-wait") == 0) {
180 debug.txn_wait = true; 159 debug.txn_wait = true;
@@ -182,6 +161,8 @@ void enable_debug_flag(const char *flag) {
182 debug.txn_timings = true; 161 debug.txn_timings = true;
183 } else if (strncmp(flag, "txn-timeout=", 12) == 0) { 162 } else if (strncmp(flag, "txn-timeout=", 12) == 0) {
184 server.txn_timeout_ms = atoi(&flag[12]); 163 server.txn_timeout_ms = atoi(&flag[12]);
164 } else if (strcmp(flag, "legacy-wl-drm") == 0) {
165 debug.legacy_wl_drm = true;
185 } else { 166 } else {
186 sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag); 167 sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
187 } 168 }
@@ -206,36 +187,35 @@ static void handle_wlr_log(enum wlr_log_importance importance,
206 _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args); 187 _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args);
207} 188}
208 189
190static const struct option long_options[] = {
191 {"help", no_argument, NULL, 'h'},
192 {"config", required_argument, NULL, 'c'},
193 {"validate", no_argument, NULL, 'C'},
194 {"debug", no_argument, NULL, 'd'},
195 {"version", no_argument, NULL, 'v'},
196 {"verbose", no_argument, NULL, 'V'},
197 {"get-socketpath", no_argument, NULL, 'p'},
198 {"unsupported-gpu", no_argument, NULL, 'u'},
199 {0, 0, 0, 0}
200};
201
202static const char usage[] =
203 "Usage: sway [options] [command]\n"
204 "\n"
205 " -h, --help Show help message and quit.\n"
206 " -c, --config <config> Specify a config file.\n"
207 " -C, --validate Check the validity of the config file, then exit.\n"
208 " -d, --debug Enables full logging, including debug information.\n"
209 " -v, --version Show the version number and quit.\n"
210 " -V, --verbose Enables more verbose logging.\n"
211 " --get-socketpath Gets the IPC socket path and prints it, then exits.\n"
212 "\n";
213
209int main(int argc, char **argv) { 214int main(int argc, char **argv) {
210 static int verbose = 0, debug = 0, validate = 0, allow_unsupported_gpu = 0; 215 static bool verbose = false, debug = false, validate = false;
211
212 static const struct option long_options[] = {
213 {"help", no_argument, NULL, 'h'},
214 {"config", required_argument, NULL, 'c'},
215 {"validate", no_argument, NULL, 'C'},
216 {"debug", no_argument, NULL, 'd'},
217 {"version", no_argument, NULL, 'v'},
218 {"verbose", no_argument, NULL, 'V'},
219 {"get-socketpath", no_argument, NULL, 'p'},
220 {"unsupported-gpu", no_argument, NULL, 'u'},
221 {"my-next-gpu-wont-be-nvidia", no_argument, NULL, 'u'},
222 {0, 0, 0, 0}
223 };
224 216
225 char *config_path = NULL; 217 char *config_path = NULL;
226 218
227 const char* usage =
228 "Usage: sway [options] [command]\n"
229 "\n"
230 " -h, --help Show help message and quit.\n"
231 " -c, --config <config> Specify a config file.\n"
232 " -C, --validate Check the validity of the config file, then exit.\n"
233 " -d, --debug Enables full logging, including debug information.\n"
234 " -v, --version Show the version number and quit.\n"
235 " -V, --verbose Enables more verbose logging.\n"
236 " --get-socketpath Gets the IPC socket path and prints it, then exits.\n"
237 "\n";
238
239 int c; 219 int c;
240 while (1) { 220 while (1) {
241 int option_index = 0; 221 int option_index = 0;
@@ -253,25 +233,25 @@ int main(int argc, char **argv) {
253 config_path = strdup(optarg); 233 config_path = strdup(optarg);
254 break; 234 break;
255 case 'C': // validate 235 case 'C': // validate
256 validate = 1; 236 validate = true;
257 break; 237 break;
258 case 'd': // debug 238 case 'd': // debug
259 debug = 1; 239 debug = true;
260 break; 240 break;
261 case 'D': // extended debug options 241 case 'D': // extended debug options
262 enable_debug_flag(optarg); 242 enable_debug_flag(optarg);
263 break; 243 break;
264 case 'u': 244 case 'u':
265 allow_unsupported_gpu = 1; 245 allow_unsupported_gpu = true;
266 break; 246 break;
267 case 'v': // version 247 case 'v': // version
268 printf("sway version " SWAY_VERSION "\n"); 248 printf("sway version " SWAY_VERSION "\n");
269 exit(EXIT_SUCCESS); 249 exit(EXIT_SUCCESS);
270 break; 250 break;
271 case 'V': // verbose 251 case 'V': // verbose
272 verbose = 1; 252 verbose = true;
273 break; 253 break;
274 case 'p': ; // --get-socketpath 254 case 'p': // --get-socketpath
275 if (getenv("SWAYSOCK")) { 255 if (getenv("SWAYSOCK")) {
276 printf("%s\n", getenv("SWAYSOCK")); 256 printf("%s\n", getenv("SWAYSOCK"));
277 exit(EXIT_SUCCESS); 257 exit(EXIT_SUCCESS);
@@ -286,6 +266,11 @@ int main(int argc, char **argv) {
286 } 266 }
287 } 267 }
288 268
269 // SUID operation is deprecated, so block it for now.
270 if (detect_suid()) {
271 exit(EXIT_FAILURE);
272 }
273
289 // Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the 274 // Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the
290 // clear error message (when not running as an IPC client). 275 // clear error message (when not running as an IPC client).
291 if (!getenv("XDG_RUNTIME_DIR") && optind == argc) { 276 if (!getenv("XDG_RUNTIME_DIR") && optind == argc) {
@@ -312,7 +297,6 @@ int main(int argc, char **argv) {
312 log_kernel(); 297 log_kernel();
313 log_distro(); 298 log_distro();
314 log_env(); 299 log_env();
315 detect_proprietary(allow_unsupported_gpu);
316 300
317 if (optind < argc) { // Behave as IPC client 301 if (optind < argc) { // Behave as IPC client
318 if (optind != 1) { 302 if (optind != 1) {
@@ -325,9 +309,6 @@ int main(int argc, char **argv) {
325 "`sway -d 2>sway.log`."); 309 "`sway -d 2>sway.log`.");
326 exit(EXIT_FAILURE); 310 exit(EXIT_FAILURE);
327 } 311 }
328 if (!drop_permissions()) {
329 exit(EXIT_FAILURE);
330 }
331 char *socket_path = getenv("SWAYSOCK"); 312 char *socket_path = getenv("SWAYSOCK");
332 if (!socket_path) { 313 if (!socket_path) {
333 sway_log(SWAY_ERROR, "Unable to retrieve socket path"); 314 sway_log(SWAY_ERROR, "Unable to retrieve socket path");
@@ -339,14 +320,7 @@ int main(int argc, char **argv) {
339 return 0; 320 return 0;
340 } 321 }
341 322
342 if (!server_privileged_prepare(&server)) { 323 increase_nofile_limit();
343 return 1;
344 }
345
346 if (!drop_permissions()) {
347 server_fini(&server);
348 exit(EXIT_FAILURE);
349 }
350 324
351 // handle SIGTERM signals 325 // handle SIGTERM signals
352 signal(SIGTERM, sig_handler); 326 signal(SIGTERM, sig_handler);
@@ -357,12 +331,14 @@ int main(int argc, char **argv) {
357 331
358 sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION); 332 sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
359 333
360 root = root_create();
361
362 if (!server_init(&server)) { 334 if (!server_init(&server)) {
363 return 1; 335 return 1;
364 } 336 }
365 337
338 if (server.linux_dmabuf_v1) {
339 wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
340 }
341
366 if (validate) { 342 if (validate) {
367 bool valid = load_main_config(config_path, false, true); 343 bool valid = load_main_config(config_path, false, true);
368 free(config_path); 344 free(config_path);
@@ -377,6 +353,8 @@ int main(int argc, char **argv) {
377 goto shutdown; 353 goto shutdown;
378 } 354 }
379 355
356 set_rr_scheduling();
357
380 if (!server_start(&server)) { 358 if (!server_start(&server)) {
381 sway_terminate(EXIT_FAILURE); 359 sway_terminate(EXIT_FAILURE);
382 goto shutdown; 360 goto shutdown;