summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhinav <abhinav.prsai@gmail.com>2025-06-14 09:46:29 +0100
committerAbhinav <abhinav.prsai@gmail.com>2025-06-14 09:46:29 +0100
commit0660788c28468957cf4bfb50f8343e2efe7e1e3d (patch)
treeeab6b98d0aeb38d5424917c2c669fb6942249050
parent7fb1e0b8f581a433df3e58691d15de982d83968b (diff)
use custom build_argv for non-linux systems
BSD users dont have wordexp so i made a custom splitter for those systems
-rw-r--r--src/parser.c91
1 files changed, 87 insertions, 4 deletions
diff --git a/src/parser.c b/src/parser.c
index 5b8e6f0..3fc2856 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -5,10 +5,11 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#ifdef __linux__
#include <wordexp.h>
+#endif
#include <X11/keysym.h>
#include <X11/Xlib.h>
-
#include "parser.h"
#include "defs.h"
@@ -470,15 +471,75 @@ KeySym parse_keysym(const char *key)
return NoSymbol;
}
+#ifndef __linux__
+static char **split_cmd(const char *cmd, int *out_argc)
+{
+ enum { NORMAL, IN_QUOTE } state = NORMAL;
+ const char *p = cmd;
+ size_t cap = 8, argc = 0, toklen = 0;
+ char *token = malloc(strlen(cmd) + 1);
+ char **argv = malloc(cap * sizeof *argv);
+ if (!token || !argv) {
+ goto err;
+ }
+
+ while (*p) {
+ if (state == NORMAL && isspace((unsigned char)*p)) {
+ if (toklen) {
+ token[toklen] = '\0';
+ if (argc + 1 >= cap) {
+ cap *= 2;
+ argv = realloc(argv, cap * sizeof *argv);
+ if (!argv) {
+ goto err;
+ }
+ }
+ argv[argc++] = strdup(token);
+ toklen = 0;
+ }
+ }
+ else if (*p == '"') {
+ state = (state == NORMAL) ? IN_QUOTE : NORMAL;
+ }
+ else {
+ token[toklen++] = *p;
+ }
+ p++;
+ }
+
+ if (toklen) {
+ token[toklen] = '\0';
+ argv[argc++] = strdup(token);
+ }
+ argv[argc] = NULL;
+ *out_argc = argc;
+ free(token);
+ return argv;
+
+err:
+ if (token) {
+ free(token);
+ }
+ if (argv) {
+ for (size_t i = 0; i < argc; i++) {
+ free(argv[i]);
+ }
+ free(argv);
+ }
+ return NULL;
+}
+#endif
+
const char **build_argv(const char *cmd)
{
+#ifdef __linux__
wordexp_t p;
if (wordexp(cmd, &p, 0) != 0 || p.we_wordc == 0) {
fprintf(stderr, "sxwm: wordexp failed for cmd: '%s'\n", cmd);
return NULL;
}
- const char **argv = malloc((p.we_wordc + 1) * sizeof(char *));
+ const char **argv = malloc((p.we_wordc + 1) * sizeof *argv);
if (!argv) {
wordfree(&p);
return NULL;
@@ -488,7 +549,29 @@ const char **build_argv(const char *cmd)
argv[i] = strdup(p.we_wordv[i]);
}
argv[p.we_wordc] = NULL;
-
wordfree(&p);
return argv;
-}
+#else
+ int argc = 0;
+ char **tmp = split_cmd(cmd, &argc);
+ if (!tmp) {
+ return NULL;
+ }
+
+ const char **argv = malloc((argc + 1) * sizeof *argv);
+ if (!argv) {
+ for (int i = 0; i < argc; i++) {
+ free(tmp[i]);
+ }
+ free(tmp);
+ return NULL;
+ }
+
+ for (int i = 0; i < argc; i++) {
+ argv[i] = tmp[i];
+ }
+ argv[argc] = NULL;
+ free(tmp);
+ return argv;
+#endif
+} \ No newline at end of file