Skip to content

Commit b2915b4

Browse files
DeusDataslvnlrt
andcommitted
Fix cbm_find_cli PATH delimiter and S_IXUSR check on Windows
PATH uses ; on Windows, not : — strtok with : splits C:\Users at the drive letter colon, producing garbage paths. Also skip S_IXUSR check on Windows since stat() doesn't set Unix permission bits. Fixes #159 Co-Authored-By: slvnlrt <slvnlrt@users.noreply.github.com>
1 parent a250ad2 commit b2915b4

File tree

1 file changed

+21
-10
lines changed

1 file changed

+21
-10
lines changed

src/cli/cli.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,24 @@ const char *cbm_detect_shell_rc(const char *home_dir) {
230230

231231
/* ── CLI binary detection ─────────────────────────────────────── */
232232

233+
/* PATH delimiter: `;` on Windows, `:` on POSIX. */
234+
#ifdef _WIN32
235+
#define PATH_DELIM ";"
236+
#else
237+
#define PATH_DELIM ":"
238+
#endif
239+
240+
/* Check if a path exists and is executable.
241+
* On Windows, stat() doesn't set S_IXUSR — just check existence. */
242+
static bool is_executable(const char *path) {
243+
struct stat st;
244+
#ifdef _WIN32
245+
return stat(path, &st) == 0;
246+
#else
247+
return stat(path, &st) == 0 && (st.st_mode & S_IXUSR);
248+
#endif
249+
}
250+
233251
/* Search for an executable named `name` in the PATH environment variable.
234252
* Returns the full path in `out` (max out_sz) if found, else empty string. */
235253
static bool find_in_path(const char *name, char *out, size_t out_sz) {
@@ -238,24 +256,17 @@ static bool find_in_path(const char *name, char *out, size_t out_sz) {
238256
return false;
239257
}
240258
char *saveptr;
241-
char *dir = strtok_r(path_copy, ":", &saveptr);
259+
char *dir = strtok_r(path_copy, PATH_DELIM, &saveptr);
242260
while (dir) {
243261
snprintf(out, out_sz, "%s/%s", dir, name);
244-
struct stat st;
245-
if (stat(out, &st) == 0 && (st.st_mode & S_IXUSR)) {
262+
if (is_executable(out)) {
246263
return true;
247264
}
248-
dir = strtok_r(NULL, ":", &saveptr);
265+
dir = strtok_r(NULL, PATH_DELIM, &saveptr);
249266
}
250267
return false;
251268
}
252269

253-
/* Check if a path exists and is executable. */
254-
static bool is_executable(const char *path) {
255-
struct stat st;
256-
return stat(path, &st) == 0 && (st.st_mode & S_IXUSR);
257-
}
258-
259270
const char *cbm_find_cli(const char *name, const char *home_dir) {
260271
static char buf[CLI_BUF_512];
261272
if (!name || !name[0]) {

0 commit comments

Comments
 (0)