aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/exec_always.c
diff options
context:
space:
mode:
authorLibravatar Zandr Martin <zandrmartin@gmail.com>2016-09-01 21:39:08 -0500
committerLibravatar Zandr Martin <zandrmartin@gmail.com>2016-09-01 21:39:08 -0500
commitb374c35758777f98e5ddbe4b0dc43bd7c80f36d7 (patch)
tree04bb4cfc3da7d2e0de7fbc38db42f65c66d2df4c /sway/commands/exec_always.c
parentMerge pull request #874 from yohanesu75/ipc-client-fix (diff)
downloadsway-b374c35758777f98e5ddbe4b0dc43bd7c80f36d7.tar.gz
sway-b374c35758777f98e5ddbe4b0dc43bd7c80f36d7.tar.zst
sway-b374c35758777f98e5ddbe4b0dc43bd7c80f36d7.zip
refactor commands.c
Diffstat (limited to 'sway/commands/exec_always.c')
-rw-r--r--sway/commands/exec_always.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c
new file mode 100644
index 00000000..dbac9f9a
--- /dev/null
+++ b/sway/commands/exec_always.c
@@ -0,0 +1,83 @@
1#include <string.h>
2#include <sys/wait.h>
3#include <unistd.h>
4#include "commands.h"
5#include "config.h"
6#include "log.h"
7#include "stringop.h"
8
9struct cmd_results *cmd_exec_always(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL);
12 if ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) {
13 return error;
14 }
15
16 char *tmp = NULL;
17 if (strcmp((char*)*argv, "--no-startup-id") == 0) {
18 sway_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored.");
19 if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) {
20 return error;
21 }
22
23 tmp = join_args(argv + 1, argc - 1);
24 } else {
25 tmp = join_args(argv, argc);
26 }
27
28 // Put argument into cmd array
29 char cmd[4096];
30 strncpy(cmd, tmp, sizeof(cmd));
31 cmd[sizeof(cmd) - 1] = 0;
32 free(tmp);
33 sway_log(L_DEBUG, "Executing %s", cmd);
34
35 int fd[2];
36 if (pipe(fd) != 0) {
37 sway_log(L_ERROR, "Unable to create pipe for fork");
38 }
39
40 pid_t pid;
41 pid_t *child = malloc(sizeof(pid_t)); // malloc'd so that Linux can avoid copying the process space
42 // Fork process
43 if ((pid = fork()) == 0) {
44 // Fork child process again
45 setsid();
46 if ((*child = fork()) == 0) {
47 execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL);
48 /* Not reached */
49 }
50 close(fd[0]);
51 ssize_t s = 0;
52 while ((size_t)s < sizeof(pid_t)) {
53 s += write(fd[1], ((uint8_t *)child) + s, sizeof(pid_t) - s);
54 }
55 close(fd[1]);
56 _exit(0); // Close child process
57 } else if (pid < 0) {
58 free(child);
59 return cmd_results_new(CMD_FAILURE, "exec_always", "Command failed (sway could not fork).");
60 }
61 close(fd[1]); // close write
62 ssize_t s = 0;
63 while ((size_t)s < sizeof(pid_t)) {
64 s += read(fd[0], ((uint8_t *)child) + s, sizeof(pid_t) - s);
65 }
66 close(fd[0]);
67 // cleanup child process
68 wait(0);
69 swayc_t *ws = swayc_active_workspace();
70 if (*child > 0 && ws) {
71 sway_log(L_DEBUG, "Child process created with pid %d for workspace %s", *child, ws->name);
72 struct pid_workspace *pw = malloc(sizeof(struct pid_workspace));
73 pw->pid = child;
74 pw->workspace = strdup(ws->name);
75 pid_workspace_add(pw);
76 // TODO: keep track of this pid and open the corresponding view on the current workspace
77 // blocked pending feature in wlc
78 } else {
79 free(child);
80 }
81
82 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
83}