diff --git a/meson.build b/meson.build index c50fab176..3f60ba83a 100644 --- a/meson.build +++ b/meson.build @@ -107,6 +107,7 @@ if scdoc.found() 'swaymsg/swaymsg.1.scd', 'swaynag/swaynag.1.scd', 'swaynag/swaynag.5.scd', + 'swayrun/swayrun.1.scd' ] foreach filename : man_files topic = filename.split('.')[-3].split('/')[-1] @@ -149,6 +150,7 @@ subdir('client') subdir('swaybg') subdir('swaybar') subdir('swaynag') +subdir('swayrun') config = configuration_data() config.set('datadir', join_paths(prefix, datadir)) diff --git a/sway.desktop b/sway.desktop index 98c9af293..2e83cc893 100644 --- a/sway.desktop +++ b/sway.desktop @@ -1,5 +1,5 @@ [Desktop Entry] Name=Sway Comment=SirCmpwn's Wayland window manager -Exec=sway +Exec=swayrun Type=Application diff --git a/swayrun/main.c b/swayrun/main.c new file mode 100644 index 000000000..f8ffd9e86 --- /dev/null +++ b/swayrun/main.c @@ -0,0 +1,71 @@ +#define _POSIX_C_SOURCE 200809L // for getline +#include +#include +#include +#include +#include +#include +#include "stringop.h" + +#define SWAY_COMMAND "sway" + +char allowed_shell(char *shell) { + FILE *fp; + char *line = NULL; + size_t len = 0; + char allowed = false; + + if (strstr(shell, "false") != NULL || strstr(shell, "nologin") != NULL) { + return false; + } + + fp = fopen("/etc/shells", "r"); + if (fp == NULL) { + return true; + } + + while (getline(&line, &len, fp) != -1) { + strip_whitespace(line); + if (strcmp(shell, line) == 0) { + allowed = true; + break; + } + } + + fclose(fp); + if (line) { + free(line); + } + return allowed; +} + +int main(int argc, char **argv) { + char *shell = getenv("SHELL"); + + if (shell && allowed_shell(shell)) { + // 3 exec arguments + argc + argv[argc] NULL pointer + int exec_argc = 4 + argc; + char **exec_argv = malloc(exec_argc * sizeof(char*)); + + // Prefix - to shell path to indicate login shell + char *login_shell = malloc(strlen(shell) + 2); + strcpy(login_shell, "-"); + strcat(login_shell, shell); + + // Build the argumrnts to exec + memcpy(exec_argv + 3, argv, (argc + 1) * sizeof(argv)); + exec_argv[0] = login_shell; + exec_argv[1] = "-c"; + exec_argv[2] = "exec " SWAY_COMMAND " \"$@\""; + exec_argv[3] = shell; + + execvp(shell, exec_argv); + fprintf(stderr, "Could not run %s using login shell: %s\n", SWAY_COMMAND, shell); + } else { + argv[0] = SWAY_COMMAND; + execvp(SWAY_COMMAND, argv); + fprintf(stderr, "Could not run %s\n", SWAY_COMMAND); + } + + return errno; +} diff --git a/swayrun/meson.build b/swayrun/meson.build new file mode 100644 index 000000000..5ad98bc84 --- /dev/null +++ b/swayrun/meson.build @@ -0,0 +1,7 @@ +executable( + 'swayrun', + 'main.c', + include_directories: [sway_inc], + link_with: [lib_sway_common], + install: true +) diff --git a/swayrun/swayrun.1.scd b/swayrun/swayrun.1.scd new file mode 100644 index 000000000..e8f84fd9e --- /dev/null +++ b/swayrun/swayrun.1.scd @@ -0,0 +1,34 @@ +swayrun(1) + +# NAME + +swayrun - Run Sway from a login shell + +# SYNOPSIS + +_swayrun_ [options...] [command] + +# DESCRIPTION + +Attempts to run *sway*(1) via the user's login shell. This allows environment +configuration and other login actions, for example when run via a login manager. + +All arguments to swayrun will be passed through unaltered to sway. + +If a valid login shell cannot be determined, sway will be executed normally. + +# CONFIGURATION + +swayrun will consult */etc/shells* if it exists for a list of valid login +shells. In addition, *false* and *nologin* will be considered invalid shells. + +# ENVIRONMENT + +The following environment variables have an effect on swayrun: + +_SHELL_ + Holds the path to the login shell. + +# SEE + +*sway*(1) *shells*(5)