diff options
Diffstat (limited to 'sway/commands/exec_always.c')
-rw-r--r-- | sway/commands/exec_always.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 39e48a44..8fca1909 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include <signal.h> | 7 | #include <signal.h> |
8 | #include "sway/commands.h" | 8 | #include "sway/commands.h" |
9 | #include "sway/config.h" | 9 | #include "sway/config.h" |
10 | #include "sway/server.h" | ||
11 | #include "sway/desktop/launcher.h" | ||
10 | #include "sway/tree/container.h" | 12 | #include "sway/tree/container.h" |
11 | #include "sway/tree/root.h" | 13 | #include "sway/tree/root.h" |
12 | #include "sway/tree/workspace.h" | 14 | #include "sway/tree/workspace.h" |
@@ -24,11 +26,22 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) { | |||
24 | return error; | 26 | return error; |
25 | } | 27 | } |
26 | 28 | ||
29 | static void export_xdga_token(struct launcher_ctx *ctx) { | ||
30 | const char *token = launcher_ctx_get_token_name(ctx); | ||
31 | setenv("XDG_ACTIVATION_TOKEN", token, 1); | ||
32 | } | ||
33 | |||
34 | static void export_startup_id(struct launcher_ctx *ctx) { | ||
35 | const char *token = launcher_ctx_get_token_name(ctx); | ||
36 | setenv("DESKTOP_STARTUP_ID", token, 1); | ||
37 | } | ||
38 | |||
27 | struct cmd_results *cmd_exec_process(int argc, char **argv) { | 39 | struct cmd_results *cmd_exec_process(int argc, char **argv) { |
28 | struct cmd_results *error = NULL; | 40 | struct cmd_results *error = NULL; |
29 | char *tmp = NULL; | 41 | char *cmd = NULL; |
42 | bool no_startup_id = false; | ||
30 | if (strcmp(argv[0], "--no-startup-id") == 0) { | 43 | if (strcmp(argv[0], "--no-startup-id") == 0) { |
31 | sway_log(SWAY_INFO, "exec switch '--no-startup-id' not supported, ignored."); | 44 | no_startup_id = true; |
32 | --argc; ++argv; | 45 | --argc; ++argv; |
33 | if ((error = checkarg(argc, argv[-1], EXPECTED_AT_LEAST, 1))) { | 46 | if ((error = checkarg(argc, argv[-1], EXPECTED_AT_LEAST, 1))) { |
34 | return error; | 47 | return error; |
@@ -36,17 +49,12 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { | |||
36 | } | 49 | } |
37 | 50 | ||
38 | if (argc == 1 && (argv[0][0] == '\'' || argv[0][0] == '"')) { | 51 | if (argc == 1 && (argv[0][0] == '\'' || argv[0][0] == '"')) { |
39 | tmp = strdup(argv[0]); | 52 | cmd = strdup(argv[0]); |
40 | strip_quotes(tmp); | 53 | strip_quotes(cmd); |
41 | } else { | 54 | } else { |
42 | tmp = join_args(argv, argc); | 55 | cmd = join_args(argv, argc); |
43 | } | 56 | } |
44 | 57 | ||
45 | // Put argument into cmd array | ||
46 | char cmd[4096]; | ||
47 | strncpy(cmd, tmp, sizeof(cmd) - 1); | ||
48 | cmd[sizeof(cmd) - 1] = 0; | ||
49 | free(tmp); | ||
50 | sway_log(SWAY_DEBUG, "Executing %s", cmd); | 58 | sway_log(SWAY_DEBUG, "Executing %s", cmd); |
51 | 59 | ||
52 | int fd[2]; | 60 | int fd[2]; |
@@ -55,18 +63,28 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { | |||
55 | } | 63 | } |
56 | 64 | ||
57 | pid_t pid, child; | 65 | pid_t pid, child; |
66 | struct launcher_ctx *ctx = launcher_ctx_create_internal(); | ||
58 | // Fork process | 67 | // Fork process |
59 | if ((pid = fork()) == 0) { | 68 | if ((pid = fork()) == 0) { |
60 | // Fork child process again | 69 | // Fork child process again |
70 | restore_nofile_limit(); | ||
61 | setsid(); | 71 | setsid(); |
62 | sigset_t set; | 72 | sigset_t set; |
63 | sigemptyset(&set); | 73 | sigemptyset(&set); |
64 | sigprocmask(SIG_SETMASK, &set, NULL); | 74 | sigprocmask(SIG_SETMASK, &set, NULL); |
75 | signal(SIGPIPE, SIG_DFL); | ||
65 | close(fd[0]); | 76 | close(fd[0]); |
66 | if ((child = fork()) == 0) { | 77 | if ((child = fork()) == 0) { |
67 | close(fd[1]); | 78 | close(fd[1]); |
68 | execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); | 79 | if (ctx) { |
69 | _exit(0); | 80 | export_xdga_token(ctx); |
81 | } | ||
82 | if (ctx && !no_startup_id) { | ||
83 | export_startup_id(ctx); | ||
84 | } | ||
85 | execlp("sh", "sh", "-c", cmd, (void *)NULL); | ||
86 | sway_log_errno(SWAY_ERROR, "execlp failed"); | ||
87 | _exit(1); | ||
70 | } | 88 | } |
71 | ssize_t s = 0; | 89 | ssize_t s = 0; |
72 | while ((size_t)s < sizeof(pid_t)) { | 90 | while ((size_t)s < sizeof(pid_t)) { |
@@ -75,10 +93,12 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { | |||
75 | close(fd[1]); | 93 | close(fd[1]); |
76 | _exit(0); // Close child process | 94 | _exit(0); // Close child process |
77 | } else if (pid < 0) { | 95 | } else if (pid < 0) { |
96 | free(cmd); | ||
78 | close(fd[0]); | 97 | close(fd[0]); |
79 | close(fd[1]); | 98 | close(fd[1]); |
80 | return cmd_results_new(CMD_FAILURE, "fork() failed"); | 99 | return cmd_results_new(CMD_FAILURE, "fork() failed"); |
81 | } | 100 | } |
101 | free(cmd); | ||
82 | close(fd[1]); // close write | 102 | close(fd[1]); // close write |
83 | ssize_t s = 0; | 103 | ssize_t s = 0; |
84 | while ((size_t)s < sizeof(pid_t)) { | 104 | while ((size_t)s < sizeof(pid_t)) { |
@@ -89,8 +109,12 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { | |||
89 | waitpid(pid, NULL, 0); | 109 | waitpid(pid, NULL, 0); |
90 | if (child > 0) { | 110 | if (child > 0) { |
91 | sway_log(SWAY_DEBUG, "Child process created with pid %d", child); | 111 | sway_log(SWAY_DEBUG, "Child process created with pid %d", child); |
92 | root_record_workspace_pid(child); | 112 | if (ctx != NULL) { |
113 | sway_log(SWAY_DEBUG, "Recording workspace for process %d", child); | ||
114 | ctx->pid = child; | ||
115 | } | ||
93 | } else { | 116 | } else { |
117 | launcher_ctx_destroy(ctx); | ||
94 | return cmd_results_new(CMD_FAILURE, "Second fork() failed"); | 118 | return cmd_results_new(CMD_FAILURE, "Second fork() failed"); |
95 | } | 119 | } |
96 | 120 | ||