diff options
author | emersion <contact@emersion.fr> | 2017-12-04 22:43:49 +0100 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2017-12-04 22:43:49 +0100 |
commit | 514c819ff98d72880c5b7e0beb7bd9ca866bc1ad (patch) | |
tree | d2ddf512ebc46ea2c93c7a487cdf758c84e3d0bd /sway/commands/exec_always.c | |
parent | Merge pull request #1494 from acrisci/feature/xwayland (diff) | |
download | sway-514c819ff98d72880c5b7e0beb7bd9ca866bc1ad.tar.gz sway-514c819ff98d72880c5b7e0beb7bd9ca866bc1ad.tar.zst sway-514c819ff98d72880c5b7e0beb7bd9ca866bc1ad.zip |
Add exec and exec_always commands
Diffstat (limited to 'sway/commands/exec_always.c')
-rw-r--r-- | sway/commands/exec_always.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c new file mode 100644 index 00000000..0a252e7b --- /dev/null +++ b/sway/commands/exec_always.c | |||
@@ -0,0 +1,85 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <stdlib.h> | ||
3 | #include <stdint.h> | ||
4 | #include <string.h> | ||
5 | #include <sys/wait.h> | ||
6 | #include <unistd.h> | ||
7 | #include "sway/commands.h" | ||
8 | #include "sway/workspace.h" | ||
9 | #include "sway/container.h" | ||
10 | #include "log.h" | ||
11 | #include "stringop.h" | ||
12 | |||
13 | struct cmd_results *cmd_exec_always(int argc, char **argv) { | ||
14 | struct cmd_results *error = NULL; | ||
15 | // TODO: config | ||
16 | //if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); | ||
17 | if ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) { | ||
18 | return error; | ||
19 | } | ||
20 | |||
21 | char *tmp = NULL; | ||
22 | if (strcmp((char*)*argv, "--no-startup-id") == 0) { | ||
23 | sway_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); | ||
24 | if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { | ||
25 | return error; | ||
26 | } | ||
27 | |||
28 | tmp = join_args(argv + 1, argc - 1); | ||
29 | } else { | ||
30 | tmp = join_args(argv, argc); | ||
31 | } | ||
32 | |||
33 | // Put argument into cmd array | ||
34 | char cmd[4096]; | ||
35 | strncpy(cmd, tmp, sizeof(cmd)); | ||
36 | cmd[sizeof(cmd) - 1] = 0; | ||
37 | free(tmp); | ||
38 | sway_log(L_DEBUG, "Executing %s", cmd); | ||
39 | |||
40 | int fd[2]; | ||
41 | if (pipe(fd) != 0) { | ||
42 | sway_log(L_ERROR, "Unable to create pipe for fork"); | ||
43 | } | ||
44 | |||
45 | pid_t pid; | ||
46 | pid_t *child = malloc(sizeof(pid_t)); // malloc'd so that Linux can avoid copying the process space | ||
47 | if (!child) { | ||
48 | return cmd_results_new(CMD_FAILURE, "exec_always", "Unable to allocate child pid"); | ||
49 | } | ||
50 | // Fork process | ||
51 | if ((pid = fork()) == 0) { | ||
52 | // Fork child process again | ||
53 | setsid(); | ||
54 | if ((*child = fork()) == 0) { | ||
55 | execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); | ||
56 | // Not reached | ||
57 | } | ||
58 | close(fd[0]); | ||
59 | ssize_t s = 0; | ||
60 | while ((size_t)s < sizeof(pid_t)) { | ||
61 | s += write(fd[1], ((uint8_t *)child) + s, sizeof(pid_t) - s); | ||
62 | } | ||
63 | close(fd[1]); | ||
64 | _exit(0); // Close child process | ||
65 | } else if (pid < 0) { | ||
66 | free(child); | ||
67 | return cmd_results_new(CMD_FAILURE, "exec_always", "fork() failed"); | ||
68 | } | ||
69 | close(fd[1]); // close write | ||
70 | ssize_t s = 0; | ||
71 | while ((size_t)s < sizeof(pid_t)) { | ||
72 | s += read(fd[0], ((uint8_t *)child) + s, sizeof(pid_t) - s); | ||
73 | } | ||
74 | close(fd[0]); | ||
75 | // cleanup child process | ||
76 | wait(0); | ||
77 | if (*child > 0) { | ||
78 | sway_log(L_DEBUG, "Child process created with pid %d", *child); | ||
79 | // TODO: add PID to active workspace | ||
80 | } else { | ||
81 | free(child); | ||
82 | } | ||
83 | |||
84 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
85 | } | ||