aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/exec_always.c
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2017-12-04 22:43:49 +0100
committerLibravatar emersion <contact@emersion.fr>2017-12-04 22:43:49 +0100
commit514c819ff98d72880c5b7e0beb7bd9ca866bc1ad (patch)
treed2ddf512ebc46ea2c93c7a487cdf758c84e3d0bd /sway/commands/exec_always.c
parentMerge pull request #1494 from acrisci/feature/xwayland (diff)
downloadsway-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.c85
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
13struct 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}