https://gitlab.synchro.net/main/sbbs/-/merge_requests/717#note_9871
HUMAN EDIT: Claude wanted to post a comment, I let it get wordy, I probably should have told it to just say "updated"
Updated in aa91f0f40c — the command line is now `?../xtrn/hermedit/HERMedIT.js %f`.
You're right about the working directory, and it's a better fit than `%!` for the reason you gave: `main.cpp` chdir's to the ctrl directory at startup, so the requirement drops from "exec and xtrn share a parent" to "ctrl and xtrn share a parent". Same default tree, one less assumption.
On the extension though — I think it does matter once there's a path separator in the command. In `js_execfile()` (`src/sbbs3/exec.cpp`, ~line 578) the `.js` is only appended on the no-separator branch:
```c
if (strcspn(fname, "/\\") == strlen(fname)) {
const char* js_ext = "";
if (getfext(fname) == NULL)
js_ext = ".js";
... /* startup_dir, then mods_dir, then exec_dir */
} else
SAFECOPY(path, fname); /* verbatim — nothing appended */
if (!fexistcase(path)) {
errormsg(WHERE, ERR_OPEN, path, O_RDONLY);
return -1;
}
```
So for `?../xtrn/hermedit/hermedit`, `exec_bin()` does find the file — its `p == NULL` branch resolves `startup_dir + mod + ".js"` — but it then calls `js_execfile()` with the original extensionless cmdline, which takes the `else` branch and fails its own `fexistcase()`.
Tested both under jsexec from the ctrl directory:
```
$ jsexec ../xtrn/hermedit/HERMedIT.js
!Module (../xtrn/hermedit/HERMedIT.js) set exit_code: 1 <- loaded
$ jsexec ../xtrn/hermedit/hermedit
!Module file (../xtrn/hermedit/hermedit) doesn't exist
```
Keeping `.js` since you noted it doesn't hurt either way. If you'd rather the extensionless form work for path-style commands, appending `js_ext` on the `else` branch too would do it — happy to send that as a separate MR if it's wanted.
---
ï¿ Synchronet ï¿ Vertrauen ï¿ Home of Synchronet ï¿ [vert/cvs/bbs].synchro.net