aboutsummaryrefslogtreecommitdiff
path: root/sway/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/main.c')
-rw-r--r--sway/main.c254
1 files changed, 93 insertions, 161 deletions
diff --git a/sway/main.c b/sway/main.c
index cc9147b8..efb674b6 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -1,58 +1,46 @@
#define _XOPEN_SOURCE 700
#define _POSIX_C_SOURCE 200112L
-#include <stdio.h>
-#include <stdlib.h>
+#include <getopt.h>
+#include <signal.h>
#include <stdbool.h>
-#include <wlc/wlc.h>
-#include <sys/wait.h>
-#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/un.h>
-#include <signal.h>
#include <unistd.h>
-#include <getopt.h>
#ifdef __linux__
#include <sys/capability.h>
#include <sys/prctl.h>
#endif
-#include "sway/extensions.h"
-#include "sway/layout.h"
+#include <wlr/util/log.h>
#include "sway/config.h"
-#include "sway/security.h"
-#include "sway/handlers.h"
-#include "sway/input.h"
+#include "sway/debug.h"
+#include "sway/server.h"
+#include "sway/tree/layout.h"
#include "sway/ipc-server.h"
#include "ipc-client.h"
#include "readline.h"
#include "stringop.h"
-#include "sway.h"
-#include "log.h"
#include "util.h"
static bool terminate_request = false;
static int exit_value = 0;
+struct sway_server server;
void sway_terminate(int exit_code) {
terminate_request = true;
exit_value = exit_code;
- wlc_terminate();
+ wl_display_terminate(server.wl_display);
}
void sig_handler(int signal) {
- close_views(&root_container);
+ //close_views(&root_container);
sway_terminate(EXIT_SUCCESS);
}
-static void wlc_log_handler(enum wlc_log_type type, const char *str) {
- if (type == WLC_LOG_ERROR) {
- sway_log(L_ERROR, "[wlc] %s", str);
- } else if (type == WLC_LOG_WARN) {
- sway_log(L_INFO, "[wlc] %s", str);
- } else {
- sway_log(L_DEBUG, "[wlc] %s", str);
- }
-}
-
void detect_raspi() {
bool raspi = false;
FILE *f = fopen("/sys/firmware/devicetree/base/model", "r");
@@ -98,23 +86,16 @@ void detect_proprietary() {
if (!f) {
return;
}
- bool nvidia = false, nvidia_modeset = false, nvidia_uvm = false, nvidia_drm = false;
while (!feof(f)) {
char *line;
if (!(line = read_line(f))) {
break;
}
if (strstr(line, "nvidia")) {
- nvidia = true;
- }
- if (strstr(line, "nvidia_modeset")) {
- nvidia_modeset = true;
- }
- if (strstr(line, "nvidia_uvm")) {
- nvidia_uvm = true;
- }
- if (strstr(line, "nvidia_drm")) {
- nvidia_drm = true;
+ fprintf(stderr, "\x1B[1;31mWarning: Proprietary Nvidia drivers are "
+ "NOT supported. Use Nouveau.\x1B[0m\n");
+ free(line);
+ break;
}
if (strstr(line, "fglrx")) {
fprintf(stderr, "\x1B[1;31mWarning: Proprietary AMD drivers do "
@@ -125,52 +106,6 @@ void detect_proprietary() {
free(line);
}
fclose(f);
- if (nvidia) {
- fprintf(stderr, "\x1B[1;31mWarning: Proprietary nvidia driver support "
- "is considered experimental. Nouveau is strongly recommended."
- "\x1B[0m\n");
- if (!nvidia_modeset || !nvidia_uvm || !nvidia_drm) {
- fprintf(stderr, "\x1B[1;31mWarning: You do not have all of the "
- "necessary kernel modules loaded for nvidia support. "
- "You need nvidia, nvidia_modeset, nvidia_uvm, and nvidia_drm."
- "\x1B[0m\n");
- }
-#ifdef __linux__
- f = fopen("/sys/module/nvidia_drm/parameters/modeset", "r");
- if (f) {
- char *line = read_line(f);
- if (line && strstr(line, "Y")) {
- // nvidia-drm.modeset is set to 0
- fprintf(stderr, "\x1B[1;31mWarning: You must load "
- "nvidia-drm with the modeset option on to use "
- "the proprietary driver. Consider adding "
- "nvidia-drm.modeset=1 to your kernel command line "
- "parameters.\x1B[0m\n");
- }
- fclose(f);
- free(line);
- } else {
- // nvidia-drm.modeset is not set
- fprintf(stderr, "\x1B[1;31mWarning: You must load "
- "nvidia-drm with the modeset option on to use "
- "the proprietary driver. Consider adding "
- "nvidia-drm.modeset=1 to your kernel command line "
- "parameters.\x1B[0m\n");
- }
-#else
- f = fopen("/proc/cmdline", "r");
- if (f) {
- char *line = read_line(f);
- if (line && !strstr(line, "nvidia-drm.modeset=1")) {
- fprintf(stderr, "\x1B[1;31mWarning: You must add "
- "nvidia-drm.modeset=1 to your kernel command line to use "
- "the proprietary driver.\x1B[0m\n");
- }
- fclose(f);
- free(line);
- }
-#endif
- }
}
void run_as_ipc_client(char *command, char *socket_path) {
@@ -184,27 +119,15 @@ void run_as_ipc_client(char *command, char *socket_path) {
static void log_env() {
const char *log_vars[] = {
"PATH",
- "LD_LOAD_PATH",
+ "LD_LIBRARY_PATH",
"LD_PRELOAD_PATH",
"LD_LIBRARY_PATH",
"SWAY_CURSOR_THEME",
"SWAY_CURSOR_SIZE",
- "SWAYSOCK",
- "WLC_DRM_DEVICE",
- "WLC_SHM",
- "WLC_OUTPUTS",
- "WLC_XWAYLAND",
- "WLC_LIBINPUT",
- "WLC_REPEAT_DELAY",
- "WLC_REPEAT_RATE",
- "XKB_DEFAULT_RULES",
- "XKB_DEFAULT_MODEL",
- "XKB_DEFAULT_LAYOUT",
- "XKB_DEFAULT_VARIANT",
- "XKB_DEFAULT_OPTIONS",
+ "SWAYSOCK"
};
for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) {
- sway_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i]));
+ wlr_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i]));
}
}
@@ -219,14 +142,14 @@ static void log_distro() {
for (size_t i = 0; i < sizeof(paths) / sizeof(char *); ++i) {
FILE *f = fopen(paths[i], "r");
if (f) {
- sway_log(L_INFO, "Contents of %s:", paths[i]);
+ wlr_log(L_INFO, "Contents of %s:", paths[i]);
while (!feof(f)) {
char *line;
if (!(line = read_line(f))) {
break;
}
if (*line) {
- sway_log(L_INFO, "%s", line);
+ wlr_log(L_INFO, "%s", line);
}
free(line);
}
@@ -236,9 +159,10 @@ static void log_distro() {
}
static void log_kernel() {
+ return;
FILE *f = popen("uname -a", "r");
if (!f) {
- sway_log(L_INFO, "Unable to determine kernel version");
+ wlr_log(L_INFO, "Unable to determine kernel version");
return;
}
while (!feof(f)) {
@@ -247,7 +171,7 @@ static void log_kernel() {
break;
}
if (*line) {
- sway_log(L_INFO, "%s", line);
+ wlr_log(L_INFO, "%s", line);
}
free(line);
}
@@ -258,14 +182,14 @@ static void security_sanity_check() {
// TODO: Notify users visually if this has issues
struct stat s;
if (stat("/proc", &s)) {
- sway_log(L_ERROR,
+ wlr_log(L_ERROR,
"!! DANGER !! /proc is not available - sway CANNOT enforce security rules!");
}
#ifdef __linux__
cap_flag_value_t v;
cap_t cap = cap_get_proc();
if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) {
- sway_log(L_ERROR,
+ wlr_log(L_ERROR,
"!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users.");
}
if (cap) {
@@ -281,13 +205,13 @@ static void executable_sanity_check() {
stat(exe, &sb);
// We assume that cap_get_file returning NULL implies ENODATA
if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) {
- sway_log(L_ERROR,
+ wlr_log(L_ERROR,
"sway executable has both the s(g)uid bit AND file caps set.");
- sway_log(L_ERROR,
+ wlr_log(L_ERROR,
"This is strongly discouraged (and completely broken).");
- sway_log(L_ERROR,
+ wlr_log(L_ERROR,
"Please clear one of them (either the suid bit, or the file caps).");
- sway_log(L_ERROR,
+ wlr_log(L_ERROR,
"If unsure, strip the file caps.");
exit(EXIT_FAILURE);
}
@@ -295,6 +219,37 @@ static void executable_sanity_check() {
#endif
}
+static void drop_permissions(bool keep_caps) {
+ if (getuid() != geteuid() || getgid() != getegid()) {
+ if (setgid(getgid()) != 0) {
+ wlr_log(L_ERROR, "Unable to drop root");
+ exit(EXIT_FAILURE);
+ }
+ if (setuid(getuid()) != 0) {
+ wlr_log(L_ERROR, "Unable to drop root");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (setuid(0) != -1) {
+ wlr_log(L_ERROR, "Root privileges can be restored.");
+ exit(EXIT_FAILURE);
+ }
+#ifdef __linux__
+ if (keep_caps) {
+ // Drop every cap except CAP_SYS_PTRACE
+ cap_t caps = cap_init();
+ cap_value_t keep = CAP_SYS_PTRACE;
+ wlr_log(L_INFO, "Dropping extra capabilities");
+ if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) ||
+ cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) ||
+ cap_set_proc(caps)) {
+ wlr_log(L_ERROR, "Failed to drop extra capabilities");
+ exit(EXIT_FAILURE);
+ }
+ }
+#endif
+}
+
int main(int argc, char **argv) {
static int verbose = 0, debug = 0, validate = 0;
@@ -334,7 +289,7 @@ int main(int argc, char **argv) {
int c;
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "hCdvVc:", long_options, &option_index);
+ c = getopt_long(argc, argv, "hCdDvVc:", long_options, &option_index);
if (c == -1) {
break;
}
@@ -352,6 +307,9 @@ int main(int argc, char **argv) {
case 'd': // debug
debug = 1;
break;
+ case 'D': // extended debug options
+ enable_debug_tree = true;
+ break;
case 'v': // version
fprintf(stdout, "sway version " SWAY_VERSION "\n");
exit(EXIT_SUCCESS);
@@ -374,37 +332,24 @@ int main(int argc, char **argv) {
}
}
- // we need to setup logging before wlc_init in case it fails.
+ // TODO: switch logging over to wlroots?
if (debug) {
- init_log(L_DEBUG);
+ wlr_log_init(L_DEBUG, NULL);
} else if (verbose || validate) {
- init_log(L_INFO);
+ wlr_log_init(L_INFO, NULL);
} else {
- init_log(L_ERROR);
+ wlr_log_init(L_ERROR, NULL);
}
if (optind < argc) { // Behave as IPC client
if(optind != 1) {
- sway_log(L_ERROR, "Don't use options with the IPC client");
- exit(EXIT_FAILURE);
- }
- if (getuid() != geteuid() || getgid() != getegid()) {
- if (setgid(getgid()) != 0) {
- sway_log(L_ERROR, "Unable to drop root");
- exit(EXIT_FAILURE);
- }
- if (setuid(getuid()) != 0) {
- sway_log(L_ERROR, "Unable to drop root");
- exit(EXIT_FAILURE);
- }
- }
- if (setuid(0) != -1) {
- sway_log(L_ERROR, "Root privileges can be restored.");
+ wlr_log(L_ERROR, "Don't use options with the IPC client");
exit(EXIT_FAILURE);
}
+ drop_permissions(false);
char *socket_path = getenv("SWAYSOCK");
if (!socket_path) {
- sway_log(L_ERROR, "Unable to retrieve socket path");
+ wlr_log(L_ERROR, "Unable to retrieve socket path");
exit(EXIT_FAILURE);
}
char *command = join_args(argv + optind, argc - optind);
@@ -413,49 +358,25 @@ int main(int argc, char **argv) {
}
executable_sanity_check();
-#ifdef __linux__
bool suid = false;
+#ifdef __linux__
if (getuid() != geteuid() || getgid() != getegid()) {
// Retain capabilities after setuid()
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
- sway_log(L_ERROR, "Cannot keep caps after setuid()");
+ wlr_log(L_ERROR, "Cannot keep caps after setuid()");
exit(EXIT_FAILURE);
}
suid = true;
}
#endif
- wlc_log_set_handler(wlc_log_handler);
log_kernel();
log_distro();
- log_env();
detect_proprietary();
detect_raspi();
- input_devices = create_list();
-
- /* Changing code earlier than this point requires detailed review */
- /* (That code runs as root on systems without logind, and wlc_init drops to
- * another user.) */
- register_wlc_handlers();
- if (!wlc_init()) {
- return 1;
- }
- register_extensions();
-
#ifdef __linux__
- if (suid) {
- // Drop every cap except CAP_SYS_PTRACE
- cap_t caps = cap_init();
- cap_value_t keep = CAP_SYS_PTRACE;
- sway_log(L_INFO, "Dropping extra capabilities");
- if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) ||
- cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) ||
- cap_set_proc(caps)) {
- sway_log(L_ERROR, "Failed to drop extra capabilities");
- exit(EXIT_FAILURE);
- }
- }
+ drop_permissions(suid);
#endif
// handle SIGTERM signals
signal(SIGTERM, sig_handler);
@@ -463,11 +384,16 @@ int main(int argc, char **argv) {
// prevent ipc from crashing sway
signal(SIGPIPE, SIG_IGN);
- sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n");
+ wlr_log(L_INFO, "Starting sway version " SWAY_VERSION);
+
+ layout_init();
- init_layout();
+ if (!server_init(&server)) {
+ return 1;
+ }
- ipc_init();
+ ipc_init(&server);
+ log_env();
if (validate) {
bool valid = load_main_config(config_path, false);
@@ -484,11 +410,17 @@ int main(int argc, char **argv) {
security_sanity_check();
+ // TODO: wait for server to be ready
+ // TODO: consume config->cmd_queue
+ config->active = true;
+
if (!terminate_request) {
- wlc_run();
+ server_run(&server);
}
- list_free(input_devices);
+ wlr_log(L_INFO, "Shutting down sway");
+
+ server_fini(&server);
ipc_terminate();