summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/sxwm.c126
1 files changed, 88 insertions, 38 deletions
diff --git a/src/sxwm.c b/src/sxwm.c
index b1ce613..7c789de 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -2130,56 +2130,106 @@ int snap_coordinate(int pos, int size, int screen_size, int snap_dist)
void spawn(const char **argv)
{
- int pipe_idx = -1;
- for (int i = 0; argv[i]; i++) {
+ int argc = 0;
+ while (argv[argc])
+ argc++;
+
+ int cmd_count = 1;
+ for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "|") == 0) {
- pipe_idx = i;
- break;
+ cmd_count++;
}
}
- if (pipe_idx < 0) {
- if (fork() == 0) {
- close(ConnectionNumber(dpy));
- setsid();
- execvp(argv[0], (char *const *)argv);
- fprintf(stderr, "sxwm: execvp '%s' failed\n", argv[0]);
- exit(EXIT_FAILURE);
+ char ***commands = malloc(cmd_count * sizeof(char **));
+ if (!commands) {
+ perror("malloc commands");
+ return;
+ }
+
+ int cmd_idx = 0;
+ int arg_start = 0;
+ for (int i = 0; i <= argc; i++) {
+ if (!argv[i] || strcmp(argv[i], "|") == 0) {
+ int len = i - arg_start;
+ char **cmd_args = malloc((len + 1) * sizeof(char *));
+ if (!cmd_args) {
+ perror("malloc cmd_args");
+ for (int j = 0; j < cmd_idx; j++) {
+ free(commands[j]);
+ }
+ free(commands);
+ return;
+ }
+ for (int j = 0; j < len; j++) {
+ cmd_args[j] = (char *)argv[arg_start + j];
+ }
+ cmd_args[len] = NULL;
+ commands[cmd_idx++] = cmd_args;
+ arg_start = i + 1;
}
}
- else {
- ((char **)argv)[pipe_idx] = NULL;
- const char **left = argv;
- const char **right = argv + pipe_idx + 1;
- int fd[2];
- Bool x = pipe(fd);
- (void)x;
-
- pid_t pid1 = fork();
- if (pid1 == 0) {
- dup2(fd[1], STDOUT_FILENO);
- close(fd[0]);
- close(fd[1]);
- execvp(left[0], (char *const *)left);
- perror("spawn left");
- exit(EXIT_FAILURE);
+
+ int pipes[cmd_count - 1][2];
+ for (int i = 0; i < cmd_count - 1; i++) {
+ if (pipe(pipes[i]) == -1) {
+ perror("pipe");
+ for (int j = 0; j < cmd_count; j++) {
+ free(commands[j]);
+ }
+ free(commands);
+ return;
}
+ }
- pid_t pid2 = fork();
- if (pid2 == 0) {
- dup2(fd[0], STDIN_FILENO);
- close(fd[0]);
- close(fd[1]);
- execvp(right[0], (char *const *)right);
- perror("spawn right");
+ for (int i = 0; i < cmd_count; i++) {
+ pid_t pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ for (int k = 0; k < cmd_count - 1; k++) {
+ close(pipes[k][0]);
+ close(pipes[k][1]);
+ }
+ for (int j = 0; j < cmd_count; j++) {
+ free(commands[j]);
+ }
+ free(commands);
+ return;
+ }
+ if (pid == 0) {
+ close(ConnectionNumber(dpy));
+
+ if (i > 0) {
+ dup2(pipes[i - 1][0], STDIN_FILENO);
+ }
+ if (i < cmd_count - 1) {
+ dup2(pipes[i][1], STDOUT_FILENO);
+ }
+
+ for (int k = 0; k < cmd_count - 1; k++) {
+ close(pipes[k][0]);
+ close(pipes[k][1]);
+ }
+
+ execvp(commands[i][0], commands[i]);
+ fprintf(stderr, "sxwm: execvp '%s' failed\n", commands[i][0]);
exit(EXIT_FAILURE);
}
+ }
+
+ for (int i = 0; i < cmd_count - 1; i++) {
+ close(pipes[i][0]);
+ close(pipes[i][1]);
+ }
+
+ for (int i = 0; i < cmd_count; i++) {
+ wait(NULL);
+ }
- close(fd[0]);
- close(fd[1]);
- waitpid(pid1, NULL, 0);
- waitpid(pid2, NULL, 0);
+ for (int i = 0; i < cmd_count; i++) {
+ free(commands[i]);
}
+ free(commands);
}
void tile(void)