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