summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAbhinav Prasai <72694427+uint23@users.noreply.github.com>2025-06-24 17:04:22 +0100
committerGitHub <noreply@github.com>2025-06-24 17:04:22 +0100
commita05a81b1f07022071f939d097629ea5cc5b89871 (patch)
treed01534e9a2882d14b9b860709f8918480b2bf461 /src
parentca52808cf5d1928a9a8f263c4c3210e83d80391c (diff)
parent6fd11314394ea055286b9c6ca0010b4378b76c4a (diff)
Merge pull request #104 from elbachir-one/main
Fix(spawn): support multiple piped commands
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)