5dbbab7bdc
When we have type safety we'll need to have functions for workspace_add_tiling and so on. This means the existing container functions will be just for containers, so they are being moved to container.c. At this point layout.c doesn't contain much else, so I've relocated everything and removed the file. * container_swap and its static functions have been moved to the swap command and made static. * container_recursive_resize has been moved to the resize command and made static. * The following have been moved to container.c: * container_handle_fullscreen_reparent * container_insert_child * container_add_sibling * container_add_child * container_remove_child * container_replace_child * container_split * enum movement_direction and sway_dir_to_wlr have been moved to util.c. Side note: Several commands included layout.h which then included root.h. With layout.h gone, root.h has to be included by those commands.
99 lines
2.4 KiB
C
99 lines
2.4 KiB
C
#define _XOPEN_SOURCE 500
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include "sway/commands.h"
|
|
#include "sway/config.h"
|
|
#include "sway/tree/container.h"
|
|
#include "sway/tree/root.h"
|
|
#include "sway/tree/workspace.h"
|
|
#include "log.h"
|
|
#include "stringop.h"
|
|
|
|
struct cmd_results *cmd_exec_always(int argc, char **argv) {
|
|
struct cmd_results *error = NULL;
|
|
if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL);
|
|
if ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) {
|
|
return error;
|
|
}
|
|
|
|
char *tmp = NULL;
|
|
if (strcmp((char*)*argv, "--no-startup-id") == 0) {
|
|
wlr_log(WLR_INFO, "exec switch '--no-startup-id' not supported, ignored.");
|
|
if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) {
|
|
return error;
|
|
}
|
|
|
|
--argc; ++argv;
|
|
}
|
|
|
|
if (argv[0][0] == '\'' || argv[0][0] == '"') {
|
|
if (argc > 0) {
|
|
return cmd_results_new(CMD_INVALID, "exec_always",
|
|
"command cannot be partially quoted");
|
|
}
|
|
tmp = strdup(argv[0]);
|
|
strip_quotes(tmp);
|
|
} else {
|
|
tmp = join_args(argv, argc);
|
|
}
|
|
|
|
// Put argument into cmd array
|
|
char cmd[4096];
|
|
strncpy(cmd, tmp, sizeof(cmd) - 1);
|
|
cmd[sizeof(cmd) - 1] = 0;
|
|
free(tmp);
|
|
wlr_log(WLR_DEBUG, "Executing %s", cmd);
|
|
|
|
int fd[2];
|
|
if (pipe(fd) != 0) {
|
|
wlr_log(WLR_ERROR, "Unable to create pipe for fork");
|
|
}
|
|
|
|
pid_t pid, child;
|
|
// Fork process
|
|
if ((pid = fork()) == 0) {
|
|
// Fork child process again
|
|
setsid();
|
|
sigset_t set;
|
|
sigemptyset(&set);
|
|
sigprocmask(SIG_SETMASK, &set, NULL);
|
|
close(fd[0]);
|
|
if ((child = fork()) == 0) {
|
|
close(fd[1]);
|
|
execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL);
|
|
_exit(0);
|
|
}
|
|
ssize_t s = 0;
|
|
while ((size_t)s < sizeof(pid_t)) {
|
|
s += write(fd[1], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
|
}
|
|
close(fd[1]);
|
|
_exit(0); // Close child process
|
|
} else if (pid < 0) {
|
|
close(fd[0]);
|
|
close(fd[1]);
|
|
return cmd_results_new(CMD_FAILURE, "exec_always", "fork() failed");
|
|
}
|
|
close(fd[1]); // close write
|
|
ssize_t s = 0;
|
|
while ((size_t)s < sizeof(pid_t)) {
|
|
s += read(fd[0], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
|
}
|
|
close(fd[0]);
|
|
// cleanup child process
|
|
waitpid(pid, NULL, 0);
|
|
if (child > 0) {
|
|
wlr_log(WLR_DEBUG, "Child process created with pid %d", child);
|
|
root_record_workspace_pid(child);
|
|
} else {
|
|
return cmd_results_new(CMD_FAILURE, "exec_always",
|
|
"Second fork() failed");
|
|
}
|
|
|
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
|
}
|