aboutsummaryrefslogtreecommitdiff
path: root/sway/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands.c')
-rw-r--r--sway/commands.c175
1 files changed, 114 insertions, 61 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 870a2377..7721c6fb 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -5,6 +5,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/wait.h>
+#include <fcntl.h>
#include <ctype.h>
#include "stringop.h"
#include "layout.h"
@@ -29,11 +31,44 @@ struct modifier_key modifiers[] = {
{ "Mod5", WLC_BIT_MOD_MOD5 },
};
-bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
- if (argc < 2) {
- sway_log(L_ERROR, "Invalid set command (expected 2 arguments, got %d)", argc);
- return false;
+enum expected_args {
+ EXPECTED_MORE_THEN,
+ EXPECTED_LESS_THEN,
+ EXPECTED_SAME_AS
+};
+
+static bool checkarg(int argc, char *name, enum expected_args type, int val) {
+ switch(type) {
+ case EXPECTED_MORE_THEN:
+ if (argc > val) {
+ return true;
+ }
+ sway_log(L_ERROR, "Invalid %s command."
+ "(expected more then %d arguments, got %d", name, val, argc);
+ break;
+ case EXPECTED_LESS_THEN:
+ if (argc < val) {
+ return true;
+ };
+ sway_log(L_ERROR, "Invalid %s command."
+ "(expected less then %d arguments, got %d", name, val, argc);
+ break;
+ case EXPECTED_SAME_AS:
+ if (argc == val) {
+ return true;
+ };
+ sway_log(L_ERROR, "Invalid %s command."
+ "(expected %d arguments, got %d", name, val, argc);
+ break;
}
+ return false;
+}
+
+
+static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "bindsym", EXPECTED_MORE_THEN, 1) == false) {
+ return false;
+ };
struct sway_binding *binding = malloc(sizeof(struct sway_binding));
binding->keys = create_list();
@@ -73,46 +108,71 @@ bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool cmd_exec(struct sway_config *config, int argc, char **argv) {
- if (argc < 1) {
- sway_log(L_ERROR, "Invalid exec command (expected at least 1 argument, got %d)", argc);
- return false;
+static void cmd_exec_cleanup(int signal) {
+ while (waitpid((pid_t)-1, 0, WNOHANG) > 0){};
+}
+
+static bool cmd_exec_always(struct sway_config *config, int argc, char **argv) {
+ /* setup signal handler to cleanup dead proccesses */
+ /* TODO: replace this with a function that has constructor attribute? */
+ static bool cleanup = false;
+ if(cleanup == false) {
+ signal(SIGCHLD, cmd_exec_cleanup);
+ cleanup = true;
+ /* Set it so filedescriptors are closed for executed programs */
+ int flag_out = fcntl(STDOUT_FILENO, F_GETFD);
+ int flag_in = fcntl(STDIN_FILENO, F_GETFD);
+ int flag_err = fcntl(STDERR_FILENO, F_GETFD);
+ if (flag_out != -1) {
+ flag_out |= FD_CLOEXEC;
+ fcntl(STDOUT_FILENO, F_SETFD, flag_out);
+ }
+ if (flag_in != -1) {
+ flag_in |= FD_CLOEXEC;
+ fcntl(STDIN_FILENO, F_SETFD, flag_in);
+ }
+ if (flag_err != -1) {
+ flag_err |= FD_CLOEXEC;
+ fcntl(STDERR_FILENO, F_SETFD, flag_err);
+ }
}
- if (config->reloading) {
- sway_log(L_DEBUG, "Ignoring exec %s due to reload", join_args(argv, argc));
- return true;
+ if (checkarg(argc, "exec_always", EXPECTED_MORE_THEN, 0) == false) {
+ return false;
}
- if (fork() == 0) {
+ pid_t pid = fork();
+ /* Failed to fork */
+ if (pid < 0) {
+ sway_log(L_ERROR, "exec command failed, sway did not fork");
+ return false;
+ }
+ /* Child process */
+ if (pid == 0) {
char *args = join_args(argv, argc);
sway_log(L_DEBUG, "Executing %s", args);
execl("/bin/sh", "sh", "-c", args, (char *)NULL);
+ /* Execl doesnt return unless failure */
+ sway_log(L_ERROR, "could not find /bin/sh");
free(args);
- exit(0);
+ exit(-1);
}
+ /* Parent */
return true;
}
-bool cmd_exec_always(struct sway_config *config, int argc, char **argv) {
- if (argc < 1) {
- sway_log(L_ERROR, "Invalid exec_always command (expected at least 1 argument, got %d)", argc);
- return false;
- }
-
- if (fork() == 0) {
+static bool cmd_exec(struct sway_config *config, int argc, char **argv) {
+ if (config->reloading) {
char *args = join_args(argv, argc);
- sway_log(L_DEBUG, "Executing %s", args);
- execl("/bin/sh", "sh", "-c", args, (char *)NULL);
+ sway_log(L_DEBUG, "Ignoring exec %s due to reload", args);
free(args);
- exit(0);
+ return true;
}
- return true;
+ return cmd_exec_always(config, argc, argv);
}
-bool cmd_exit(struct sway_config *config, int argc, char **argv) {
- if (argc != 0) {
- sway_log(L_ERROR, "Invalid exit command (expected 1 arguments, got %d)", argc);
+static bool cmd_exit(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "exit", EXPECTED_SAME_AS, 0) == false) {
return false;
}
// TODO: Some kind of clean up is probably in order
@@ -120,9 +180,8 @@ bool cmd_exit(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool cmd_focus(struct sway_config *config, int argc, char **argv) {
- if (argc != 1) {
- sway_log(L_ERROR, "Invalid focus command (expected 1 arguments, got %d)", argc);
+static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "focus", EXPECTED_SAME_AS, 1) == false) {
return false;
}
if (strcasecmp(argv[0], "left") == 0) {
@@ -139,9 +198,8 @@ bool cmd_focus(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv) {
- if (argc != 1) {
- sway_log(L_ERROR, "Invalid focus_follows_mouse command (expected 1 arguments, got %d)", argc);
+static bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "focus_follows_mouse", EXPECTED_SAME_AS, 1) == false) {
return false;
}
@@ -149,9 +207,8 @@ bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv)
return true;
}
-bool cmd_layout(struct sway_config *config, int argc, char **argv) {
- if (argc < 1) {
- sway_log(L_ERROR, "Invalid layout command (expected at least 1 argument, got %d)", argc);
+static bool cmd_layout(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "layout", EXPECTED_MORE_THEN, 0) == false) {
return false;
}
swayc_t *parent = get_focused_container(&root_container);
@@ -174,9 +231,8 @@ bool cmd_layout(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool cmd_reload(struct sway_config *config, int argc, char **argv) {
- if (argc != 0) {
- sway_log(L_ERROR, "Invalid reload command (expected 0 arguments, got %d)", argc);
+static bool cmd_reload(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "reload", EXPECTED_SAME_AS, 0) == false) {
return false;
}
if (!load_config()) {
@@ -186,9 +242,8 @@ bool cmd_reload(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool cmd_set(struct sway_config *config, int argc, char **argv) {
- if (argc != 2) {
- sway_log(L_ERROR, "Invalid set command (expected 2 arguments, got %d)", argc);
+static bool cmd_set(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "set", EXPECTED_SAME_AS, 2) == false) {
return false;
}
struct sway_variable *var = malloc(sizeof(struct sway_variable));
@@ -200,9 +255,11 @@ bool cmd_set(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool _do_split(struct sway_config *config, int argc, char **argv, int layout) {
- if (argc != 0) {
- sway_log(L_ERROR, "Invalid splitv command (expected 0 arguments, got %d)", argc);
+static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) {
+ char *name = layout == L_VERT ? "splitv":
+ layout == L_HORIZ ? "splith":
+ "split";
+ if (checkarg(argc, name, EXPECTED_SAME_AS, 0) == false) {
return false;
}
swayc_t *focused = get_focused_container(&root_container);
@@ -225,20 +282,18 @@ bool _do_split(struct sway_config *config, int argc, char **argv, int layout) {
return true;
}
-bool cmd_splitv(struct sway_config *config, int argc, char **argv) {
+static bool cmd_splitv(struct sway_config *config, int argc, char **argv) {
return _do_split(config, argc, argv, L_VERT);
}
-bool cmd_splith(struct sway_config *config, int argc, char **argv) {
+static bool cmd_splith(struct sway_config *config, int argc, char **argv) {
return _do_split(config, argc, argv, L_HORIZ);
}
-bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {
- if (argc != 1) {
- sway_log(L_ERROR, "Invalid log_colors command (expected 1 argument, got %d)", argc);
+static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "log_colors", EXPECTED_SAME_AS, 1) == false) {
return false;
}
-
if (strcasecmp(argv[0], "no") != 0 && strcasecmp(argv[0], "yes") != 0) {
sway_log(L_ERROR, "Invalid log_colors command (expected `yes` or `no`, got '%s')", argv[0]);
return false;
@@ -248,9 +303,8 @@ bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
- if (argc != 1) {
- sway_log(L_ERROR, "Invalid fullscreen command (expected 1 arguments, got %d)", argc);
+static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "fullscreen", EXPECTED_SAME_AS, 0) == false) {
return false;
}
@@ -262,9 +316,8 @@ bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
return true;
}
-bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
- if (argc != 1) {
- sway_log(L_ERROR, "Invalid workspace command (expected 1 arguments, got %d)", argc);
+static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
+ if (checkarg(argc, "workspace", EXPECTED_SAME_AS, 1) == false) {
return false;
}
@@ -278,7 +331,7 @@ bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
}
/* Keep alphabetized */
-struct cmd_handler handlers[] = {
+static struct cmd_handler handlers[] = {
{ "bindsym", cmd_bindsym },
{ "exec", cmd_exec },
{ "exec_always", cmd_exec_always },
@@ -295,7 +348,7 @@ struct cmd_handler handlers[] = {
{ "workspace", cmd_workspace }
};
-char **split_directive(char *line, int *argc) {
+static char **split_directive(char *line, int *argc) {
const char *delimiters = " ";
*argc = 0;
while (isspace(*line) && *line) ++line;
@@ -347,13 +400,13 @@ char **split_directive(char *line, int *argc) {
return parts;
}
-int handler_compare(const void *_a, const void *_b) {
+static int handler_compare(const void *_a, const void *_b) {
const struct cmd_handler *a = _a;
const struct cmd_handler *b = _b;
return strcasecmp(a->command, b->command);
}
-struct cmd_handler *find_handler(struct cmd_handler handlers[], int l, char *line) {
+static struct cmd_handler *find_handler(struct cmd_handler handlers[], int l, char *line) {
struct cmd_handler d = { .command=line };
struct cmd_handler *res = bsearch(&d, handlers, l, sizeof(struct cmd_handler), handler_compare);
return res;