Skip to content

Commit 3658588

Browse files
bingh0DeusData
authored andcommitted
fix(platform): fall back to USERPROFILE when HOME is unset
Add cbm_get_home_dir() in platform.c: tries HOME first, then USERPROFILE (Windows). Replace all 17 raw getenv("HOME") callsites. Fallback from "/tmp" to cbm_tmpdir() for cross-platform temp dir. Cherry-picked from PR #88 by @bingh0. Fixes #77.
1 parent 296a97a commit 3658588

9 files changed

Lines changed: 59 additions & 40 deletions

File tree

src/cli/cli.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "cli/cli.h"
88
#include "foundation/compat.h"
99
#include "foundation/str_util.h"
10+
#include "foundation/platform.h"
1011

1112
// the correct standard headers are included below but clang-tidy doesn't map them.
1213
#include <ctype.h>
@@ -1685,7 +1686,7 @@ unsigned char *cbm_extract_binary_from_targz(const unsigned char *data, int data
16851686
static const char *get_cache_dir(const char *home_dir) {
16861687
static char buf[1024];
16871688
if (!home_dir) {
1688-
home_dir = getenv("HOME");
1689+
home_dir = cbm_get_home_dir();
16891690
}
16901691
if (!home_dir) {
16911692
return NULL;
@@ -1909,10 +1910,9 @@ int cbm_cmd_config(int argc, char **argv) {
19091910
return 0;
19101911
}
19111912

1912-
// NOLINTNEXTLINE(concurrency-mt-unsafe)
1913-
const char *home = getenv("HOME");
1913+
const char *home = cbm_get_home_dir();
19141914
if (!home) {
1915-
fprintf(stderr, "error: HOME not set\n");
1915+
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
19161916
return 1;
19171917
}
19181918

@@ -2140,9 +2140,9 @@ int cbm_cmd_install(int argc, char **argv) {
21402140
}
21412141
}
21422142

2143-
const char *home = getenv("HOME");
2143+
const char *home = cbm_get_home_dir();
21442144
if (!home) {
2145-
fprintf(stderr, "error: HOME not set\n");
2145+
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
21462146
return 1;
21472147
}
21482148

@@ -2448,9 +2448,9 @@ int cbm_cmd_uninstall(int argc, char **argv) {
24482448
}
24492449
}
24502450

2451-
const char *home = getenv("HOME");
2451+
const char *home = cbm_get_home_dir();
24522452
if (!home) {
2453-
fprintf(stderr, "error: HOME not set\n");
2453+
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
24542454
return 1;
24552455
}
24562456

@@ -2671,9 +2671,9 @@ int cbm_cmd_uninstall(int argc, char **argv) {
26712671
int cbm_cmd_update(int argc, char **argv) {
26722672
parse_auto_answer(argc, argv);
26732673

2674-
const char *home = getenv("HOME");
2674+
const char *home = cbm_get_home_dir();
26752675
if (!home) {
2676-
fprintf(stderr, "error: HOME not set\n");
2676+
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
26772677
return 1;
26782678
}
26792679

src/foundation/platform.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,19 @@ int64_t cbm_file_size(const char *path) {
216216
}
217217

218218
#endif /* _WIN32 */
219+
220+
/* ── Home directory (cross-platform) ──────────────────────────── */
221+
222+
const char *cbm_get_home_dir(void) {
223+
// NOLINTNEXTLINE(concurrency-mt-unsafe)
224+
const char *h = getenv("HOME");
225+
if (h && h[0]) {
226+
return h;
227+
}
228+
// NOLINTNEXTLINE(concurrency-mt-unsafe)
229+
h = getenv("USERPROFILE");
230+
if (h && h[0]) {
231+
return h;
232+
}
233+
return NULL;
234+
}

src/foundation/platform.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ cbm_system_info_t cbm_system_info(void);
6464
* initial=false: max(1, perf_cores-1) (leave headroom for user apps) */
6565
int cbm_default_worker_count(bool initial);
6666

67+
/* ── Home directory ─────────────────────────────────────────────── */
68+
69+
/* Cross-platform home directory: tries HOME first, then USERPROFILE (Windows).
70+
* Returns NULL when neither is set. */
71+
const char *cbm_get_home_dir(void);
72+
6773
/* ── File system ───────────────────────────────────────────────── */
6874

6975
/* Check if a path exists. */

src/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "store/store.h"
2020
#include "cli/cli.h"
2121
#include "foundation/log.h"
22+
#include "foundation/platform.h"
2223
#include "foundation/compat_thread.h"
2324
#include "foundation/mem.h"
2425
#include "ui/config.h"
@@ -221,7 +222,7 @@ int main(int argc, char **argv) {
221222

222223
/* Open config store for runtime settings */
223224
char config_dir[1024];
224-
const char *cfg_home = getenv("HOME");
225+
const char *cfg_home = cbm_get_home_dir();
225226
cbm_config_t *runtime_config = NULL;
226227
if (cfg_home) {
227228
snprintf(config_dir, sizeof(config_dir), "%s/.cache/codebase-memory-mcp", cfg_home);

src/mcp/mcp.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -607,10 +607,9 @@ bool cbm_mcp_server_has_cached_store(cbm_mcp_server_t *srv) {
607607
/* Returns the platform cache directory: ~/.cache/codebase-memory-mcp
608608
* Writes to buf, returns buf for convenience. */
609609
static const char *cache_dir(char *buf, size_t bufsz) {
610-
// NOLINTNEXTLINE(concurrency-mt-unsafe)
611-
const char *home = getenv("HOME");
610+
const char *home = cbm_get_home_dir();
612611
if (!home) {
613-
home = "/tmp";
612+
home = cbm_tmpdir();
614613
}
615614
snprintf(buf, bufsz, "%s/.cache/codebase-memory-mcp", home);
616615
return buf;
@@ -2552,8 +2551,7 @@ static void detect_session(cbm_mcp_server_t *srv) {
25522551
/* 1. Try CWD */
25532552
char cwd[1024];
25542553
if (getcwd(cwd, sizeof(cwd)) != NULL) {
2555-
// NOLINTNEXTLINE(concurrency-mt-unsafe)
2556-
const char *home = getenv("HOME");
2554+
const char *home = cbm_get_home_dir();
25572555
/* Skip useless roots: / and $HOME */
25582556
if (strcmp(cwd, "/") != 0 && (home == NULL || strcmp(cwd, home) != 0)) {
25592557
snprintf(srv->session_root, sizeof(srv->session_root), "%s", cwd);
@@ -2624,8 +2622,7 @@ static void maybe_auto_index(cbm_mcp_server_t *srv) {
26242622
}
26252623

26262624
/* Check if project already has a DB */
2627-
// NOLINTNEXTLINE(concurrency-mt-unsafe)
2628-
const char *home = getenv("HOME");
2625+
const char *home = cbm_get_home_dir();
26292626
if (home) {
26302627
char db_check[1024];
26312628
snprintf(db_check, sizeof(db_check), "%s/.cache/codebase-memory-mcp/%s.db", home,

src/pipeline/pipeline.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,9 @@ static char *resolve_db_path(const cbm_pipeline_t *p) {
137137
if (p->db_path) {
138138
snprintf(path, 1024, "%s", p->db_path);
139139
} else {
140-
// NOLINTNEXTLINE(concurrency-mt-unsafe)
141-
const char *home = getenv("HOME");
140+
const char *home = cbm_get_home_dir();
142141
if (!home) {
143-
home = "/tmp";
142+
home = cbm_tmpdir();
144143
}
145144
snprintf(path, 1024, "%s/.cache/codebase-memory-mcp/%s.db", home, p->project_name);
146145
}
@@ -721,14 +720,13 @@ int cbm_pipeline_run(cbm_pipeline_t *p) {
721720
if (!check_cancel(p)) {
722721
cbm_clock_gettime(CLOCK_MONOTONIC, &t);
723722

724-
// NOLINTNEXTLINE(concurrency-mt-unsafe) — called once during single-threaded dump
725-
const char *home = getenv("HOME");
723+
const char *home = cbm_get_home_dir();
726724
char db_path[1024];
727725
if (p->db_path) {
728726
snprintf(db_path, sizeof(db_path), "%s", p->db_path);
729727
} else {
730728
if (!home) {
731-
home = "/tmp";
729+
home = cbm_tmpdir();
732730
}
733731
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home,
734732
p->project_name);

src/store/store.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,9 @@ cbm_store_t *cbm_store_open(const char *project) {
370370
return NULL;
371371
}
372372
/* Build path: ~/.cache/codebase-memory-mcp/<project>.db */
373-
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe) — called once during
374-
// single-threaded store open, never concurrently
373+
const char *home = cbm_get_home_dir();
375374
if (!home) {
376-
home = "/tmp";
375+
home = cbm_tmpdir();
377376
}
378377
char path[1024];
379378
snprintf(path, sizeof(path), "%s/.cache/codebase-memory-mcp/%s.db", home, project);

src/ui/config.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
*/
77
#include "ui/config.h"
88
#include "foundation/log.h"
9+
#include "foundation/platform.h"
910
#include "foundation/compat_fs.h"
11+
#include "foundation/compat.h"
1012

1113
#include <yyjson/yyjson.h>
1214

@@ -17,9 +19,9 @@
1719
/* ── Path ────────────────────────────────────────────────────── */
1820

1921
void cbm_ui_config_path(char *buf, int bufsz) {
20-
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
22+
const char *home = cbm_get_home_dir();
2123
if (!home) {
22-
home = "/tmp";
24+
home = cbm_tmpdir();
2325
}
2426
snprintf(buf, (size_t)bufsz, "%s/.cache/codebase-memory-mcp/config.json", home);
2527
}

src/ui/http_server.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ static void handle_browse(struct mg_connection *c, struct mg_http_message *hm) {
377377
char path[1024] = {0};
378378
if (!get_query_param(hm->query, "path", path, (int)sizeof(path)) || path[0] == '\0') {
379379
/* Default to home directory */
380-
const char *home = getenv("HOME");
380+
const char *home = cbm_get_home_dir();
381381
if (home)
382382
snprintf(path, sizeof(path), "%s", home);
383383
else
@@ -452,9 +452,9 @@ static void handle_adr_get(struct mg_connection *c, struct mg_http_message *hm)
452452
return;
453453
}
454454

455-
const char *home = getenv("HOME");
455+
const char *home = cbm_get_home_dir();
456456
if (!home)
457-
home = "/tmp";
457+
home = cbm_tmpdir();
458458
char db_path[1024];
459459
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, name);
460460

@@ -545,9 +545,9 @@ static void handle_adr_save(struct mg_connection *c, struct mg_http_message *hm)
545545
const char *proj = yyjson_get_str(v_proj);
546546
const char *content = yyjson_get_str(v_content);
547547

548-
const char *home = getenv("HOME");
548+
const char *home = cbm_get_home_dir();
549549
if (!home)
550-
home = "/tmp";
550+
home = cbm_tmpdir();
551551
char db_path[1024];
552552
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, proj);
553553

@@ -832,9 +832,9 @@ static void handle_delete_project(struct mg_connection *c, struct mg_http_messag
832832
return;
833833
}
834834

835-
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
835+
const char *home = cbm_get_home_dir();
836836
if (!home)
837-
home = "/tmp";
837+
home = cbm_tmpdir();
838838
char db_path[1024];
839839
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, name);
840840

@@ -870,9 +870,9 @@ static void handle_project_health(struct mg_connection *c, struct mg_http_messag
870870
return;
871871
}
872872

873-
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
873+
const char *home = cbm_get_home_dir();
874874
if (!home)
875-
home = "/tmp";
875+
home = cbm_tmpdir();
876876
char db_path[1024];
877877
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, name);
878878

@@ -928,9 +928,9 @@ static void handle_layout(struct mg_connection *c, struct mg_http_message *hm) {
928928
}
929929

930930
/* Open a read-only store for this project */
931-
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
931+
const char *home = cbm_get_home_dir();
932932
if (!home)
933-
home = "/tmp";
933+
home = cbm_tmpdir();
934934
char db_path[1024];
935935
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, project);
936936

0 commit comments

Comments
 (0)